1 /* VSTORE.H     (c) Copyright Roger Bowler, 1999-2011                */
2 /*              ESA/390 Virtual Storage Functions                    */
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 contains various functions which store, fetch, and    */
9 /* copy values to, from, or between virtual storage locations.       */
10 /*                                                                   */
11 /* Functions provided in this module are:                            */
12 /* vstorec      Store 1 to 256 characters into virtual storage       */
13 /* vstoreb      Store a single byte into virtual storage             */
14 /* vstore2      Store a two-byte integer into virtual storage        */
15 /* vstore4      Store a four-byte integer into virtual storage       */
16 /* vstore8      Store an eight-byte integer into virtual storage     */
17 /* vfetchc      Fetch 1 to 256 characters from virtual storage       */
18 /* vfetchb      Fetch a single byte from virtual storage             */
19 /* vfetch2      Fetch a two-byte integer from virtual storage        */
20 /* vfetch4      Fetch a four-byte integer from virtual storage       */
21 /* vfetch8      Fetch an eight-byte integer from virtual storage     */
22 /* instfetch    Fetch instruction from virtual storage               */
23 /* move_chars   Move characters using specified keys and addrspaces  */
24 /* move_charx   Move characters with optional specifications         */
25 /* validate_operand   Validate addressing, protection, translation   */
26 /*-------------------------------------------------------------------*/
27 /* And provided by means of macro's address wrapping versions of     */
28 /* the above:                                                        */
29 /* wstoreX                                                           */
30 /* wfetchX                                                           */
31 /* wmove_chars                                                       */
32 /* wvalidate_operand                                                 */
33 /*-------------------------------------------------------------------*/
34 
35 #define s370_wstorec(_src, _len, _addr, _arn, _regs) \
36         s370_vstorec((_src), (_len), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
37 #define s370_wstoreb(_value, _addr, _arn, _regs) \
38         s370_vstoreb((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
39 #define s370_wstore2(_value, _addr, _arn, _regs) \
40         s370_vstore2((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
41 #define s370_wstore4(_value, _addr, _arn, _regs) \
42         s370_vstore4((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
43 #define s370_wstore8(_value, _addr, _arn, _regs) \
44         s370_vstore8((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
45 #define s370_wfetchc(_dest, _len, _addr, _arn, _regs) \
46         s370_vfetchc((_dest), (_len), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
47 #define s370_wfetchb(_addr, _arn, _regs) \
48         s370_vfetchb(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
49 #define s370_wfetch2(_addr, _arn, _regs) \
50         s370_vfetch2(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
51 #define s370_wfetch4(_addr, _arn, _regs) \
52         s370_vfetch4(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
53 #define s370_wfetch8(_addr, _arn, _regs) \
54         s370_vfetch8(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
55 #define s370_wmove_chars(_addr1, _arn1, _key1, _addr2, _arn2, _key2, _len, _regs) \
56         s370_move_chars(((_addr1) & ADDRESS_MAXWRAP((_regs))), (_arn1), (_key1), \
57                         ((_addr2) & ADDRESS_MAXWRAP((_regs))), (_arn2), (_key2), (_len), (_regs))
58 #define s370_wvalidate_operand(_addr, _arn, _len, _acctype, _regs) \
59         s370_validate_operand(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_len), (_acctype), (_regs))
60 
61 #define s390_wstorec(_src, _len, _addr, _arn, _regs) \
62         s390_vstorec((_src), (_len), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
63 #define s390_wstoreb(_value, _addr, _arn, _regs) \
64         s390_vstoreb((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
65 #define s390_wstore2(_value, _addr, _arn, _regs) \
66         s390_vstore2((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
67 #define s390_wstore4(_value, _addr, _arn, _regs) \
68         s390_vstore4((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
69 #define s390_wstore8(_value, _addr, _arn, _regs) \
70         s390_vstore8((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
71 #define s390_wfetchc(_dest, _len, _addr, _arn, _regs) \
72         s390_vfetchc((_dest), (_len), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
73 #define s390_wfetchb(_addr, _arn, _regs) \
74         s390_vfetchb(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
75 #define s390_wfetch2(_addr, _arn, _regs) \
76         s390_vfetch2(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
77 #define s390_wfetch4(_addr, _arn, _regs) \
78         s390_vfetch4(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
79 #define s390_wfetch8(_addr, _arn, _regs) \
80         s390_vfetch8(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
81 #define s390_wmove_chars(_addr1, _arn1, _key1, _addr2, _arn2, _key2, _len, _regs) \
82         s390_move_chars(((_addr1) & ADDRESS_MAXWRAP((_regs))), (_arn1), (_key1), \
83                         ((_addr2) & ADDRESS_MAXWRAP((_regs))), (_arn2), (_key2), (_len), (_regs))
84 #define s390_wvalidate_operand(_addr, _arn, _len, _acctype, _regs) \
85         s390_validate_operand(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_len), (_acctype), (_regs))
86 
87 #define z900_wstorec(_src, _len, _addr, _arn, _regs) \
88         z900_vstorec((_src), (_len), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
89 #define z900_wstoreb(_value, _addr, _arn, _regs) \
90         z900_vstoreb((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
91 #define z900_wstore2(_value, _addr, _arn, _regs) \
92         z900_vstore2((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
93 #define z900_wstore4(_value, _addr, _arn, _regs) \
94         z900_vstore4((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
95 #define z900_wstore8(_value, _addr, _arn, _regs) \
96         z900_vstore8((_value), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
97 #define z900_wfetchc(_dest, _len, _addr, _arn, _regs) \
98         z900_vfetchc((_dest), (_len), ((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
99 #define z900_wfetchb(_addr, _arn, _regs) \
100         z900_vfetchb(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
101 #define z900_wfetch2(_addr, _arn, _regs) \
102         z900_vfetch2(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
103 #define z900_wfetch4(_addr, _arn, _regs) \
104         z900_vfetch4(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
105 #define z900_wfetch8(_addr, _arn, _regs) \
106         z900_vfetch8(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_regs))
107 #define z900_wmove_chars(_addr1, _arn1, _key1, _addr2, _arn2, _key2, _len, _regs) \
108         z900_move_chars(((_addr1) & ADDRESS_MAXWRAP((_regs))), (_arn1), (_key1), \
109                         ((_addr2) & ADDRESS_MAXWRAP((_regs))), (_arn2), (_key2), (_len), (_regs))
110 #define z900_wvalidate_operand(_addr, _arn, _len, _acctype, _regs) \
111         z900_validate_operand(((_addr) & ADDRESS_MAXWRAP((_regs))), (_arn), (_len), (_acctype), (_regs))
112 
113 /*-------------------------------------------------------------------*/
114 /*              Operand Length Checking Macros                       */
115 /*                                                                   */
116 /* The following macros are used to determine whether an operand     */
117 /* storage access will cross a 2K page boundary or not.              */
118 /*                                                                   */
119 /* The first 'plain' pair of macros (without the 'L') are used for   */
120 /* 0-based lengths wherein zero = 1 byte is being referenced and 255 */
121 /* means 256 bytes are being referenced. They are obviously designed */
122 /* for maximum length values of 0-255 as used w/MVC instructions.    */
123 /*                                                                   */
124 /* The second pair of 'L' macros are using for 1-based lengths where */
125 /* 0 = no bytes are being referenced, 1 = one byte, etc. They are    */
126 /* designed for 'Large' maximum length values such as occur with the */
127 /* MVCL instruction for example (where the length can be up to 16MB) */
128 /*-------------------------------------------------------------------*/
129 
130 #define NOCROSS2K(_addr,_len) likely( ( (int)((_addr) & 0x7FF)) <= ( 0x7FF - (_len) ) )
131 #define CROSS2K(_addr,_len) unlikely( ( (int)((_addr) & 0x7FF)) > ( 0x7FF - (_len) ) )
132 
133 #define NOCROSS2KL(_addr,_len) likely( ( (int)((_addr) & 0x7FF)) <= ( 0x800 - (_len) ) )
134 #define CROSS2KL(_addr,_len) unlikely( ( (int)((_addr) & 0x7FF)) > ( 0x800 - (_len) ) )
135 
136 #if !defined(OPTION_NO_INLINE_VSTORE) || defined(_VSTORE_C)
137 
138 /*-------------------------------------------------------------------*/
139 /* Store 1 to 256 characters into virtual storage operand            */
140 /*                                                                   */
141 /* Input:                                                            */
142 /*      src     1 to 256 byte input buffer                           */
143 /*      len     Size of operand minus 1                              */
144 /*      addr    Logical address of leftmost character of operand     */
145 /*      arn     Access register number                               */
146 /*      regs    CPU register context                                 */
147 /*                                                                   */
148 /*      A program check may be generated if the logical address      */
149 /*      range causes an addressing, translation, or protection       */
150 /*      exception, and in this case no real storage locations are    */
151 /*      updated, and the function does not return.                   */
152 /*-------------------------------------------------------------------*/
ARCH_DEP(vstorec)153 _VSTORE_C_STATIC void ARCH_DEP(vstorec) (void *src, BYTE len,
154                                         VADR addr, int arn, REGS *regs)
155 {
156 BYTE   *main1, *main2;                  /* Mainstor addresses        */
157 BYTE   *sk;                             /* Storage key addresses     */
158 int     len2;                           /* Length to end of page     */
159 
160     if ( NOCROSS2K(addr,len) )
161     {
162         memcpy(MADDRL(addr, len+1, arn, regs, ACCTYPE_WRITE, regs->psw.pkey),
163                src, len + 1);
164         ITIMER_UPDATE(addr,len,regs);
165     }
166     else
167     {
168         len2 = 0x800 - (addr & 0x7FF);
169         main1 = MADDRL(addr, len2, arn, regs, ACCTYPE_WRITE_SKP,
170                       regs->psw.pkey);
171         sk = regs->dat.storkey;
172         main2 = MADDRL((addr + len2) & ADDRESS_MAXWRAP(regs),
173                       len+1-len2, arn,
174                       regs, ACCTYPE_WRITE, regs->psw.pkey);
175         *sk |= (STORKEY_REF | STORKEY_CHANGE);
176         memcpy (main1, src, len2);
177         memcpy (main2, (BYTE*)src + len2, len + 1 - len2);
178     }
179 
180 } /* end function ARCH_DEP(vstorec) */
181 
182 /*-------------------------------------------------------------------*/
183 /* Store a single byte into virtual storage operand                  */
184 /*                                                                   */
185 /* Input:                                                            */
186 /*      value   Byte value to be stored                              */
187 /*      addr    Logical address of operand byte                      */
188 /*      arn     Access register number                               */
189 /*      regs    CPU register context                                 */
190 /*                                                                   */
191 /*      A program check may be generated if the logical address      */
192 /*      causes an addressing, translation, or protection             */
193 /*      exception, and in this case the function does not return.    */
194 /*-------------------------------------------------------------------*/
ARCH_DEP(vstoreb)195 _VSTORE_C_STATIC void ARCH_DEP(vstoreb) (BYTE value, VADR addr,
196                                          int arn, REGS *regs)
197 {
198 BYTE   *main1;                          /* Mainstor address          */
199 
200     main1 = MADDR(addr, arn, regs, ACCTYPE_WRITE, regs->psw.pkey);
201     *main1 = value;
202     ITIMER_UPDATE(addr,1-1,regs);
203 
204 } /* end function ARCH_DEP(vstoreb) */
205 
206 /*-------------------------------------------------------------------*/
207 /* Store a two-byte integer into virtual storage operand             */
208 /*                                                                   */
209 /* Input:                                                            */
210 /*      value   16-bit integer value to be stored                    */
211 /*      addr    Logical address of leftmost operand byte             */
212 /*      arn     Access register number                               */
213 /*      regs    CPU register context                                 */
214 /*                                                                   */
215 /*      A program check may be generated if the logical address      */
216 /*      causes an addressing, translation, or protection             */
217 /*      exception, and in this case the function does not return.    */
218 /*-------------------------------------------------------------------*/
ARCH_DEP(vstore2_full)219 _VSTORE_FULL_C_STATIC void ARCH_DEP(vstore2_full)(U16 value, VADR addr,
220                                               int arn, REGS *regs)
221 {
222 BYTE   *main1, *main2;                  /* Mainstor addresses        */
223 BYTE   *sk;                             /* Storage key addresses     */
224 
225     main1 = MADDR(addr, arn, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey);
226     sk = regs->dat.storkey;
227     main2 = MADDR((addr + 1) & ADDRESS_MAXWRAP(regs), arn, regs,
228                   ACCTYPE_WRITE, regs->psw.pkey);
229     *sk |= (STORKEY_REF | STORKEY_CHANGE);
230     *main1 = value >> 8;
231     *main2 = value & 0xFF;
232 
233 } /* end function ARCH_DEP(vstore2_full) */
234 
235 /* vstore2 accelerator - Simple case only (better inline candidate) */
ARCH_DEP(vstore2)236 _VSTORE_C_STATIC void ARCH_DEP(vstore2) (U16 value, VADR addr, int arn,
237                                                             REGS *regs)
238 {
239     /* Most common case : Aligned & not crossing page boundary */
240     if (likely(!((VADR_L)addr & 1) || ((VADR_L)addr & 0x7FF) != 0x7FF))
241     {
242         BYTE *mn;
243         mn = MADDRL (addr, 2, arn, regs, ACCTYPE_WRITE, regs->psw.pkey);
244         STORE_HW(mn, value);
245         ITIMER_UPDATE(addr,2-1,regs);
246     }
247     else
248         ARCH_DEP(vstore2_full)(value, addr, arn, regs);
249 } /* end function ARCH_DEP(vstore2) */
250 
251 /*-------------------------------------------------------------------*/
252 /* Store a four-byte integer into virtual storage operand            */
253 /*                                                                   */
254 /* Input:                                                            */
255 /*      value   32-bit integer value to be stored                    */
256 /*      addr    Logical address of leftmost operand byte             */
257 /*      arn     Access register number                               */
258 /*      regs    CPU register context                                 */
259 /*                                                                   */
260 /*      A program check may be generated if the logical address      */
261 /*      causes an addressing, translation, or protection             */
262 /*      exception, and in this case the function does not return.    */
263 /*-------------------------------------------------------------------*/
ARCH_DEP(vstore4_full)264 _VSTORE_FULL_C_STATIC void ARCH_DEP(vstore4_full)(U32 value, VADR addr,
265                                               int arn, REGS *regs)
266 {
267 BYTE   *main1, *main2;                  /* Mainstor addresses        */
268 BYTE   *sk;                             /* Storage key addresses     */
269 int     len;                            /* Length to end of page     */
270 BYTE    temp[4];                        /* Copied value              */
271 
272     len = 0x800 - (addr & 0x7FF);
273     main1 = MADDRL(addr, len, arn, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey);
274     sk = regs->dat.storkey;
275     main2 = MADDRL((addr + len) & ADDRESS_MAXWRAP(regs), 4-len, arn, regs,
276                   ACCTYPE_WRITE, regs->psw.pkey);
277     *sk |= (STORKEY_REF | STORKEY_CHANGE);
278     STORE_FW(temp, value);
279     memcpy(main1, temp, len);
280     memcpy(main2, temp+len, 4-len);
281 
282 } /* end function ARCH_DEP(vstore4_full) */
283 
284 /* vstore4 accelerator - Simple case only (better inline candidate) */
ARCH_DEP(vstore4)285 _VSTORE_C_STATIC void ARCH_DEP(vstore4) (U32 value, VADR addr, int arn,
286                                                             REGS *regs)
287 {
288     /* Most common case : Aligned & not crossing page boundary */
289     if(likely(!((VADR_L)addr & 0x03)) || (((VADR_L)addr & 0x7ff) <= 0x7fc))
290     {
291         BYTE *mn;
292         mn = MADDRL(addr, 4, arn, regs, ACCTYPE_WRITE, regs->psw.pkey);
293         STORE_FW(mn, value);
294         ITIMER_UPDATE(addr,4-1,regs);
295     }
296     else
297         ARCH_DEP(vstore4_full)(value,addr,arn,regs);
298 }
299 
300 /*-------------------------------------------------------------------*/
301 /* Store an eight-byte integer into virtual storage operand          */
302 /*                                                                   */
303 /* Input:                                                            */
304 /*      value   64-bit integer value to be stored                    */
305 /*      addr    Logical address of leftmost operand byte             */
306 /*      arn     Access register number                               */
307 /*      regs    CPU register context                                 */
308 /*                                                                   */
309 /*      A program check may be generated if the logical address      */
310 /*      causes an addressing, translation, or protection             */
311 /*      exception, and in this case the function does not return.    */
312 /*                                                                   */
313 /*      NOTE that vstore8_full should only be invoked when a page    */
314 /*           boundary IS going to be crossed.                        */
315 /*-------------------------------------------------------------------*/
ARCH_DEP(vstore8_full)316 _VSTORE_FULL_C_STATIC void ARCH_DEP(vstore8_full)(U64 value, VADR addr,
317                                               int arn, REGS *regs)
318 {
319 BYTE   *main1, *main2;                  /* Mainstor addresses        */
320 BYTE   *sk;                             /* Storage key addresses     */
321 int     len;                            /* Length to end of page     */
322 BYTE    temp[8];                        /* Copied value              */
323 
324     len = 0x800 - (addr & 0x7FF);
325     main1 = MADDRL(addr, len, arn, regs, ACCTYPE_WRITE_SKP, regs->psw.pkey);
326     sk = regs->dat.storkey;
327     main2 = MADDRL((addr + len) & ADDRESS_MAXWRAP(regs), 8-len, arn, regs,
328                   ACCTYPE_WRITE, regs->psw.pkey);
329     *sk |= (STORKEY_REF | STORKEY_CHANGE);
330     STORE_DW(temp, value);
331     memcpy(main1, temp, len);
332     memcpy(main2, temp+len, 8-len);
333 
334 } /* end function ARCH_DEP(vstore8) */
ARCH_DEP(vstore8)335 _VSTORE_C_STATIC void ARCH_DEP(vstore8) (U64 value, VADR addr, int arn,
336                                                             REGS *regs)
337 {
338 #if defined(OPTION_SINGLE_CPU_DW) && defined(ASSIST_STORE_DW)
339     /* Check alignement. If aligned then we are guaranteed
340        not to cross a page boundary */
341     if(likely(!((VADR_L)addr & 0x07)))
342     {
343         /* Most common case : Aligned */
344         U64 *mn;
345         mn = (U64*)MADDRL(addr,8,arn,regs,ACCTYPE_WRITE,regs->psw.pkey);
346         if (regs->cpubit == regs->sysblk->started_mask)
347             *mn = CSWAP64(value);
348         else
349         STORE_DW(mn, value);
350     }
351     else
352 #endif
353     {
354         /* We're not aligned. So we have to check whether we are
355            crossing a page boundary. This cannot be the same
356            code as above because casting U64 * to a non aligned
357            pointer may break on those architectures mandating
358            strict alignement */
359         if(likely(((VADR_L)addr & 0x7ff) <= 0x7f8))
360         {
361             /* Non aligned but not crossing page boundary */
362             BYTE *mn;
363             mn = MADDRL(addr,8,arn,regs,ACCTYPE_WRITE,regs->psw.pkey);
364             /* invoking STORE_DW ensures endianness correctness */
365             STORE_DW(mn,value);
366         }
367         else
368             /* Crossing page boundary */
369             ARCH_DEP(vstore8_full)(value,addr,arn,regs);
370     }
371     ITIMER_UPDATE(addr,8-1,regs);
372 }
373 
374 /*-------------------------------------------------------------------*/
375 /* Fetch a 1 to 256 character operand from virtual storage           */
376 /*                                                                   */
377 /* Input:                                                            */
378 /*      len     Size of operand minus 1                              */
379 /*      addr    Logical address of leftmost character of operand     */
380 /*      arn     Access register number                               */
381 /*      regs    CPU register context                                 */
382 /* Output:                                                           */
383 /*      dest    1 to 256 byte output buffer                          */
384 /*                                                                   */
385 /*      A program check may be generated if the logical address      */
386 /*      causes an addressing, translation, or fetch protection       */
387 /*      exception, and in this case the function does not return.    */
388 /*-------------------------------------------------------------------*/
ARCH_DEP(vfetchc)389 _VSTORE_C_STATIC void ARCH_DEP(vfetchc) (void *dest, BYTE len,
390                                         VADR addr, int arn, REGS *regs)
391 {
392 BYTE   *main1, *main2;                  /* Main storage addresses    */
393 int     len2;                           /* Length to copy on page    */
394 
395     main1 = MADDR(addr,arn,regs,ACCTYPE_READ,regs->psw.pkey);
396 
397     if ( NOCROSS2K(addr,len) )
398     {
399         ITIMER_SYNC(addr,len,regs);
400         memcpy (dest, main1, len + 1);
401     }
402     else
403     {
404         len2 = 0x800 - (addr & 0x7FF);
405         main2 = MADDR ((addr + len2) & ADDRESS_MAXWRAP(regs),
406                        arn, regs, ACCTYPE_READ, regs->psw.pkey);
407         memcpy (dest, main1, len2);
408         memcpy ((BYTE*)dest + len2, main2, len + 1 - len2);
409     }
410 
411 } /* end function ARCH_DEP(vfetchc) */
412 
413 /*-------------------------------------------------------------------*/
414 /* Fetch a single byte operand from virtual storage                  */
415 /*                                                                   */
416 /* Input:                                                            */
417 /*      addr    Logical address of operand character                 */
418 /*      arn     Access register number                               */
419 /*      regs    CPU register context                                 */
420 /* Returns:                                                          */
421 /*      Operand byte                                                 */
422 /*                                                                   */
423 /*      A program check may be generated if the logical address      */
424 /*      causes an addressing, translation, or fetch protection       */
425 /*      exception, and in this case the function does not return.    */
426 /*-------------------------------------------------------------------*/
ARCH_DEP(vfetchb)427 _VSTORE_C_STATIC BYTE ARCH_DEP(vfetchb) (VADR addr, int arn,
428                                          REGS *regs)
429 {
430 BYTE   *mn;                           /* Main storage address      */
431 
432     ITIMER_SYNC(addr,1-1,regs);
433     mn = MADDR (addr, arn, regs, ACCTYPE_READ, regs->psw.pkey);
434     return *mn;
435 } /* end function ARCH_DEP(vfetchb) */
436 
437 /*-------------------------------------------------------------------*/
438 /* Fetch a two-byte integer operand from virtual storage             */
439 /*                                                                   */
440 /* Input:                                                            */
441 /*      addr    Logical address of leftmost byte of operand          */
442 /*      arn     Access register number                               */
443 /*      regs    CPU register context                                 */
444 /* Returns:                                                          */
445 /*      Operand in 16-bit integer format                             */
446 /*                                                                   */
447 /*      A program check may be generated if the logical address      */
448 /*      causes an addressing, translation, or fetch protection       */
449 /*      exception, and in this case the function does not return.    */
450 /*-------------------------------------------------------------------*/
ARCH_DEP(vfetch2_full)451 _VSTORE_FULL_C_STATIC U16 ARCH_DEP(vfetch2_full) (VADR addr, int arn,
452                                              REGS *regs)
453 {
454 BYTE   *mn;                             /* Main storage addresses    */
455 U16     value;
456 
457     mn = MADDR (addr, arn, regs, ACCTYPE_READ, regs->psw.pkey);
458     value = *mn << 8;
459     mn = MADDR ((addr + 1) & ADDRESS_MAXWRAP(regs), arn, regs,
460                  ACCTYPE_READ, regs->psw.pkey);
461     value |= *mn;
462     return value;
463 
464 } /* end function ARCH_DEP(vfetch2) */
465 
ARCH_DEP(vfetch2)466 _VSTORE_C_STATIC U16 ARCH_DEP(vfetch2) (VADR addr, int arn, REGS *regs)
467 {
468     if(likely(!((VADR_L)addr & 0x01)) || (((VADR_L)addr & 0x7ff) !=0x7ff ))
469     {
470     BYTE *mn;
471         ITIMER_SYNC(addr,2-1,regs);
472         mn = MADDR(addr,arn,regs,ACCTYPE_READ,regs->psw.pkey);
473         return fetch_hw(mn);
474     }
475     return(ARCH_DEP(vfetch2_full)(addr,arn,regs));
476 }
477 
478 /*-------------------------------------------------------------------*/
479 /* Fetch a four-byte integer operand from virtual storage            */
480 /*                                                                   */
481 /* Input:                                                            */
482 /*      addr    Logical address of leftmost byte of operand          */
483 /*      arn     Access register number                               */
484 /*      regs    CPU register context                                 */
485 /* Returns:                                                          */
486 /*      Operand in 32-bit integer format                             */
487 /*                                                                   */
488 /*      A program check may be generated if the logical address      */
489 /*      causes an addressing, translation, or fetch protection       */
490 /*      exception, and in this case the function does not return.    */
491 /*-------------------------------------------------------------------*/
ARCH_DEP(vfetch4_full)492 _VSTORE_FULL_C_STATIC U32 ARCH_DEP(vfetch4_full) (VADR addr, int arn,
493                                              REGS *regs)
494 {
495 BYTE   *mn;                             /* Main storage addresses    */
496 int     len;                            /* Length to end of page     */
497 BYTE    temp[8];                        /* Copy destination          */
498 
499     mn = MADDR (addr, arn, regs, ACCTYPE_READ, regs->psw.pkey);
500     memcpy(temp, mn, 4);
501     len = 0x800 - (addr & 0x7FF);
502     mn = MADDR ((addr + len) & ADDRESS_MAXWRAP(regs), arn, regs,
503                  ACCTYPE_READ, regs->psw.pkey);
504     memcpy(temp+len, mn, 4);
505     return fetch_fw(temp);
506 
507 } /* end function ARCH_DEP(vfetch4_full) */
508 
ARCH_DEP(vfetch4)509 _VSTORE_C_STATIC U32 ARCH_DEP(vfetch4) (VADR addr, int arn, REGS *regs)
510 {
511     if ( (likely(!((VADR_L)addr & 0x03)) || (((VADR_L)addr & 0x7ff) <= 0x7fc )))
512     {
513     BYTE *mn;
514         ITIMER_SYNC(addr,4-1,regs);
515         mn=MADDR(addr,arn,regs,ACCTYPE_READ,regs->psw.pkey);
516         return fetch_fw(mn);
517     }
518     return(ARCH_DEP(vfetch4_full)(addr,arn,regs));
519 }
520 
521 /*-------------------------------------------------------------------*/
522 /* Fetch an eight-byte integer operand from virtual storage          */
523 /*                                                                   */
524 /* Input:                                                            */
525 /*      addr    Logical address of leftmost byte of operand          */
526 /*      arn     Access register number                               */
527 /*      regs    CPU register context                                 */
528 /* Returns:                                                          */
529 /*      Operand in 64-bit integer format                             */
530 /*                                                                   */
531 /*      A program check may be generated if the logical address      */
532 /*      causes an addressing, translation, or fetch protection       */
533 /*      exception, and in this case the function does not return.    */
534 /*-------------------------------------------------------------------*/
ARCH_DEP(vfetch8_full)535 _VSTORE_FULL_C_STATIC U64 ARCH_DEP(vfetch8_full) (VADR addr, int arn,
536                                              REGS *regs)
537 {
538 BYTE   *mn;                             /* Main storage addresses    */
539 int     len;                            /* Length to end of page     */
540 BYTE    temp[16];                       /* Copy destination          */
541 
542     /* Get absolute address of first byte of operand */
543     mn = MADDR (addr, arn, regs, ACCTYPE_READ, regs->psw.pkey);
544     memcpy(temp, mn, 8);
545     len = 0x800 - (addr & 0x7FF);
546     mn = MADDR ((addr + len) & ADDRESS_MAXWRAP(regs), arn, regs,
547                 ACCTYPE_READ, regs->psw.pkey);
548     memcpy(temp+len, mn, 8);
549     return fetch_dw(temp);
550 
551 } /* end function ARCH_DEP(vfetch8) */
552 
ARCH_DEP(vfetch8)553 _VSTORE_C_STATIC U64 ARCH_DEP(vfetch8) (VADR addr, int arn, REGS *regs)
554 {
555 #if defined(OPTION_SINGLE_CPU_DW) && defined(ASSIST_STORE_DW)
556     if(likely(!((VADR_L)addr & 0x07)))
557     {
558         /* doubleword aligned fetch */
559         U64 *mn;
560         ITIMER_SYNC(addr,8-1,regs);
561         mn=(U64*)MADDR (addr, arn, regs, ACCTYPE_READ, regs->psw.pkey);
562         if (regs->cpubit == regs->sysblk->started_mask)
563             return CSWAP64(*mn);
564         return fetch_dw(mn);
565     }
566     else
567 #endif
568     {
569 
570         if(likely(((VADR_L)addr & 0x7ff) <= 0x7f8))
571         {
572             /* unaligned, non-crossing doubleword fetch */
573             BYTE *mn;
574             ITIMER_SYNC(addr,8-1,regs);
575             mn=MADDR (addr, arn, regs, ACCTYPE_READ, regs->psw.pkey);
576             return fetch_dw(mn);
577         }
578     }
579     /* page crossing doubleword fetch */
580     return ARCH_DEP(vfetch8_full)(addr,arn,regs);
581 }
582 #endif
583 
584 #if !defined(OPTION_NO_INLINE_IFETCH) || defined(_VSTORE_C)
585 /*-------------------------------------------------------------------*/
586 /* Fetch instruction from halfword-aligned virtual storage location  */
587 /*                                                                   */
588 /* Input:                                                            */
589 /*      regs    Pointer to the CPU register context                  */
590 /*      exec    If 1 then called by EXecute otherwise called by      */
591 /*              INSTRUCTION_FETCH                                    */
592 /*                                                                   */
593 /* If called by INSTRUCTION_FETCH then                               */
594 /*      addr    regs->psw.IA                                         */
595 /*      dest    regs->inst                                           */
596 /*                                                                   */
597 /* If called by EXecute then                                         */
598 /*      addr    regs->ET                                             */
599 /*      dest    regs->exinst                                         */
600 /*                                                                   */
601 /* Output:                                                           */
602 /*      If successful, a pointer is returned to the instruction. If  */
603 /*      the instruction crossed a page boundary then the instruction */
604 /*      is copied either to regs->inst or regs->exinst (depending on */
605 /*      the exec flag).  Otherwise the pointer points into mainstor. */
606 /*                                                                   */
607 /*      If the exec flag is 0 and tracing or PER is not active then  */
608 /*      the AIA is updated.  This forces interrupts to be checked    */
609 /*      instfetch to be call for each instruction.  Note that        */
610 /*      process_trace() is called from here if tracing is active.    */
611 /*                                                                   */
612 /*      A program check may be generated if the instruction address  */
613 /*      is odd, or causes an addressing or translation exception,    */
614 /*      and in this case the function does not return.  In the       */
615 /*      latter case, regs->instinvalid is 1 which indicates to       */
616 /*      program_interrupt that the exception occurred during         */
617 /*      instruction fetch.                                           */
618 /*                                                                   */
619 /*      Because this function is inlined and `exec' is a constant    */
620 /*      (either 0 or 1) the references to exec are optimized out by  */
621 /*      the compiler.                                                */
622 /*-------------------------------------------------------------------*/
ARCH_DEP(instfetch)623 _VFETCH_C_STATIC BYTE * ARCH_DEP(instfetch) (REGS *regs, int exec)
624 {
625 VADR    addr;                           /* Instruction address       */
626 BYTE   *ia;                             /* Instruction pointer       */
627 BYTE   *dest;                           /* Copied instruction        */
628 int     pagesz;                         /* Effective page size       */
629 int     offset;                         /* Address offset into page  */
630 int     len;                            /* Length for page crossing  */
631 
632     SET_BEAR_REG(regs, regs->bear_ip);
633 
634     addr = exec ? regs->ET
635          : likely(regs->aie == NULL) ? regs->psw.IA : PSW_IA(regs,0);
636 
637     offset = (int)(addr & PAGEFRAME_BYTEMASK);
638 
639     /* Program check if instruction address is odd */
640     if ( unlikely(offset & 0x01) )
641     {
642         if (!exec) regs->instinvalid = 1;
643         regs->program_interrupt(regs, PGM_SPECIFICATION_EXCEPTION);
644     }
645     pagesz = unlikely(addr < 0x800) ? 0x800 : PAGEFRAME_PAGESIZE;
646 
647 #if defined(FEATURE_PER)
648     /* Save the address address used to fetch the instruction */
649     if( EN_IC_PER(regs) )
650     {
651 #if defined(FEATURE_PER2)
652         regs->perc = 0x40    /* ATMID-validity */
653                    | (regs->psw.amode64 << 7)
654                    | (regs->psw.amode << 5)
655                    | (!REAL_MODE(&regs->psw) ? 0x10 : 0)
656                    | (SPACE_BIT(&regs->psw) << 3)
657                    | (AR_BIT(&regs->psw) << 2);
658 #else /*!defined(FEATURE_PER2)*/
659         regs->perc = 0;
660 #endif /*!defined(FEATURE_PER2)*/
661 
662         if(!exec)
663             regs->peradr = addr;
664 
665         /* Test for PER instruction-fetching event */
666         if( EN_IC_PER_IF(regs)
667           && PER_RANGE_CHECK(addr,regs->CR(10),regs->CR(11)) )
668         {
669             ON_IC_PER_IF(regs);
670       #if defined(FEATURE_PER3)
671             /* If CR9_IFNUL (PER instruction-fetching nullification) is
672                set, take a program check immediately, without executing
673                the instruction or updating the PSW instruction address */
674             if ( EN_IC_PER_IFNUL(regs) )
675             {
676                 ON_IC_PER_IFNUL(regs);
677                 regs->psw.IA = addr;
678                 regs->psw.zeroilc = 1;
679                 regs->program_interrupt(regs, PGM_PER_EVENT);
680             }
681       #endif /*defined(FEATURE_PER3)*/
682         }
683         /* Quick exit if aia valid */
684         if (!exec && !regs->tracing
685          && regs->aie && regs->ip < regs->aip + pagesz - 5)
686             return regs->ip;
687     }
688 #endif /*defined(FEATURE_PER)*/
689 
690     if (!exec) regs->instinvalid = 1;
691 
692     /* Get instruction address */
693     ia = MADDR (addr, USE_INST_SPACE, regs, ACCTYPE_INSTFETCH, regs->psw.pkey);
694 
695     /* If boundary is crossed then copy instruction to destination */
696     if ( offset + ILC(ia[0]) > pagesz )
697     {
698         /* Note - dest is 8 bytes */
699         dest = exec ? regs->exinst : regs->inst;
700         memcpy (dest, ia, 4);
701         len = pagesz - offset;
702         offset = 0;
703         addr = (addr + len) & ADDRESS_MAXWRAP(regs);
704         ia = MADDR(addr, USE_INST_SPACE, regs, ACCTYPE_INSTFETCH, regs->psw.pkey);
705         if (!exec) regs->ip = ia - len;
706         memcpy(dest + len, ia, 4);
707     }
708     else
709     {
710         dest = ia;
711         if (!exec) regs->ip = ia;
712     }
713 
714     if (!exec)
715     {
716         regs->instinvalid = 0;
717 
718         /* Update the AIA */
719         regs->AIV = addr & PAGEFRAME_PAGEMASK;
720         regs->aip = (BYTE *)((uintptr_t)ia & ~PAGEFRAME_BYTEMASK);
721         regs->aim = (uintptr_t)regs->aip ^ (uintptr_t)regs->AIV;
722         if (likely(!regs->tracing && !regs->permode))
723             regs->aie = regs->aip + pagesz - 5;
724         else
725         {
726             regs->aie = (BYTE *)1;
727             if (regs->tracing)
728                 ARCH_DEP(process_trace)(regs);
729         }
730     }
731 
732     return dest;
733 
734 } /* end function ARCH_DEP(instfetch) */
735 #endif
736 
737 
738 /*-------------------------------------------------------------------*/
739 /* Copy 8 bytes at a time concurrently                               */
740 /*-------------------------------------------------------------------*/
741 #ifndef _VSTORE_CONCPY
742 #define _VSTORE_CONCPY
concpy(REGS * regs,void * d,void * s,int n)743 static __inline__ void concpy (REGS *regs, void *d, void *s, int n)
744 {
745  int   n2;
746  BYTE *dest = (BYTE *)d, *src = (BYTE *)s;
747 
748     /* Byte for byte copy if short length or possible overlap */
749     if (n < 8
750      || (dest <= src  && dest + 8 > src)
751      || (src  <= dest && src  + 8 > dest))
752     {
753         /* use memset directly when the copy's effect is to
754            propagate a byte over an area - like in MVC 1(255,2),0(2) */
755         if(dest==src+1)
756         {
757             memset(dest,*src,n);
758         }
759         else
760         {
761             for ( ; n; n--)
762                 *(dest++) = *(src++);
763         }
764         return;
765     }
766 
767     /* copy to an 8 byte boundary */
768     n2 = (intptr_t)dest & 7;
769     n -= n2;
770     for ( ; n2; n2--)
771         *(dest++) = *(src++);
772 
773 #if !defined(OPTION_STRICT_ALIGNMENT) && \
774     ((!defined(_MSVC_) && defined(SIZEOF_LONG)  && SIZEOF_LONG  >= 8) || \
775      ( defined(_MSVC_) && defined(SIZEOF_INT_P) && SIZEOF_INT_P >= 8))
776 
777     /* Below for 64-bit BUILDS ONLY, since the below C code
778        does NOT generate atomic 64-bit load/store assembler
779        code sequence compatible with Concurrent Block Update
780        except when building for 64-bit systems...
781     */
782     UNREFERENCED(regs);
783 
784     /* copy 8 bytes at a time */
785     for ( ; n >= 8; n -= 8, dest += 8, src += 8)
786         *(U64 *)dest = *(U64 *)src;
787 
788 #else /* 32-bit builds... */
789 
790  #if !defined(OPTION_STRICT_ALIGNMENT)
791 
792     /* copy 4 bytes at a time if only one cpu started */
793     if (regs->cpubit == regs->sysblk->started_mask)
794         for ( ; n >= 4; n -= 4, dest += 4, src += 4)
795             *(U32 *)dest = *(U32 *)src;
796     else
797 
798  #else /* defined(OPTION_STRICT_ALIGNMENT) */
799     UNREFERENCED(regs);
800  #endif
801 
802     /* else copy 8 bytes at a time concurrently */
803         for ( ; n >= 8; n -= 8, dest += 8, src += 8)
804             store_dw_noswap(dest,fetch_dw_noswap(src));
805 
806 #endif /* (64-bit builds test...) */
807 
808     /* copy leftovers */
809     for ( ; n; n--)
810         *(dest++) = *(src++);
811 }
812 #endif /* !defined(_VSTORE_CONCPY) */
813 
814 #if !defined(OPTION_NO_INLINE_VSTORE) || defined(_VSTORE_C)
815 
816 /*-------------------------------------------------------------------*/
817 /* Move characters using specified keys and address spaces           */
818 /*                                                                   */
819 /* Input:                                                            */
820 /*      addr1   Effective address of first operand                   */
821 /*      arn1    Access register number for first operand,            */
822 /*              or USE_PRIMARY_SPACE or USE_SECONDARY_SPACE          */
823 /*      key1    Bits 0-3=first operand access key, 4-7=zeroes        */
824 /*      addr2   Effective address of second operand                  */
825 /*      arn2    Access register number for second operand,           */
826 /*              or USE_PRIMARY_SPACE or USE_SECONDARY_SPACE          */
827 /*      key2    Bits 0-3=second operand access key, 4-7=zeroes       */
828 /*      len     Operand length minus 1 (range 0-255)                 */
829 /*      regs    Pointer to the CPU register context                  */
830 /*                                                                   */
831 /*      This function implements the MVC, MVCP, MVCS, MVCK, MVCSK,   */
832 /*      and MVCDK instructions.  These instructions move up to 256   */
833 /*      characters using the address space and key specified by      */
834 /*      the caller for each operand.  Operands are moved byte by     */
835 /*      byte to ensure correct processing of overlapping operands.   */
836 /*                                                                   */
837 /*      The arn parameter for each operand may be an access          */
838 /*      register number, in which case the operand is in the         */
839 /*      primary, secondary, or home space, or in the space           */
840 /*      designated by the specified access register, according to    */
841 /*      the current PSW addressing mode.                             */
842 /*                                                                   */
843 /*      Alternatively the arn parameter may be one of the special    */
844 /*      values USE_PRIMARY_SPACE or USE_SECONDARY_SPACE in which     */
845 /*      case the operand is in the specified space regardless of     */
846 /*      the current PSW addressing mode.                             */
847 /*                                                                   */
848 /*      A program check may be generated if either logical address   */
849 /*      causes an addressing, protection, or translation exception,  */
850 /*      and in this case the function does not return.               */
851 /*-------------------------------------------------------------------*/
ARCH_DEP(move_chars)852 _VSTORE_C_STATIC void ARCH_DEP(move_chars) (VADR addr1, int arn1,
853        BYTE key1, VADR addr2, int arn2, BYTE key2, int len, REGS *regs)
854 {
855 BYTE   *dest1, *dest2;                  /* Destination addresses     */
856 BYTE   *source1, *source2;              /* Source addresses          */
857 BYTE   *sk1, *sk2;                      /* Storage key addresses     */
858 int     len2, len3;                     /* Lengths to copy           */
859 
860     ITIMER_SYNC(addr2,len,regs);
861 
862     /* Quick out if copying just 1 byte */
863     if (unlikely(len == 0))
864     {
865         source1 = MADDR (addr2, arn2, regs, ACCTYPE_READ, key2);
866         dest1 = MADDR (addr1, arn1, regs, ACCTYPE_WRITE, key1);
867         *dest1 = *source1;
868         ITIMER_UPDATE(addr1,len,regs);
869         return;
870     }
871 
872     /* Translate addresses of leftmost operand bytes */
873     source1 = MADDR (addr2, arn2, regs, ACCTYPE_READ, key2);
874     dest1 = MADDRL (addr1, len+1, arn1, regs, ACCTYPE_WRITE_SKP, key1);
875     sk1 = regs->dat.storkey;
876 
877     /* There are several scenarios (in optimal order):
878      * (1) dest boundary and source boundary not crossed
879      * (2) dest boundary not crossed and source boundary crossed
880      * (3) dest boundary crossed and source boundary not crossed
881      * (4) dest boundary and source boundary are crossed
882      *     (a) dest and source boundary cross at the same time
883      *     (b) dest boundary crossed first
884      *     (c) source boundary crossed first
885      * Note: since the operand length is limited to 256 bytes,
886      *       neither operand can cross more than one 2K boundary.
887      */
888 
889     if ( NOCROSS2K(addr1,len) )
890     {
891         if ( NOCROSS2K(addr2,len) )
892         {
893             /* (1) - No boundaries are crossed */
894             concpy (regs, dest1, source1, len + 1);
895         }
896         else
897         {
898             /* (2) - Second operand crosses a boundary */
899             len2 = 0x800 - (addr2 & 0x7FF);
900             source2 = MADDR ((addr2 + len2) & ADDRESS_MAXWRAP(regs),
901                               arn2, regs, ACCTYPE_READ, key2);
902             concpy (regs, dest1, source1, len2);
903             concpy (regs, dest1 + len2, source2, len - len2 + 1);
904         }
905         *sk1 |= (STORKEY_REF | STORKEY_CHANGE);
906     }
907     else
908     {
909         /* First operand crosses a boundary */
910         len2 = 0x800 - (addr1 & 0x7FF);
911         dest2 = MADDR ((addr1 + len2) & ADDRESS_MAXWRAP(regs),
912                        arn1, regs, ACCTYPE_WRITE_SKP, key1);
913         sk2 = regs->dat.storkey;
914 
915         if ( NOCROSS2K(addr2,len) )
916         {
917              /* (3) - First operand crosses a boundary */
918              concpy (regs, dest1, source1, len2);
919              concpy (regs, dest2, source1 + len2, len - len2 + 1);
920         }
921         else
922         {
923             /* (4) - Both operands cross a boundary */
924             len3 = 0x800 - (addr2 & 0x7FF);
925             source2 = MADDR ((addr2 + len3) & ADDRESS_MAXWRAP(regs),
926                              arn2, regs, ACCTYPE_READ, key2);
927             if (len2 == len3)
928             {
929                 /* (4a) - Both operands cross at the same time */
930                 concpy (regs, dest1, source1, len2);
931                 concpy (regs, dest2, source2, len - len2 + 1);
932             }
933             else if (len2 < len3)
934             {
935                 /* (4b) - First operand crosses first */
936                 concpy (regs, dest1, source1, len2);
937                 concpy (regs, dest2, source1 + len2, len3 - len2);
938                 concpy (regs, dest2 + len3 - len2, source2, len - len3 + 1);
939             }
940             else
941             {
942                 /* (4c) - Second operand crosses first */
943                 concpy (regs, dest1, source1, len3);
944                 concpy (regs, dest1 + len3, source2, len2 - len3);
945                 concpy (regs, dest2, source2 + len2 - len3, len - len2 + 1);
946             }
947         }
948         *sk1 |= (STORKEY_REF | STORKEY_CHANGE);
949         *sk2 |= (STORKEY_REF | STORKEY_CHANGE);
950     }
951     ITIMER_UPDATE(addr1,len,regs);
952 
953 } /* end function ARCH_DEP(move_chars) */
954 
955 
956 #if defined(FEATURE_MOVE_WITH_OPTIONAL_SPECIFICATIONS)
957 /*-------------------------------------------------------------------*/
958 /* Move characters with optional specifications                      */
959 /*                                                                   */
960 /* Input:                                                            */
961 /*      addr1   Effective address of first operand                   */
962 /*      space1  Address space for first operand:                     */
963 /*                 USE_PRIMARY_SPACE                                 */
964 /*                 USE_SECONDARY_SPACE                               */
965 /*                 USE_ARMODE + access register number               */
966 /*                 USE_HOME_SPACE                                    */
967 /*      key1    Bits 0-3=first operand access key, 4-7=zeroes        */
968 /*      addr2   Effective address of second operand                  */
969 /*      space1  Address space for second operand (values as space1)  */
970 /*      key2    Bits 0-3=second operand access key, 4-7=zeroes       */
971 /*      len     Operand length (range 0-4096)                        */
972 /*      regs    Pointer to the CPU register context                  */
973 /*                                                                   */
974 /*      This function implements the MVCOS instruction which moves   */
975 /*      up to 4096 characters using the address space and key        */
976 /*      specified by the caller for each operand.  Results are       */
977 /*      unpredictable if destructive overlap exists.                 */
978 /*                                                                   */
979 /*      The space1 and space2 parameters force the use of the        */
980 /*      specified address space, or the use of the specified         */
981 /*      access register, regardless of the current PSW addressing    */
982 /*      mode.                                                        */
983 /*                                                                   */
984 /*      A program check may be generated if either logical address   */
985 /*      causes an addressing, protection, or translation exception,  */
986 /*      and in this case the function does not return.               */
987 /*-------------------------------------------------------------------*/
ARCH_DEP(move_charx)988 _VSTORE_C_STATIC void ARCH_DEP(move_charx) (VADR addr1, int space1,
989        BYTE key1, VADR addr2, int space2, BYTE key2,
990        int len, REGS *regs)
991 {
992 BYTE   *main1, *main2;                  /* Main storage pointers     */
993 int     len1, len2, len3;               /* Work areas for lengths    */
994 
995     /* Ultra quick out if copying zero bytes */
996     if (unlikely(len == 0))
997         return;
998 
999     ITIMER_SYNC(addr2,len-1,regs);
1000 
1001     /* Quick out if copying just 1 byte */
1002     if (unlikely(len == 1))
1003     {
1004         main2 = MADDR (addr2, space2, regs, ACCTYPE_READ, key2);
1005         main1 = MADDR (addr1, space1, regs, ACCTYPE_WRITE, key1);
1006         *main1 = *main2;
1007         ITIMER_UPDATE(addr1,len-1,regs);
1008         return;
1009     }
1010 
1011     /* Translate addresses of leftmost operand bytes */
1012     main2 = MADDR (addr2, space2, regs, ACCTYPE_READ, key2);
1013     main1 = MADDRL (addr1, len, space1, regs, ACCTYPE_WRITE, key1);
1014 
1015     /* Copy the largest chunks which do not cross a 2K
1016        boundary of either source or destination operand */
1017     while (len > 0)
1018     {
1019         /* Calculate distance to next 2K boundary */
1020         len1 = NOCROSS2KL(addr1,len) ? len :
1021                 (int)(0x800 - (addr1 & 0x7FF));
1022         len2 = NOCROSS2KL(addr2,len) ? len :
1023                 (int)(0x800 - (addr2 & 0x7FF));
1024         len3 = len1 < len2 ? len1 : len2;
1025 
1026         /* Copy bytes from source to destination */
1027         concpy (regs, main1, main2, len3);
1028 
1029         /* Calculate virtual addresses for next chunk */
1030         addr1 = (addr1 + len3) & ADDRESS_MAXWRAP(regs);
1031         addr2 = (addr2 + len3) & ADDRESS_MAXWRAP(regs);
1032 
1033         /* Adjust remaining length */
1034         len -= len3;
1035 
1036         /* Exit if no more bytes to move */
1037         if (len == 0) break;
1038 
1039         /* Adjust addresses for start of next chunk, or
1040            translate again if a 2K boundary was crossed */
1041         main2 = (addr2 & 0x7FF) ? main2 + len3 :
1042                     MADDR (addr2, space2, regs, ACCTYPE_READ, key2);
1043         main1 = (addr1 & 0x7FF) ? main1 + len3 :
1044                     MADDR (addr1, space1, regs, ACCTYPE_WRITE, key1);
1045 
1046     } /* end while(len) */
1047 
1048     ITIMER_UPDATE(addr1,len-1,regs);
1049 
1050 } /* end function ARCH_DEP(move_charx) */
1051 #endif /*defined(FEATURE_MOVE_WITH_OPTIONAL_SPECIFICATIONS)*/
1052 
1053 
1054 /*-------------------------------------------------------------------*/
1055 /* Validate operand for addressing, protection, translation          */
1056 /*                                                                   */
1057 /* Input:                                                            */
1058 /*      addr    Effective address of operand                         */
1059 /*      arn     Access register number                               */
1060 /*      len     Operand length minus 1 (range 0-255)                 */
1061 /*      acctype Type of access requested: READ or WRITE              */
1062 /*      regs    Pointer to the CPU register context                  */
1063 /*                                                                   */
1064 /*      The purpose of this function is to allow an instruction      */
1065 /*      operand to be validated for addressing, protection, and      */
1066 /*      translation exceptions, thus allowing the instruction to     */
1067 /*      be nullified or suppressed before any updates occur.         */
1068 /*                                                                   */
1069 /*      A program check is generated if the operand causes an        */
1070 /*      addressing, protection, or translation exception, and        */
1071 /*      in this case the function does not return.                   */
1072 /*-------------------------------------------------------------------*/
ARCH_DEP(validate_operand)1073 _VSTORE_C_STATIC void ARCH_DEP(validate_operand) (VADR addr, int arn,
1074                                       int len, int acctype, REGS *regs)
1075 {
1076     /* Translate address of leftmost operand byte */
1077     MADDR (addr, arn, regs, acctype, regs->psw.pkey);
1078 
1079     /* Translate next page if boundary crossed */
1080     if ( CROSS2K(addr,len) )
1081     {
1082         MADDR ((addr + len) & ADDRESS_MAXWRAP(regs),
1083                arn, regs, acctype, regs->psw.pkey);
1084     }
1085 #ifdef FEATURE_INTERVAL_TIMER
1086     else
1087         ITIMER_SYNC(addr,len,regs);
1088 #endif /*FEATURE_INTERVAL_TIMER*/
1089 } /* end function ARCH_DEP(validate_operand) */
1090 
1091 #endif /*!defined(OPTION_NO_INLINE_VSTORE) || defined(_VSTORE_C)*/
1092