1 /* XSTORE.C (c) Copyright Jan Jaeger, 1999-2009 */
2 /* Expanded storage related instructions */
3
4 /* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2009 */
5 /* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2009 */
6
7 /* MVPG moved from cpu.c to xstore.c 05/07/00 Jan Jaeger */
8
9 /*-------------------------------------------------------------------*/
10 /* This module implements the expanded storage instructions */
11 /* for the Hercules ESA/390 emulator. */
12 /*-------------------------------------------------------------------*/
13
14 #include "hstdinc.h"
15
16 #if !defined(_HENGINE_DLL_)
17 #define _HENGINE_DLL_
18 #endif
19
20 #if !defined(_XSTORE_C_)
21 #define _XSTORE_C_
22 #endif
23
24 #include "hercules.h"
25 #include "opcode.h"
26 #include "inline.h"
27
28 #if defined(FEATURE_EXPANDED_STORAGE)
29 /*-------------------------------------------------------------------*/
30 /* B22E PGIN - Page in from expanded storage [RRE] */
31 /*-------------------------------------------------------------------*/
DEF_INST(page_in)32 DEF_INST(page_in)
33 {
34 int r1, r2; /* Values of R fields */
35 VADR vaddr; /* Virtual storage address */
36 BYTE *maddr; /* Main storage address */
37 U32 xaddr; /* Expanded storage block# */
38 size_t xoffs; /* Byte offset into xpndstor */
39
40 RRE(inst, regs, r1, r2);
41
42 PRIV_CHECK(regs);
43
44 if(SIE_STATB(regs, IC3, PGX))
45 longjmp(regs->progjmp, SIE_INTERCEPT_INST);
46
47 #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)
48 /* Cannot perform xstore page movement in XC mode */
49 if(SIE_STATB(regs, MX, XC))
50 longjmp(regs->progjmp, SIE_INTERCEPT_INST);
51 #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/
52
53 /* expanded storage block number */
54 xaddr = regs->GR_L(r2);
55
56 if(SIE_MODE(regs))
57 {
58 xaddr += regs->sie_xso;
59 if(xaddr >= regs->sie_xsl)
60 {
61 PTT(PTT_CL_ERR,"*PGIN",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
62 regs->psw.cc = 3;
63 return;
64 }
65 }
66
67 /* If the expanded storage block is not configured then
68 terminate with cc3 */
69 if (xaddr >= sysblk.xpndsize)
70 {
71 PTT(PTT_CL_ERR,"*PGIN",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
72 regs->psw.cc = 3;
73 return;
74 }
75
76 /* Byte offset in expanded storage */
77 xoffs = (size_t)xaddr << XSTORE_PAGESHIFT;
78
79 /* Obtain abs address, verify access and set ref/change bits */
80 vaddr = (regs->GR(r1) & ADDRESS_MAXWRAP(regs)) & XSTORE_PAGEMASK;
81 maddr = MADDRL (vaddr, 4096, USE_REAL_ADDR, regs, ACCTYPE_WRITE, 0);
82
83 /* Copy data from expanded to main */
84 memcpy (maddr, sysblk.xpndstor + xoffs, XSTORE_PAGESIZE);
85
86 /* cc0 means pgin ok */
87 regs->psw.cc = 0;
88
89 } /* end DEF_INST(page_in) */
90 #endif /*defined(FEATURE_EXPANDED_STORAGE)*/
91
92
93 #if defined(FEATURE_EXPANDED_STORAGE)
94 /*-------------------------------------------------------------------*/
95 /* B22F PGOUT - Page out to expanded storage [RRE] */
96 /*-------------------------------------------------------------------*/
DEF_INST(page_out)97 DEF_INST(page_out)
98 {
99 int r1, r2; /* Values of R fields */
100 VADR vaddr; /* Virtual storage address */
101 BYTE *maddr; /* Main storage address */
102 U32 xaddr; /* Expanded storage block# */
103 size_t xoffs; /* Byte offset into xpndstor */
104
105 RRE(inst, regs, r1, r2);
106
107 PRIV_CHECK(regs);
108
109 if(SIE_STATB(regs, IC3, PGX))
110 longjmp(regs->progjmp, SIE_INTERCEPT_INST);
111
112 #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)
113 /* Cannot perform xstore page movement in XC mode */
114 if(SIE_STATB(regs, MX, XC))
115 longjmp(regs->progjmp, SIE_INTERCEPT_INST);
116 #endif /*defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/
117
118 /* expanded storage block number */
119 xaddr = regs->GR_L(r2);
120
121 if(SIE_MODE(regs))
122 {
123 xaddr += regs->sie_xso;
124 if(xaddr >= regs->sie_xsl)
125 {
126 PTT(PTT_CL_ERR,"*PGOUT",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
127 regs->psw.cc = 3;
128 return;
129 }
130 }
131
132 /* If the expanded storage block is not configured then
133 terminate with cc3 */
134 if (xaddr >= sysblk.xpndsize)
135 {
136 PTT(PTT_CL_ERR,"*PGOUT",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
137 regs->psw.cc = 3;
138 return;
139 }
140
141 /* Byte offset in expanded storage */
142 xoffs = (size_t)xaddr << XSTORE_PAGESHIFT;
143
144 /* Obtain abs address, verify access and set ref/change bits */
145 vaddr = (regs->GR(r1) & ADDRESS_MAXWRAP(regs)) & XSTORE_PAGEMASK;
146 maddr = MADDR (vaddr, USE_REAL_ADDR, regs, ACCTYPE_READ, 0);
147
148 /* Copy data from main to expanded */
149 memcpy (sysblk.xpndstor + xoffs, maddr, XSTORE_PAGESIZE);
150
151 /* cc0 means pgout ok */
152 regs->psw.cc = 0;
153
154 } /* end DEF_INST(page_out) */
155 #endif /*defined(FEATURE_EXPANDED_STORAGE)*/
156
157
158 #if defined(FEATURE_MOVE_PAGE_FACILITY_2) && defined(FEATURE_EXPANDED_STORAGE)
159 /*-------------------------------------------------------------------*/
160 /* B259 IESBE - Invalidate Expanded Storage Block Entry [RRE] */
161 /*-------------------------------------------------------------------*/
DEF_INST(invalidate_expanded_storage_block_entry)162 DEF_INST(invalidate_expanded_storage_block_entry)
163 {
164 int r1, r2; /* Values of R fields */
165
166 RRE(inst, regs, r1, r2);
167
168 PRIV_CHECK(regs);
169
170 #if defined(_FEATURE_SIE)
171 if(SIE_STATNB(regs, EC0, MVPG))
172 longjmp(regs->progjmp, SIE_INTERCEPT_INST);
173 #endif /*defined(_FEATURE_SIE)*/
174
175 /* Perform serialization before operation */
176 PERFORM_SERIALIZATION (regs);
177 OBTAIN_INTLOCK(regs);
178 SYNCHRONIZE_CPUS(regs);
179
180 /* Invalidate page table entry */
181 ARCH_DEP(invalidate_pte) (inst[1], regs->GR_G(r1), regs->GR_L(r2), regs);
182
183 RELEASE_INTLOCK(regs);
184
185 /* Perform serialization after operation */
186 PERFORM_SERIALIZATION (regs);
187
188 } /* end DEF_INST(invalidate_expanded_storage_block_entry) */
189 #endif /*defined(FEATURE_EXPANDED_STORAGE)*/
190
191
192 #if defined(_MSVC_)
193 /* Workaround for "fatal error C1001: INTERNAL COMPILER ERROR" in MSVC */
194 #pragma optimize("",off)
195 #endif /*defined(_MSVC_)*/
196
197 #if defined(FEATURE_MOVE_PAGE_FACILITY_2)
198 /*-------------------------------------------------------------------*/
199 /* B254 MVPG - Move Page [RRE] */
200 /*-------------------------------------------------------------------*/
DEF_INST(move_page)201 DEF_INST(move_page)
202 {
203 int r1, r2; /* Register values */
204 int rc = 0; /* Return code */
205 int cc = 0; /* Condition code */
206 VADR vaddr1, vaddr2; /* Virtual addresses */
207 RADR raddr1=0, raddr2=0, xpkeya; /* Real addresses */
208 BYTE *main1 = NULL, *main2 = NULL; /* Mainstor addresses */
209 BYTE *sk1; /* Storage key address */
210 BYTE akey; /* Access key in register 0 */
211 BYTE akey1, akey2; /* Access keys for operands */
212 #if defined(FEATURE_EXPANDED_STORAGE)
213 int xpvalid1 = 0, xpvalid2 = 0; /* 1=Operand in expanded stg */
214 CREG pte1 = 0, pte2 = 0; /* Page table entry */
215 U32 xpblk1 = 0, xpblk2 = 0; /* Expanded storage block# */
216 BYTE xpkey1 = 0, xpkey2 = 0; /* Expanded storage keys */
217 #endif /*defined(FEATURE_EXPANDED_STORAGE)*/
218
219 RRE(inst, regs, r1, r2);
220
221 #if defined(_FEATURE_SIE)
222 if(SIE_STATNB(regs, EC0, MVPG))
223 longjmp(regs->progjmp, SIE_INTERCEPT_INST);
224 #endif /*defined(_FEATURE_SIE)*/
225
226 /* Use PSW key as access key for both operands */
227 akey1 = akey2 = regs->psw.pkey;
228
229 /* If register 0 bit 20 or 21 is one, get access key from R0 */
230 if (regs->GR_L(0) & 0x00000C00)
231 {
232 /* Extract the access key from register 0 bits 24-27 */
233 akey = regs->GR_L(0) & 0x000000F0;
234
235 /* Priviliged operation exception if in problem state, and
236 the specified key is not permitted by the PSW key mask */
237 if ( PROBSTATE(®s->psw)
238 && ((regs->CR(3) << (akey >> 4)) & 0x80000000) == 0 )
239 regs->program_interrupt (regs, PGM_PRIVILEGED_OPERATION_EXCEPTION);
240
241 /* If register 0 bit 20 is one, use R0 key for operand 1 */
242 if (regs->GR_L(0) & 0x00000800)
243 akey1 = akey;
244
245 /* If register 0 bit 21 is one, use R0 key for operand 2 */
246 if (regs->GR_L(0) & 0x00000400)
247 akey2 = akey;
248 }
249
250 /* Specification exception if register 0 bits 16-19 are
251 not all zero, or if bits 20 and 21 are both ones */
252 if ((regs->GR_L(0) & 0x0000F000) != 0
253 || (regs->GR_L(0) & 0x00000C00) == 0x00000C00)
254 regs->program_interrupt (regs, PGM_SPECIFICATION_EXCEPTION);
255
256 /* Determine the logical addresses of each operand */
257 vaddr1 = regs->GR(r1) & ADDRESS_MAXWRAP(regs);
258 vaddr2 = regs->GR(r2) & ADDRESS_MAXWRAP(regs);
259
260 /* Isolate the page addresses of each operand */
261 vaddr1 &= XSTORE_PAGEMASK;
262 vaddr2 &= XSTORE_PAGEMASK;
263
264 /* Obtain the real or expanded address of each operand */
265 if ( !REAL_MODE(®s->psw) || SIE_MODE(regs) )
266 {
267 /* Translate the second operand address to a real address */
268 if(!REAL_MODE(®s->psw))
269 {
270 rc = ARCH_DEP(translate_addr) (vaddr2, r2, regs, ACCTYPE_READ);
271 raddr2 = regs->dat.raddr;
272 }
273 else
274 raddr2 = vaddr2;
275
276 if(rc != 0 && rc != 2)
277 goto mvpg_progck;
278
279 raddr2 = APPLY_PREFIXING (raddr2, regs->PX);
280
281 if (raddr2 > regs->mainlim)
282 regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION);
283
284 #if defined(_FEATURE_SIE)
285 if(SIE_MODE(regs) && !regs->sie_pref)
286 {
287
288 #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)
289 if (SIE_TRANSLATE_ADDR (regs->sie_mso + raddr2,
290 (SIE_STATB(regs, MX, XC) && AR_BIT(®s->psw) && r2 > 0)
291 ? r2 : USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE))
292 #else /*!defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/
293 if (SIE_TRANSLATE_ADDR (regs->sie_mso + raddr2,
294 USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE))
295 #endif /*!defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/
296 (regs->hostregs->program_interrupt) (regs->hostregs, regs->hostregs->dat.xcode);
297
298 /* Convert host real address to host absolute address */
299 raddr2 = APPLY_PREFIXING (regs->hostregs->dat.raddr, regs->hostregs->PX);
300 }
301 #endif /*defined(_FEATURE_SIE)*/
302
303 #if defined(FEATURE_EXPANDED_STORAGE)
304 if(rc == 2)
305 {
306 FETCH_W(pte2,regs->mainstor + raddr2);
307 /* If page is invalid in real storage but valid in expanded
308 storage then xpblk2 now contains expanded storage block# */
309 if(pte2 & PAGETAB_ESVALID)
310 {
311 xpblk2 = (pte2 & ZPGETAB_PFRA) >> 12;
312 #if defined(_FEATURE_SIE)
313 if(SIE_MODE(regs))
314 {
315 /* Add expanded storage origin for this guest */
316 xpblk2 += regs->sie_xso;
317 /* If the block lies beyond this guests limit
318 then we must terminate the instruction */
319 if(xpblk2 >= regs->sie_xsl)
320 {
321 cc = 2;
322 goto mvpg_progck;
323 }
324 }
325 #endif /*defined(_FEATURE_SIE)*/
326
327 rc = 0;
328 xpvalid2 = 1;
329 xpkeya = raddr2 +
330 #if defined(FEATURE_ESAME)
331 2048;
332 #else /*!defined(FEATURE_ESAME)*/
333 /* For ESA/390 mode, the XPTE lies directly beyond
334 the PTE, and each entry is 12 bytes long, we must
335 therefor add 1024 + 8 times the page index */
336 1024 + ((vaddr2 & 0x000FF000) >> 9);
337 #endif /*!defined(FEATURE_ESAME)*/
338 if (xpkeya > regs->mainlim)
339 regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION);
340 xpkey2 = regs->mainstor[xpkeya];
341
342 /*DEBUG logmsg("MVPG pte2 = " F_CREG ", xkey2 = %2.2X, xpblk2 = %5.5X, akey2 = %2.2X\n",
343 pte2,xpkey2,xpblk2,akey2); */
344
345 }
346 else
347 {
348 cc = 2;
349 goto mvpg_progck;
350 }
351 }
352 #endif /*defined(FEATURE_EXPANDED_STORAGE)*/
353
354 /* Program check if second operand is not valid
355 in either main storage or expanded storage */
356 if (rc)
357 {
358 cc = 2;
359 goto mvpg_progck;
360 }
361
362 /* Reset protection indication before calling translate_addr() */
363 regs->dat.protect = 0;
364 /* Translate the first operand address to a real address */
365 if(!REAL_MODE(®s->psw))
366 {
367 rc = ARCH_DEP(translate_addr) (vaddr1, r1, regs, ACCTYPE_WRITE);
368 raddr1 = regs->dat.raddr;
369 }
370 else
371 raddr1 = vaddr1;
372
373 if(rc != 0 && rc != 2)
374 goto mvpg_progck;
375
376 raddr1 = APPLY_PREFIXING (raddr1, regs->PX);
377
378 if (raddr1 > regs->mainlim)
379 regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION);
380
381 #if defined(_FEATURE_SIE)
382 if(SIE_MODE(regs) && !regs->sie_pref)
383 {
384 #if defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)
385 if (SIE_TRANSLATE_ADDR (regs->sie_mso + raddr1,
386 (SIE_STATB(regs, MX, XC) && AR_BIT(®s->psw) && r1 > 0)
387 ? r1 : USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE))
388 #else /*!defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/
389 if (SIE_TRANSLATE_ADDR (regs->sie_mso + raddr1,
390 USE_PRIMARY_SPACE, regs->hostregs, ACCTYPE_SIE))
391 #endif /*!defined(FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/
392 (regs->hostregs->program_interrupt) (regs->hostregs, regs->hostregs->dat.xcode);
393
394 /* Convert host real address to host absolute address */
395 raddr1 = APPLY_PREFIXING (regs->hostregs->dat.raddr, regs->hostregs->PX);
396 }
397 #endif /*defined(_FEATURE_SIE)*/
398
399 #if defined(FEATURE_EXPANDED_STORAGE)
400 if(rc == 2)
401 {
402 FETCH_W(pte1,regs->mainstor + raddr1);
403 /* If page is invalid in real storage but valid in expanded
404 storage then xpblk1 now contains expanded storage block# */
405 if(pte1 & PAGETAB_ESVALID)
406 {
407 xpblk1 = (pte1 & ZPGETAB_PFRA) >> 12;
408 #if defined(_FEATURE_SIE)
409 if(SIE_MODE(regs))
410 {
411 /* Add expanded storage origin for this guest */
412 xpblk1 += regs->sie_xso;
413 /* If the block lies beyond this guests limit
414 then we must terminate the instruction */
415 if(xpblk1 >= regs->sie_xsl)
416 {
417 cc = 1;
418 goto mvpg_progck;
419 }
420 }
421 #endif /*defined(_FEATURE_SIE)*/
422
423 rc = 0;
424 xpvalid1 = 1;
425 xpkeya = raddr1 +
426 #if defined(FEATURE_ESAME)
427 2048;
428 #else /*!defined(FEATURE_ESAME)*/
429 /* For ESA/390 mode, the XPTE lies directly beyond
430 the PTE, and each entry is 12 bytes long, we must
431 therefor add 1024 + 8 times the page index */
432 1024 + ((vaddr1 & 0x000FF000) >> 9);
433 #endif /*!defined(FEATURE_ESAME)*/
434 if (xpkeya > regs->mainlim)
435 regs->program_interrupt (regs, PGM_ADDRESSING_EXCEPTION);
436 xpkey1 = regs->mainstor[xpkeya];
437
438 /*DEBUG logmsg("MVPG pte1 = " F_CREG ", xkey1 = %2.2X, xpblk1 = %5.5X, akey1 = %2.2X\n",
439 pte1,xpkey1,xpblk1,akey1); */
440 }
441 else
442 {
443 cc = 1;
444 goto mvpg_progck;
445 }
446 }
447 #endif /*defined(FEATURE_EXPANDED_STORAGE)*/
448
449 /* Program check if operand not valid in main or expanded */
450 if (rc)
451 {
452 cc = 1;
453 goto mvpg_progck;
454 }
455
456 /* Program check if page protection or access-list controlled
457 protection applies to the first operand */
458 if (regs->dat.protect || (xpvalid1 && (pte1 & PAGETAB_PROT)))
459 {
460 regs->TEA = vaddr1 | TEA_PROT_AP | regs->dat.stid;
461 regs->excarid = (ACCESS_REGISTER_MODE(®s->psw)) ? r1 : 0;
462 regs->program_interrupt (regs, PGM_PROTECTION_EXCEPTION);
463 }
464
465 } /* end if(!REAL_MODE) */
466
467 #if defined(FEATURE_EXPANDED_STORAGE)
468 /* Program check if both operands are in expanded storage, or
469 if first operand is in expanded storage and the destination
470 reference intention (register 0 bit 22) is set to one, or
471 if first operand is in expanded storage and pte lock bit on, or
472 if first operand is in expanded storage and frame invalid */
473 if ((xpvalid1 && xpvalid2)
474 || (xpvalid1 && (regs->GR_L(0) & 0x00000200))
475 || (xpvalid1 && (pte1 & PAGETAB_PGLOCK))
476 || (xpvalid1 && (xpblk1 >= sysblk.xpndsize)))
477 {
478 regs->dat.xcode = PGM_PAGE_TRANSLATION_EXCEPTION;
479 rc = 2;
480 cc = 1;
481 goto mvpg_progck;
482 }
483 /* More Program check checking, but at lower priority:
484 if second operand is in expanded storage and pte lock bit on, or
485 if second operand is in expanded storage and frame invalid */
486 if ((xpvalid2 && (pte2 & PAGETAB_PGLOCK))
487 || (xpvalid2 && (xpblk2 >= sysblk.xpndsize)))
488 {
489 /* re-do translation to set up TEA */
490 rc = ARCH_DEP(translate_addr) (vaddr2, r2, regs, ACCTYPE_READ);
491 regs->dat.xcode = PGM_PAGE_TRANSLATION_EXCEPTION;
492 cc = 1;
493 goto mvpg_progck;
494 }
495
496 /* Perform protection checks */
497 if (xpvalid1)
498 {
499 /* Key check on expanded storage block if NoKey bit off in PTE */
500 if (akey1 != 0 && akey1 != (xpkey1 & STORKEY_KEY)
501 && (pte1 & PAGETAB_ESNK) == 0
502 && !((regs->CR(0) & CR0_STORE_OVRD) && ((xpkey1 & STORKEY_KEY) == 0x90)))
503 {
504 regs->program_interrupt (regs, PGM_PROTECTION_EXCEPTION);
505 }
506 sk1=NULL;
507 }
508 else
509 #endif /*defined(FEATURE_EXPANDED_STORAGE)*/
510 {
511 /* Obtain absolute address of main storage block,
512 check protection, and set reference and change bits */
513 main1 = MADDRL (vaddr1, 4096, r1, regs, ACCTYPE_WRITE_SKP, akey1);
514 sk1 = regs->dat.storkey;
515 }
516
517 #if defined(FEATURE_EXPANDED_STORAGE)
518 if (xpvalid2)
519 {
520 /* Key check on expanded storage block if NoKey bit off in PTE */
521 if (akey2 != 0 && (xpkey2 & STORKEY_FETCH)
522 && akey2 != (xpkey2 & STORKEY_KEY)
523 && (pte2 & PAGETAB_ESNK) == 0)
524 {
525 regs->program_interrupt (regs, PGM_PROTECTION_EXCEPTION);
526 }
527 }
528 else
529 #endif /*defined(FEATURE_EXPANDED_STORAGE)*/
530 {
531 /* Obtain absolute address of main storage block,
532 check protection, and set reference bit.
533 Use last byte of page to avoid FPO area. */
534 main2 = MADDR (vaddr2 | 0xFFF, r2, regs, ACCTYPE_READ, akey2);
535 main2 -= 0xFFF;
536 }
537
538 #if defined(FEATURE_EXPANDED_STORAGE)
539 /* Perform page movement */
540 if (xpvalid2)
541 {
542 /* Set the main storage reference and change bits */
543 *sk1 |= (STORKEY_REF | STORKEY_CHANGE);
544
545 /* Set Expanded Storage reference bit in the PTE */
546 STORE_W(regs->mainstor + raddr2, pte2 | PAGETAB_ESREF);
547
548
549 /* Move 4K bytes from expanded storage to main storage */
550 memcpy (main1,
551 sysblk.xpndstor + ((size_t)xpblk2 << XSTORE_PAGESHIFT),
552 XSTORE_PAGESIZE);
553 }
554 else if (xpvalid1)
555 {
556 /* Set Expanded Storage reference and change bits in the PTE */
557 STORE_W(regs->mainstor + raddr1, pte1 | PAGETAB_ESREF | PAGETAB_ESCHA);
558
559 /* Move 4K bytes from main storage to expanded storage */
560 memcpy (sysblk.xpndstor + ((size_t)xpblk1 << XSTORE_PAGESHIFT),
561 main2,
562 XSTORE_PAGESIZE);
563 }
564 else
565 #endif /*defined(FEATURE_EXPANDED_STORAGE)*/
566 {
567 /* Set the main storage reference and change bits */
568 *sk1 |= (STORKEY_REF | STORKEY_CHANGE);
569
570 /* Move 4K bytes from main storage to main storage */
571 memcpy (main1, main2, XSTORE_PAGESIZE);
572 }
573
574 /* Return condition code zero */
575 regs->psw.cc = 0;
576 return;
577
578 mvpg_progck:
579
580 PTT(PTT_CL_ERR,"*MVPG",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
581
582 /* If page translation exception (PTE invalid) and condition code
583 option in register 0 bit 23 is set, return condition code */
584 if ((regs->GR_L(0) & 0x00000100)
585 && regs->dat.xcode == PGM_PAGE_TRANSLATION_EXCEPTION
586 && rc == 2)
587 {
588 regs->psw.cc = cc;
589 return;
590 }
591
592 /* Otherwise generate program check */
593 /* (Bit 29 of TEA is on for PIC 11 & operand ID also stored) */
594 if (regs->dat.xcode == PGM_PAGE_TRANSLATION_EXCEPTION)
595 {
596 regs->TEA |= TEA_MVPG;
597 regs->opndrid = (r1 << 4) | r2;
598 }
599 regs->program_interrupt (regs, regs->dat.xcode);
600
601 } /* end DEF_INST(move_page) */
602 #endif /*defined(FEATURE_MOVE_PAGE_FACILITY_2)*/
603
604 #if defined(_MSVC_)
605 /* Workaround for "fatal error C1001: INTERNAL COMPILER ERROR" in MSVC */
606 #pragma optimize("",on)
607 #endif /*defined(_MSVC_)*/
608
609
610 #if !defined(_GEN_ARCH)
611
612 #if defined(_ARCHMODE2)
613 #define _GEN_ARCH _ARCHMODE2
614 #include "xstore.c"
615 #endif
616
617 #if defined(_ARCHMODE3)
618 #undef _GEN_ARCH
619 #define _GEN_ARCH _ARCHMODE3
620 #include "xstore.c"
621 #endif
622
623 #endif /*!defined(_GEN_ARCH)*/
624