]>
git.proxmox.com Git - qemu.git/blob - target-sparc/op_helper.c
48f5fc60044f28556ade3c7f514d7f36c000d307
2 #include "host-utils.h"
7 //#define DEBUG_UNALIGNED
8 //#define DEBUG_UNASSIGNED
11 #define DPRINTF_MMU(fmt, args...) \
12 do { printf("MMU: " fmt , ##args); } while (0)
14 #define DPRINTF_MMU(fmt, args...)
18 #define DPRINTF_MXCC(fmt, args...) \
19 do { printf("MXCC: " fmt , ##args); } while (0)
21 #define DPRINTF_MXCC(fmt, args...)
24 void raise_exception(int tt
)
26 env
->exception_index
= tt
;
30 void check_ieee_exceptions()
32 T0
= get_float_exception_flags(&env
->fp_status
);
35 /* Copy IEEE 754 flags into FSR */
36 if (T0
& float_flag_invalid
)
38 if (T0
& float_flag_overflow
)
40 if (T0
& float_flag_underflow
)
42 if (T0
& float_flag_divbyzero
)
44 if (T0
& float_flag_inexact
)
47 if ((env
->fsr
& FSR_CEXC_MASK
) & ((env
->fsr
& FSR_TEM_MASK
) >> 23))
49 /* Unmasked exception, generate a trap */
50 env
->fsr
|= FSR_FTT_IEEE_EXCP
;
51 raise_exception(TT_FP_EXCP
);
55 /* Accumulate exceptions */
56 env
->fsr
|= (env
->fsr
& FSR_CEXC_MASK
) << 5;
61 #ifdef USE_INT_TO_FLOAT_HELPERS
64 set_float_exception_flags(0, &env
->fp_status
);
65 FT0
= int32_to_float32(*((int32_t *)&FT1
), &env
->fp_status
);
66 check_ieee_exceptions();
71 DT0
= int32_to_float64(*((int32_t *)&FT1
), &env
->fp_status
);
76 set_float_exception_flags(0, &env
->fp_status
);
77 FT0
= int64_to_float32(*((int64_t *)&DT1
), &env
->fp_status
);
78 check_ieee_exceptions();
83 set_float_exception_flags(0, &env
->fp_status
);
84 DT0
= int64_to_float64(*((int64_t *)&DT1
), &env
->fp_status
);
85 check_ieee_exceptions();
92 FT0
= float32_abs(FT1
);
98 DT0
= float64_abs(DT1
);
101 #if defined(CONFIG_USER_ONLY)
104 QT0
= float128_abs(QT1
);
111 set_float_exception_flags(0, &env
->fp_status
);
112 FT0
= float32_sqrt(FT1
, &env
->fp_status
);
113 check_ieee_exceptions();
118 set_float_exception_flags(0, &env
->fp_status
);
119 DT0
= float64_sqrt(DT1
, &env
->fp_status
);
120 check_ieee_exceptions();
123 #if defined(CONFIG_USER_ONLY)
126 set_float_exception_flags(0, &env
->fp_status
);
127 QT0
= float128_sqrt(QT1
, &env
->fp_status
);
128 check_ieee_exceptions();
132 #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
133 void glue(do_, name) (void) \
135 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
136 switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
137 case float_relation_unordered: \
138 T0 = (FSR_FCC1 | FSR_FCC0) << FS; \
139 if ((env->fsr & FSR_NVM) || TRAP) { \
141 env->fsr |= FSR_NVC; \
142 env->fsr |= FSR_FTT_IEEE_EXCP; \
143 raise_exception(TT_FP_EXCP); \
145 env->fsr |= FSR_NVA; \
148 case float_relation_less: \
149 T0 = FSR_FCC0 << FS; \
151 case float_relation_greater: \
152 T0 = FSR_FCC1 << FS; \
161 GEN_FCMP(fcmps
, float32
, FT0
, FT1
, 0, 0);
162 GEN_FCMP(fcmpd
, float64
, DT0
, DT1
, 0, 0);
164 GEN_FCMP(fcmpes
, float32
, FT0
, FT1
, 0, 1);
165 GEN_FCMP(fcmped
, float64
, DT0
, DT1
, 0, 1);
167 #ifdef CONFIG_USER_ONLY
168 GEN_FCMP(fcmpq
, float128
, QT0
, QT1
, 0, 0);
169 GEN_FCMP(fcmpeq
, float128
, QT0
, QT1
, 0, 1);
172 #ifdef TARGET_SPARC64
173 GEN_FCMP(fcmps_fcc1
, float32
, FT0
, FT1
, 22, 0);
174 GEN_FCMP(fcmpd_fcc1
, float64
, DT0
, DT1
, 22, 0);
176 GEN_FCMP(fcmps_fcc2
, float32
, FT0
, FT1
, 24, 0);
177 GEN_FCMP(fcmpd_fcc2
, float64
, DT0
, DT1
, 24, 0);
179 GEN_FCMP(fcmps_fcc3
, float32
, FT0
, FT1
, 26, 0);
180 GEN_FCMP(fcmpd_fcc3
, float64
, DT0
, DT1
, 26, 0);
182 GEN_FCMP(fcmpes_fcc1
, float32
, FT0
, FT1
, 22, 1);
183 GEN_FCMP(fcmped_fcc1
, float64
, DT0
, DT1
, 22, 1);
185 GEN_FCMP(fcmpes_fcc2
, float32
, FT0
, FT1
, 24, 1);
186 GEN_FCMP(fcmped_fcc2
, float64
, DT0
, DT1
, 24, 1);
188 GEN_FCMP(fcmpes_fcc3
, float32
, FT0
, FT1
, 26, 1);
189 GEN_FCMP(fcmped_fcc3
, float64
, DT0
, DT1
, 26, 1);
190 #ifdef CONFIG_USER_ONLY
191 GEN_FCMP(fcmpq_fcc1
, float128
, QT0
, QT1
, 22, 0);
192 GEN_FCMP(fcmpq_fcc2
, float128
, QT0
, QT1
, 24, 0);
193 GEN_FCMP(fcmpq_fcc3
, float128
, QT0
, QT1
, 26, 0);
194 GEN_FCMP(fcmpeq_fcc1
, float128
, QT0
, QT1
, 22, 1);
195 GEN_FCMP(fcmpeq_fcc2
, float128
, QT0
, QT1
, 24, 1);
196 GEN_FCMP(fcmpeq_fcc3
, float128
, QT0
, QT1
, 26, 1);
200 #ifndef TARGET_SPARC64
201 #ifndef CONFIG_USER_ONLY
204 static void dump_mxcc(CPUState
*env
)
206 printf("mxccdata: %016llx %016llx %016llx %016llx\n",
207 env
->mxccdata
[0], env
->mxccdata
[1], env
->mxccdata
[2], env
->mxccdata
[3]);
208 printf("mxccregs: %016llx %016llx %016llx %016llx\n"
209 " %016llx %016llx %016llx %016llx\n",
210 env
->mxccregs
[0], env
->mxccregs
[1], env
->mxccregs
[2], env
->mxccregs
[3],
211 env
->mxccregs
[4], env
->mxccregs
[5], env
->mxccregs
[6], env
->mxccregs
[7]);
215 void helper_ld_asi(int asi
, int size
, int sign
)
220 uint32_t last_T0
= T0
;
224 case 2: /* SuperSparc MXCC registers */
226 case 0x01c00a00: /* MXCC control register */
228 ret
= env
->mxccregs
[3] >> 32;
229 T0
= env
->mxccregs
[3];
231 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
233 case 0x01c00a04: /* MXCC control register */
235 ret
= env
->mxccregs
[3];
237 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
239 case 0x01c00c00: /* Module reset register */
241 ret
= env
->mxccregs
[5] >> 32;
242 T0
= env
->mxccregs
[5];
243 // should we do something here?
245 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
247 case 0x01c00f00: /* MBus port address register */
249 ret
= env
->mxccregs
[7] >> 32;
250 T0
= env
->mxccregs
[7];
252 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
255 DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0
, size
);
258 DPRINTF_MXCC("asi = %d, size = %d, sign = %d, T0 = %08x -> ret = %08x,"
259 "T0 = %08x\n", asi
, size
, sign
, last_T0
, ret
, T0
);
264 case 3: /* MMU probe */
268 mmulev
= (T0
>> 8) & 15;
272 ret
= mmu_probe(env
, T0
, mmulev
);
275 DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0
, mmulev
, ret
);
278 case 4: /* read MMU regs */
280 int reg
= (T0
>> 8) & 0x1f;
282 ret
= env
->mmuregs
[reg
];
283 if (reg
== 3) /* Fault status cleared on read */
285 else if (reg
== 0x13) /* Fault status read */
286 ret
= env
->mmuregs
[3];
287 else if (reg
== 0x14) /* Fault address read */
288 ret
= env
->mmuregs
[4];
289 DPRINTF_MMU("mmu_read: reg[%d] = 0x%08x\n", reg
, ret
);
292 case 9: /* Supervisor code access */
298 ret
= lduw_code(T0
& ~1);
302 ret
= ldl_code(T0
& ~3);
305 tmp
= ldq_code(T0
& ~7);
311 case 0xa: /* User data access */
317 ret
= lduw_user(T0
& ~1);
321 ret
= ldl_user(T0
& ~3);
324 tmp
= ldq_user(T0
& ~7);
330 case 0xb: /* Supervisor data access */
333 ret
= ldub_kernel(T0
);
336 ret
= lduw_kernel(T0
& ~1);
340 ret
= ldl_kernel(T0
& ~3);
343 tmp
= ldq_kernel(T0
& ~7);
349 case 0xc: /* I-cache tag */
350 case 0xd: /* I-cache data */
351 case 0xe: /* D-cache tag */
352 case 0xf: /* D-cache data */
354 case 0x20: /* MMU passthrough */
360 ret
= lduw_phys(T0
& ~1);
364 ret
= ldl_phys(T0
& ~3);
367 tmp
= ldq_phys(T0
& ~7);
373 case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
374 case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
377 ret
= ldub_phys((target_phys_addr_t
)T0
378 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
381 ret
= lduw_phys((target_phys_addr_t
)(T0
& ~1)
382 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
386 ret
= ldl_phys((target_phys_addr_t
)(T0
& ~3)
387 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
390 tmp
= ldq_phys((target_phys_addr_t
)(T0
& ~7)
391 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
397 case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
399 do_unassigned_access(T0
, 0, 0, 1);
420 void helper_st_asi(int asi
, int size
)
423 case 2: /* SuperSparc MXCC registers */
425 case 0x01c00000: /* MXCC stream data register 0 */
427 env
->mxccdata
[0] = ((uint64_t)T1
<< 32) | T2
;
429 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
431 case 0x01c00008: /* MXCC stream data register 1 */
433 env
->mxccdata
[1] = ((uint64_t)T1
<< 32) | T2
;
435 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
437 case 0x01c00010: /* MXCC stream data register 2 */
439 env
->mxccdata
[2] = ((uint64_t)T1
<< 32) | T2
;
441 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
443 case 0x01c00018: /* MXCC stream data register 3 */
445 env
->mxccdata
[3] = ((uint64_t)T1
<< 32) | T2
;
447 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
449 case 0x01c00100: /* MXCC stream source */
451 env
->mxccregs
[0] = ((uint64_t)T1
<< 32) | T2
;
453 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
454 env
->mxccdata
[0] = ldq_phys((env
->mxccregs
[0] & 0xffffffffULL
) + 0);
455 env
->mxccdata
[1] = ldq_phys((env
->mxccregs
[0] & 0xffffffffULL
) + 8);
456 env
->mxccdata
[2] = ldq_phys((env
->mxccregs
[0] & 0xffffffffULL
) + 16);
457 env
->mxccdata
[3] = ldq_phys((env
->mxccregs
[0] & 0xffffffffULL
) + 24);
459 case 0x01c00200: /* MXCC stream destination */
461 env
->mxccregs
[1] = ((uint64_t)T1
<< 32) | T2
;
463 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
464 stq_phys((env
->mxccregs
[1] & 0xffffffffULL
) + 0, env
->mxccdata
[0]);
465 stq_phys((env
->mxccregs
[1] & 0xffffffffULL
) + 8, env
->mxccdata
[1]);
466 stq_phys((env
->mxccregs
[1] & 0xffffffffULL
) + 16, env
->mxccdata
[2]);
467 stq_phys((env
->mxccregs
[1] & 0xffffffffULL
) + 24, env
->mxccdata
[3]);
469 case 0x01c00a00: /* MXCC control register */
471 env
->mxccregs
[3] = ((uint64_t)T1
<< 32) | T2
;
473 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
475 case 0x01c00a04: /* MXCC control register */
477 env
->mxccregs
[3] = (env
->mxccregs
[0xa] & 0xffffffff00000000ULL
) | T1
;
479 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
481 case 0x01c00e00: /* MXCC error register */
482 // writing a 1 bit clears the error
484 env
->mxccregs
[6] &= ~(((uint64_t)T1
<< 32) | T2
);
486 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
488 case 0x01c00f00: /* MBus port address register */
490 env
->mxccregs
[7] = ((uint64_t)T1
<< 32) | T2
;
492 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
495 DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0
, size
);
498 DPRINTF_MXCC("asi = %d, size = %d, T0 = %08x, T1 = %08x\n", asi
, size
, T0
, T1
);
503 case 3: /* MMU flush */
507 mmulev
= (T0
>> 8) & 15;
508 DPRINTF_MMU("mmu flush level %d\n", mmulev
);
510 case 0: // flush page
511 tlb_flush_page(env
, T0
& 0xfffff000);
513 case 1: // flush segment (256k)
514 case 2: // flush region (16M)
515 case 3: // flush context (4G)
516 case 4: // flush entire
527 case 4: /* write MMU regs */
529 int reg
= (T0
>> 8) & 0x1f;
532 oldreg
= env
->mmuregs
[reg
];
535 env
->mmuregs
[reg
] = (env
->mmuregs
[reg
] & 0xff000000) |
537 // Mappings generated during no-fault mode or MMU
538 // disabled mode are invalid in normal mode
539 if ((oldreg
& (MMU_E
| MMU_NF
| env
->mmu_bm
)) !=
540 (env
->mmuregs
[reg
] & (MMU_E
| MMU_NF
| env
->mmu_bm
)))
544 env
->mmuregs
[reg
] = T1
;
545 if (oldreg
!= env
->mmuregs
[reg
]) {
546 /* we flush when the MMU context changes because
547 QEMU has no MMU context support */
555 env
->mmuregs
[3] = T1
;
558 env
->mmuregs
[4] = T1
;
561 env
->mmuregs
[reg
] = T1
;
564 if (oldreg
!= env
->mmuregs
[reg
]) {
565 DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg
, oldreg
, env
->mmuregs
[reg
]);
572 case 0xa: /* User data access */
578 stw_user(T0
& ~1, T1
);
582 stl_user(T0
& ~3, T1
);
585 stq_user(T0
& ~7, ((uint64_t)T1
<< 32) | T2
);
589 case 0xb: /* Supervisor data access */
595 stw_kernel(T0
& ~1, T1
);
599 stl_kernel(T0
& ~3, T1
);
602 stq_kernel(T0
& ~7, ((uint64_t)T1
<< 32) | T2
);
606 case 0xc: /* I-cache tag */
607 case 0xd: /* I-cache data */
608 case 0xe: /* D-cache tag */
609 case 0xf: /* D-cache data */
610 case 0x10: /* I/D-cache flush page */
611 case 0x11: /* I/D-cache flush segment */
612 case 0x12: /* I/D-cache flush region */
613 case 0x13: /* I/D-cache flush context */
614 case 0x14: /* I/D-cache flush user */
616 case 0x17: /* Block copy, sta access */
619 // address (T0) = dst
622 uint32_t src
= T1
& ~3, dst
= T0
& ~3, temp
;
624 for (i
= 0; i
< 32; i
+= 4, src
+= 4, dst
+= 4) {
625 temp
= ldl_kernel(src
);
626 stl_kernel(dst
, temp
);
630 case 0x1f: /* Block fill, stda access */
633 // address (T0) = dst
636 uint32_t dst
= T0
& 7;
639 val
= (((uint64_t)T1
) << 32) | T2
;
641 for (i
= 0; i
< 32; i
+= 8, dst
+= 8)
642 stq_kernel(dst
, val
);
645 case 0x20: /* MMU passthrough */
652 stw_phys(T0
& ~1, T1
);
656 stl_phys(T0
& ~3, T1
);
659 stq_phys(T0
& ~7, ((uint64_t)T1
<< 32) | T2
);
664 case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
665 case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
669 stb_phys((target_phys_addr_t
)T0
670 | ((target_phys_addr_t
)(asi
& 0xf) << 32), T1
);
673 stw_phys((target_phys_addr_t
)(T0
& ~1)
674 | ((target_phys_addr_t
)(asi
& 0xf) << 32), T1
);
678 stl_phys((target_phys_addr_t
)(T0
& ~3)
679 | ((target_phys_addr_t
)(asi
& 0xf) << 32), T1
);
682 stq_phys((target_phys_addr_t
)(T0
& ~7)
683 | ((target_phys_addr_t
)(asi
& 0xf) << 32),
684 ((uint64_t)T1
<< 32) | T2
);
689 case 0x31: /* Ross RT620 I-cache flush */
690 case 0x36: /* I-cache flash clear */
691 case 0x37: /* D-cache flash clear */
693 case 9: /* Supervisor code access, XXX */
694 case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
696 do_unassigned_access(T0
, 1, 0, 1);
701 #endif /* CONFIG_USER_ONLY */
702 #else /* TARGET_SPARC64 */
704 #ifdef CONFIG_USER_ONLY
705 void helper_ld_asi(int asi
, int size
, int sign
)
710 raise_exception(TT_PRIV_ACT
);
713 case 0x80: // Primary
714 case 0x82: // Primary no-fault
715 case 0x88: // Primary LE
716 case 0x8a: // Primary no-fault LE
723 ret
= lduw_raw(T0
& ~1);
726 ret
= ldl_raw(T0
& ~3);
730 ret
= ldq_raw(T0
& ~7);
735 case 0x81: // Secondary
736 case 0x83: // Secondary no-fault
737 case 0x89: // Secondary LE
738 case 0x8b: // Secondary no-fault LE
745 /* Convert from little endian */
747 case 0x88: // Primary LE
748 case 0x89: // Secondary LE
749 case 0x8a: // Primary no-fault LE
750 case 0x8b: // Secondary no-fault LE
768 /* Convert to signed number */
787 void helper_st_asi(int asi
, int size
)
790 raise_exception(TT_PRIV_ACT
);
792 /* Convert to little endian */
794 case 0x88: // Primary LE
795 case 0x89: // Secondary LE
814 case 0x80: // Primary
815 case 0x88: // Primary LE
822 stw_raw(T0
& ~1, T1
);
825 stl_raw(T0
& ~3, T1
);
829 stq_raw(T0
& ~7, T1
);
834 case 0x81: // Secondary
835 case 0x89: // Secondary LE
839 case 0x82: // Primary no-fault, RO
840 case 0x83: // Secondary no-fault, RO
841 case 0x8a: // Primary no-fault LE, RO
842 case 0x8b: // Secondary no-fault LE, RO
844 do_unassigned_access(T0
, 1, 0, 1);
849 #else /* CONFIG_USER_ONLY */
851 void helper_ld_asi(int asi
, int size
, int sign
)
855 if ((asi
< 0x80 && (env
->pstate
& PS_PRIV
) == 0)
856 || (asi
>= 0x30 && asi
< 0x80 && !(env
->hpstate
& HS_PRIV
)))
857 raise_exception(TT_PRIV_ACT
);
860 case 0x10: // As if user primary
861 case 0x18: // As if user primary LE
862 case 0x80: // Primary
863 case 0x82: // Primary no-fault
864 case 0x88: // Primary LE
865 case 0x8a: // Primary no-fault LE
866 if ((asi
& 0x80) && (env
->pstate
& PS_PRIV
)) {
867 if (env
->hpstate
& HS_PRIV
) {
873 ret
= lduw_hypv(T0
& ~1);
876 ret
= ldl_hypv(T0
& ~3);
880 ret
= ldq_hypv(T0
& ~7);
886 ret
= ldub_kernel(T0
);
889 ret
= lduw_kernel(T0
& ~1);
892 ret
= ldl_kernel(T0
& ~3);
896 ret
= ldq_kernel(T0
& ~7);
906 ret
= lduw_user(T0
& ~1);
909 ret
= ldl_user(T0
& ~3);
913 ret
= ldq_user(T0
& ~7);
919 case 0x15: // Bypass, non-cacheable
920 case 0x1c: // Bypass LE
921 case 0x1d: // Bypass, non-cacheable LE
928 ret
= lduw_phys(T0
& ~1);
931 ret
= ldl_phys(T0
& ~3);
935 ret
= ldq_phys(T0
& ~7);
940 case 0x04: // Nucleus
941 case 0x0c: // Nucleus Little Endian (LE)
942 case 0x11: // As if user secondary
943 case 0x19: // As if user secondary LE
944 case 0x24: // Nucleus quad LDD 128 bit atomic
945 case 0x2c: // Nucleus quad LDD 128 bit atomic
946 case 0x4a: // UPA config
947 case 0x81: // Secondary
948 case 0x83: // Secondary no-fault
949 case 0x89: // Secondary LE
950 case 0x8b: // Secondary no-fault LE
956 case 0x50: // I-MMU regs
958 int reg
= (T0
>> 3) & 0xf;
960 ret
= env
->immuregs
[reg
];
963 case 0x51: // I-MMU 8k TSB pointer
964 case 0x52: // I-MMU 64k TSB pointer
965 case 0x55: // I-MMU data access
968 case 0x56: // I-MMU tag read
972 for (i
= 0; i
< 64; i
++) {
973 // Valid, ctx match, vaddr match
974 if ((env
->itlb_tte
[i
] & 0x8000000000000000ULL
) != 0 &&
975 env
->itlb_tag
[i
] == T0
) {
976 ret
= env
->itlb_tag
[i
];
982 case 0x58: // D-MMU regs
984 int reg
= (T0
>> 3) & 0xf;
986 ret
= env
->dmmuregs
[reg
];
989 case 0x5e: // D-MMU tag read
993 for (i
= 0; i
< 64; i
++) {
994 // Valid, ctx match, vaddr match
995 if ((env
->dtlb_tte
[i
] & 0x8000000000000000ULL
) != 0 &&
996 env
->dtlb_tag
[i
] == T0
) {
997 ret
= env
->dtlb_tag
[i
];
1003 case 0x59: // D-MMU 8k TSB pointer
1004 case 0x5a: // D-MMU 64k TSB pointer
1005 case 0x5b: // D-MMU data pointer
1006 case 0x5d: // D-MMU data access
1007 case 0x48: // Interrupt dispatch, RO
1008 case 0x49: // Interrupt data receive
1009 case 0x7f: // Incoming interrupt vector, RO
1012 case 0x54: // I-MMU data in, WO
1013 case 0x57: // I-MMU demap, WO
1014 case 0x5c: // D-MMU data in, WO
1015 case 0x5f: // D-MMU demap, WO
1016 case 0x77: // Interrupt vector, WO
1018 do_unassigned_access(T0
, 0, 0, 1);
1023 /* Convert from little endian */
1025 case 0x0c: // Nucleus Little Endian (LE)
1026 case 0x18: // As if user primary LE
1027 case 0x19: // As if user secondary LE
1028 case 0x1c: // Bypass LE
1029 case 0x1d: // Bypass, non-cacheable LE
1030 case 0x88: // Primary LE
1031 case 0x89: // Secondary LE
1032 case 0x8a: // Primary no-fault LE
1033 case 0x8b: // Secondary no-fault LE
1051 /* Convert to signed number */
1058 ret
= (int16_t) ret
;
1061 ret
= (int32_t) ret
;
1070 void helper_st_asi(int asi
, int size
)
1072 if ((asi
< 0x80 && (env
->pstate
& PS_PRIV
) == 0)
1073 || (asi
>= 0x30 && asi
< 0x80 && !(env
->hpstate
& HS_PRIV
)))
1074 raise_exception(TT_PRIV_ACT
);
1076 /* Convert to little endian */
1078 case 0x0c: // Nucleus Little Endian (LE)
1079 case 0x18: // As if user primary LE
1080 case 0x19: // As if user secondary LE
1081 case 0x1c: // Bypass LE
1082 case 0x1d: // Bypass, non-cacheable LE
1083 case 0x88: // Primary LE
1084 case 0x89: // Secondary LE
1103 case 0x10: // As if user primary
1104 case 0x18: // As if user primary LE
1105 case 0x80: // Primary
1106 case 0x88: // Primary LE
1107 if ((asi
& 0x80) && (env
->pstate
& PS_PRIV
)) {
1108 if (env
->hpstate
& HS_PRIV
) {
1114 stw_hypv(T0
& ~1, T1
);
1117 stl_hypv(T0
& ~3, T1
);
1121 stq_hypv(T0
& ~7, T1
);
1130 stw_kernel(T0
& ~1, T1
);
1133 stl_kernel(T0
& ~3, T1
);
1137 stq_kernel(T0
& ~7, T1
);
1147 stw_user(T0
& ~1, T1
);
1150 stl_user(T0
& ~3, T1
);
1154 stq_user(T0
& ~7, T1
);
1159 case 0x14: // Bypass
1160 case 0x15: // Bypass, non-cacheable
1161 case 0x1c: // Bypass LE
1162 case 0x1d: // Bypass, non-cacheable LE
1169 stw_phys(T0
& ~1, T1
);
1172 stl_phys(T0
& ~3, T1
);
1176 stq_phys(T0
& ~7, T1
);
1181 case 0x04: // Nucleus
1182 case 0x0c: // Nucleus Little Endian (LE)
1183 case 0x11: // As if user secondary
1184 case 0x19: // As if user secondary LE
1185 case 0x24: // Nucleus quad LDD 128 bit atomic
1186 case 0x2c: // Nucleus quad LDD 128 bit atomic
1187 case 0x4a: // UPA config
1188 case 0x81: // Secondary
1189 case 0x89: // Secondary LE
1197 env
->lsu
= T1
& (DMMU_E
| IMMU_E
);
1198 // Mappings generated during D/I MMU disabled mode are
1199 // invalid in normal mode
1200 if (oldreg
!= env
->lsu
) {
1201 DPRINTF_MMU("LSU change: 0x%" PRIx64
" -> 0x%" PRIx64
"\n", oldreg
, env
->lsu
);
1209 case 0x50: // I-MMU regs
1211 int reg
= (T0
>> 3) & 0xf;
1214 oldreg
= env
->immuregs
[reg
];
1219 case 1: // Not in I-MMU
1226 T1
= 0; // Clear SFSR
1228 case 5: // TSB access
1229 case 6: // Tag access
1233 env
->immuregs
[reg
] = T1
;
1234 if (oldreg
!= env
->immuregs
[reg
]) {
1235 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64
" -> 0x%08" PRIx64
"\n", reg
, oldreg
, env
->immuregs
[reg
]);
1242 case 0x54: // I-MMU data in
1246 // Try finding an invalid entry
1247 for (i
= 0; i
< 64; i
++) {
1248 if ((env
->itlb_tte
[i
] & 0x8000000000000000ULL
) == 0) {
1249 env
->itlb_tag
[i
] = env
->immuregs
[6];
1250 env
->itlb_tte
[i
] = T1
;
1254 // Try finding an unlocked entry
1255 for (i
= 0; i
< 64; i
++) {
1256 if ((env
->itlb_tte
[i
] & 0x40) == 0) {
1257 env
->itlb_tag
[i
] = env
->immuregs
[6];
1258 env
->itlb_tte
[i
] = T1
;
1265 case 0x55: // I-MMU data access
1267 unsigned int i
= (T0
>> 3) & 0x3f;
1269 env
->itlb_tag
[i
] = env
->immuregs
[6];
1270 env
->itlb_tte
[i
] = T1
;
1273 case 0x57: // I-MMU demap
1276 case 0x58: // D-MMU regs
1278 int reg
= (T0
>> 3) & 0xf;
1281 oldreg
= env
->dmmuregs
[reg
];
1287 if ((T1
& 1) == 0) {
1288 T1
= 0; // Clear SFSR, Fault address
1289 env
->dmmuregs
[4] = 0;
1291 env
->dmmuregs
[reg
] = T1
;
1293 case 1: // Primary context
1294 case 2: // Secondary context
1295 case 5: // TSB access
1296 case 6: // Tag access
1297 case 7: // Virtual Watchpoint
1298 case 8: // Physical Watchpoint
1302 env
->dmmuregs
[reg
] = T1
;
1303 if (oldreg
!= env
->dmmuregs
[reg
]) {
1304 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64
" -> 0x%08" PRIx64
"\n", reg
, oldreg
, env
->dmmuregs
[reg
]);
1311 case 0x5c: // D-MMU data in
1315 // Try finding an invalid entry
1316 for (i
= 0; i
< 64; i
++) {
1317 if ((env
->dtlb_tte
[i
] & 0x8000000000000000ULL
) == 0) {
1318 env
->dtlb_tag
[i
] = env
->dmmuregs
[6];
1319 env
->dtlb_tte
[i
] = T1
;
1323 // Try finding an unlocked entry
1324 for (i
= 0; i
< 64; i
++) {
1325 if ((env
->dtlb_tte
[i
] & 0x40) == 0) {
1326 env
->dtlb_tag
[i
] = env
->dmmuregs
[6];
1327 env
->dtlb_tte
[i
] = T1
;
1334 case 0x5d: // D-MMU data access
1336 unsigned int i
= (T0
>> 3) & 0x3f;
1338 env
->dtlb_tag
[i
] = env
->dmmuregs
[6];
1339 env
->dtlb_tte
[i
] = T1
;
1342 case 0x5f: // D-MMU demap
1343 case 0x49: // Interrupt data receive
1346 case 0x51: // I-MMU 8k TSB pointer, RO
1347 case 0x52: // I-MMU 64k TSB pointer, RO
1348 case 0x56: // I-MMU tag read, RO
1349 case 0x59: // D-MMU 8k TSB pointer, RO
1350 case 0x5a: // D-MMU 64k TSB pointer, RO
1351 case 0x5b: // D-MMU data pointer, RO
1352 case 0x5e: // D-MMU tag read, RO
1353 case 0x48: // Interrupt dispatch, RO
1354 case 0x7f: // Incoming interrupt vector, RO
1355 case 0x82: // Primary no-fault, RO
1356 case 0x83: // Secondary no-fault, RO
1357 case 0x8a: // Primary no-fault LE, RO
1358 case 0x8b: // Secondary no-fault LE, RO
1360 do_unassigned_access(T0
, 1, 0, 1);
1364 #endif /* CONFIG_USER_ONLY */
1366 void helper_ldf_asi(int asi
, int size
, int rd
)
1368 target_ulong tmp_T0
= T0
, tmp_T1
= T1
;
1372 case 0xf0: // Block load primary
1373 case 0xf1: // Block load secondary
1374 case 0xf8: // Block load primary LE
1375 case 0xf9: // Block load secondary LE
1377 raise_exception(TT_ILL_INSN
);
1381 raise_exception(TT_UNALIGNED
);
1384 for (i
= 0; i
< 16; i
++) {
1385 helper_ld_asi(asi
& 0x8f, 4, 0);
1386 *(uint32_t *)&env
->fpr
[rd
++] = T1
;
1397 helper_ld_asi(asi
, size
, 0);
1401 *((uint32_t *)&FT0
) = T1
;
1404 *((int64_t *)&DT0
) = T1
;
1406 #if defined(CONFIG_USER_ONLY)
1415 void helper_stf_asi(int asi
, int size
, int rd
)
1417 target_ulong tmp_T0
= T0
, tmp_T1
= T1
;
1421 case 0xf0: // Block store primary
1422 case 0xf1: // Block store secondary
1423 case 0xf8: // Block store primary LE
1424 case 0xf9: // Block store secondary LE
1426 raise_exception(TT_ILL_INSN
);
1430 raise_exception(TT_UNALIGNED
);
1433 for (i
= 0; i
< 16; i
++) {
1434 T1
= *(uint32_t *)&env
->fpr
[rd
++];
1435 helper_st_asi(asi
& 0x8f, 4);
1449 T1
= *((uint32_t *)&FT0
);
1452 T1
= *((int64_t *)&DT0
);
1454 #if defined(CONFIG_USER_ONLY)
1460 helper_st_asi(asi
, size
);
1464 #endif /* TARGET_SPARC64 */
1466 #ifndef TARGET_SPARC64
1471 if (env
->psret
== 1)
1472 raise_exception(TT_ILL_INSN
);
1475 cwp
= (env
->cwp
+ 1) & (NWINDOWS
- 1);
1476 if (env
->wim
& (1 << cwp
)) {
1477 raise_exception(TT_WIN_UNF
);
1480 env
->psrs
= env
->psrps
;
1484 void helper_ldfsr(void)
1487 switch (env
->fsr
& FSR_RD_MASK
) {
1488 case FSR_RD_NEAREST
:
1489 rnd_mode
= float_round_nearest_even
;
1493 rnd_mode
= float_round_to_zero
;
1496 rnd_mode
= float_round_up
;
1499 rnd_mode
= float_round_down
;
1502 set_float_rounding_mode(rnd_mode
, &env
->fp_status
);
1507 env
->exception_index
= EXCP_DEBUG
;
1511 #ifndef TARGET_SPARC64
1514 if ((T0
& PSR_CWP
) >= NWINDOWS
)
1515 raise_exception(TT_ILL_INSN
);
1532 static inline uint64_t *get_gregset(uint64_t pstate
)
1547 static inline void change_pstate(uint64_t new_pstate
)
1549 uint64_t pstate_regs
, new_pstate_regs
;
1550 uint64_t *src
, *dst
;
1552 pstate_regs
= env
->pstate
& 0xc01;
1553 new_pstate_regs
= new_pstate
& 0xc01;
1554 if (new_pstate_regs
!= pstate_regs
) {
1555 // Switch global register bank
1556 src
= get_gregset(new_pstate_regs
);
1557 dst
= get_gregset(pstate_regs
);
1558 memcpy32(dst
, env
->gregs
);
1559 memcpy32(env
->gregs
, src
);
1561 env
->pstate
= new_pstate
;
1564 void do_wrpstate(void)
1566 change_pstate(T0
& 0xf3f);
1572 env
->pc
= env
->tnpc
[env
->tl
];
1573 env
->npc
= env
->tnpc
[env
->tl
] + 4;
1574 PUT_CCR(env
, env
->tstate
[env
->tl
] >> 32);
1575 env
->asi
= (env
->tstate
[env
->tl
] >> 24) & 0xff;
1576 change_pstate((env
->tstate
[env
->tl
] >> 8) & 0xf3f);
1577 PUT_CWP64(env
, env
->tstate
[env
->tl
] & 0xff);
1583 env
->pc
= env
->tpc
[env
->tl
];
1584 env
->npc
= env
->tnpc
[env
->tl
];
1585 PUT_CCR(env
, env
->tstate
[env
->tl
] >> 32);
1586 env
->asi
= (env
->tstate
[env
->tl
] >> 24) & 0xff;
1587 change_pstate((env
->tstate
[env
->tl
] >> 8) & 0xf3f);
1588 PUT_CWP64(env
, env
->tstate
[env
->tl
] & 0xff);
1592 void set_cwp(int new_cwp
)
1594 /* put the modified wrap registers at their proper location */
1595 if (env
->cwp
== (NWINDOWS
- 1))
1596 memcpy32(env
->regbase
, env
->regbase
+ NWINDOWS
* 16);
1598 /* put the wrap registers at their temporary location */
1599 if (new_cwp
== (NWINDOWS
- 1))
1600 memcpy32(env
->regbase
+ NWINDOWS
* 16, env
->regbase
);
1601 env
->regwptr
= env
->regbase
+ (new_cwp
* 16);
1602 REGWPTR
= env
->regwptr
;
1605 void cpu_set_cwp(CPUState
*env1
, int new_cwp
)
1607 CPUState
*saved_env
;
1609 target_ulong
*saved_regwptr
;
1614 saved_regwptr
= REGWPTR
;
1620 REGWPTR
= saved_regwptr
;
1624 #ifdef TARGET_SPARC64
1625 void do_interrupt(int intno
)
1628 if (loglevel
& CPU_LOG_INT
) {
1630 fprintf(logfile
, "%6d: v=%04x pc=%016" PRIx64
" npc=%016" PRIx64
" SP=%016" PRIx64
"\n",
1633 env
->npc
, env
->regwptr
[6]);
1634 cpu_dump_state(env
, logfile
, fprintf
, 0);
1640 fprintf(logfile
, " code=");
1641 ptr
= (uint8_t *)env
->pc
;
1642 for(i
= 0; i
< 16; i
++) {
1643 fprintf(logfile
, " %02x", ldub(ptr
+ i
));
1645 fprintf(logfile
, "\n");
1651 #if !defined(CONFIG_USER_ONLY)
1652 if (env
->tl
== MAXTL
) {
1653 cpu_abort(env
, "Trap 0x%04x while trap level is MAXTL, Error state", env
->exception_index
);
1657 env
->tstate
[env
->tl
] = ((uint64_t)GET_CCR(env
) << 32) | ((env
->asi
& 0xff) << 24) |
1658 ((env
->pstate
& 0xf3f) << 8) | GET_CWP64(env
);
1659 env
->tpc
[env
->tl
] = env
->pc
;
1660 env
->tnpc
[env
->tl
] = env
->npc
;
1661 env
->tt
[env
->tl
] = intno
;
1662 change_pstate(PS_PEF
| PS_PRIV
| PS_AG
);
1664 if (intno
== TT_CLRWIN
)
1665 set_cwp((env
->cwp
- 1) & (NWINDOWS
- 1));
1666 else if ((intno
& 0x1c0) == TT_SPILL
)
1667 set_cwp((env
->cwp
- env
->cansave
- 2) & (NWINDOWS
- 1));
1668 else if ((intno
& 0x1c0) == TT_FILL
)
1669 set_cwp((env
->cwp
+ 1) & (NWINDOWS
- 1));
1670 env
->tbr
&= ~0x7fffULL
;
1671 env
->tbr
|= ((env
->tl
> 1) ? 1 << 14 : 0) | (intno
<< 5);
1672 if (env
->tl
< MAXTL
- 1) {
1675 env
->pstate
|= PS_RED
;
1676 if (env
->tl
!= MAXTL
)
1680 env
->npc
= env
->pc
+ 4;
1681 env
->exception_index
= 0;
1684 void do_interrupt(int intno
)
1689 if (loglevel
& CPU_LOG_INT
) {
1691 fprintf(logfile
, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
1694 env
->npc
, env
->regwptr
[6]);
1695 cpu_dump_state(env
, logfile
, fprintf
, 0);
1701 fprintf(logfile
, " code=");
1702 ptr
= (uint8_t *)env
->pc
;
1703 for(i
= 0; i
< 16; i
++) {
1704 fprintf(logfile
, " %02x", ldub(ptr
+ i
));
1706 fprintf(logfile
, "\n");
1712 #if !defined(CONFIG_USER_ONLY)
1713 if (env
->psret
== 0) {
1714 cpu_abort(env
, "Trap 0x%02x while interrupts disabled, Error state", env
->exception_index
);
1719 cwp
= (env
->cwp
- 1) & (NWINDOWS
- 1);
1721 env
->regwptr
[9] = env
->pc
;
1722 env
->regwptr
[10] = env
->npc
;
1723 env
->psrps
= env
->psrs
;
1725 env
->tbr
= (env
->tbr
& TBR_BASE_MASK
) | (intno
<< 4);
1727 env
->npc
= env
->pc
+ 4;
1728 env
->exception_index
= 0;
1732 #if !defined(CONFIG_USER_ONLY)
1734 static void do_unaligned_access(target_ulong addr
, int is_write
, int is_user
,
1737 #define MMUSUFFIX _mmu
1738 #define ALIGNED_ONLY
1740 # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
1742 # define GETPC() (__builtin_return_address(0))
1746 #include "softmmu_template.h"
1749 #include "softmmu_template.h"
1752 #include "softmmu_template.h"
1755 #include "softmmu_template.h"
1757 static void do_unaligned_access(target_ulong addr
, int is_write
, int is_user
,
1760 #ifdef DEBUG_UNALIGNED
1761 printf("Unaligned access to 0x%x from 0x%x\n", addr
, env
->pc
);
1763 raise_exception(TT_UNALIGNED
);
1766 /* try to fill the TLB and return an exception if error. If retaddr is
1767 NULL, it means that the function was called in C code (i.e. not
1768 from generated code or from helper.c) */
1769 /* XXX: fix it to restore all registers */
1770 void tlb_fill(target_ulong addr
, int is_write
, int mmu_idx
, void *retaddr
)
1772 TranslationBlock
*tb
;
1775 CPUState
*saved_env
;
1777 /* XXX: hack to restore env in all cases, even if not called from
1780 env
= cpu_single_env
;
1782 ret
= cpu_sparc_handle_mmu_fault(env
, addr
, is_write
, mmu_idx
, 1);
1785 /* now we have a real cpu fault */
1786 pc
= (unsigned long)retaddr
;
1787 tb
= tb_find_pc(pc
);
1789 /* the PC is inside the translated code. It means that we have
1790 a virtual CPU fault */
1791 cpu_restore_state(tb
, env
, pc
, (void *)T2
);
1801 #ifndef TARGET_SPARC64
1802 void do_unassigned_access(target_phys_addr_t addr
, int is_write
, int is_exec
,
1805 CPUState
*saved_env
;
1807 /* XXX: hack to restore env in all cases, even if not called from
1810 env
= cpu_single_env
;
1811 if (env
->mmuregs
[3]) /* Fault status register */
1812 env
->mmuregs
[3] = 1; /* overflow (not read before another fault) */
1814 env
->mmuregs
[3] |= 1 << 16;
1816 env
->mmuregs
[3] |= 1 << 5;
1818 env
->mmuregs
[3] |= 1 << 6;
1820 env
->mmuregs
[3] |= 1 << 7;
1821 env
->mmuregs
[3] |= (5 << 2) | 2;
1822 env
->mmuregs
[4] = addr
; /* Fault address register */
1823 if ((env
->mmuregs
[0] & MMU_E
) && !(env
->mmuregs
[0] & MMU_NF
)) {
1824 #ifdef DEBUG_UNASSIGNED
1825 printf("Unassigned mem access to " TARGET_FMT_plx
" from " TARGET_FMT_lx
1826 "\n", addr
, env
->pc
);
1829 raise_exception(TT_CODE_ACCESS
);
1831 raise_exception(TT_DATA_ACCESS
);
1836 void do_unassigned_access(target_phys_addr_t addr
, int is_write
, int is_exec
,
1839 #ifdef DEBUG_UNASSIGNED
1840 CPUState
*saved_env
;
1842 /* XXX: hack to restore env in all cases, even if not called from
1845 env
= cpu_single_env
;
1846 printf("Unassigned mem access to " TARGET_FMT_plx
" from " TARGET_FMT_lx
"\n",
1851 raise_exception(TT_CODE_ACCESS
);
1853 raise_exception(TT_DATA_ACCESS
);