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(®s->psw) ? 0x10 : 0)
656 | (SPACE_BIT(®s->psw) << 3)
657 | (AR_BIT(®s->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