2 #include "host-utils.h"
7 //#define DEBUG_UNALIGNED
8 //#define DEBUG_UNASSIGNED
12 #define DPRINTF_MMU(fmt, args...) \
13 do { printf("MMU: " fmt , ##args); } while (0)
15 #define DPRINTF_MMU(fmt, args...)
19 #define DPRINTF_MXCC(fmt, args...) \
20 do { printf("MXCC: " fmt , ##args); } while (0)
22 #define DPRINTF_MXCC(fmt, args...)
26 #define DPRINTF_ASI(fmt, args...) \
27 do { printf("ASI: " fmt , ##args); } while (0)
29 #define DPRINTF_ASI(fmt, args...)
32 void raise_exception(int tt
)
34 env
->exception_index
= tt
;
38 void check_ieee_exceptions()
40 T0
= get_float_exception_flags(&env
->fp_status
);
43 /* Copy IEEE 754 flags into FSR */
44 if (T0
& float_flag_invalid
)
46 if (T0
& float_flag_overflow
)
48 if (T0
& float_flag_underflow
)
50 if (T0
& float_flag_divbyzero
)
52 if (T0
& float_flag_inexact
)
55 if ((env
->fsr
& FSR_CEXC_MASK
) & ((env
->fsr
& FSR_TEM_MASK
) >> 23))
57 /* Unmasked exception, generate a trap */
58 env
->fsr
|= FSR_FTT_IEEE_EXCP
;
59 raise_exception(TT_FP_EXCP
);
63 /* Accumulate exceptions */
64 env
->fsr
|= (env
->fsr
& FSR_CEXC_MASK
) << 5;
69 #ifdef USE_INT_TO_FLOAT_HELPERS
72 set_float_exception_flags(0, &env
->fp_status
);
73 FT0
= int32_to_float32(*((int32_t *)&FT1
), &env
->fp_status
);
74 check_ieee_exceptions();
79 DT0
= int32_to_float64(*((int32_t *)&FT1
), &env
->fp_status
);
82 #if defined(CONFIG_USER_ONLY)
85 QT0
= int32_to_float128(*((int32_t *)&FT1
), &env
->fp_status
);
92 set_float_exception_flags(0, &env
->fp_status
);
93 FT0
= int64_to_float32(*((int64_t *)&DT1
), &env
->fp_status
);
94 check_ieee_exceptions();
99 set_float_exception_flags(0, &env
->fp_status
);
100 DT0
= int64_to_float64(*((int64_t *)&DT1
), &env
->fp_status
);
101 check_ieee_exceptions();
104 #if defined(CONFIG_USER_ONLY)
107 set_float_exception_flags(0, &env
->fp_status
);
108 QT0
= int64_to_float128(*((int32_t *)&DT1
), &env
->fp_status
);
109 check_ieee_exceptions();
117 FT0
= float32_abs(FT1
);
120 #ifdef TARGET_SPARC64
123 DT0
= float64_abs(DT1
);
126 #if defined(CONFIG_USER_ONLY)
129 QT0
= float128_abs(QT1
);
136 set_float_exception_flags(0, &env
->fp_status
);
137 FT0
= float32_sqrt(FT1
, &env
->fp_status
);
138 check_ieee_exceptions();
143 set_float_exception_flags(0, &env
->fp_status
);
144 DT0
= float64_sqrt(DT1
, &env
->fp_status
);
145 check_ieee_exceptions();
148 #if defined(CONFIG_USER_ONLY)
151 set_float_exception_flags(0, &env
->fp_status
);
152 QT0
= float128_sqrt(QT1
, &env
->fp_status
);
153 check_ieee_exceptions();
157 #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
158 void glue(do_, name) (void) \
160 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
161 switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
162 case float_relation_unordered: \
163 T0 = (FSR_FCC1 | FSR_FCC0) << FS; \
164 if ((env->fsr & FSR_NVM) || TRAP) { \
166 env->fsr |= FSR_NVC; \
167 env->fsr |= FSR_FTT_IEEE_EXCP; \
168 raise_exception(TT_FP_EXCP); \
170 env->fsr |= FSR_NVA; \
173 case float_relation_less: \
174 T0 = FSR_FCC0 << FS; \
176 case float_relation_greater: \
177 T0 = FSR_FCC1 << FS; \
186 GEN_FCMP(fcmps
, float32
, FT0
, FT1
, 0, 0);
187 GEN_FCMP(fcmpd
, float64
, DT0
, DT1
, 0, 0);
189 GEN_FCMP(fcmpes
, float32
, FT0
, FT1
, 0, 1);
190 GEN_FCMP(fcmped
, float64
, DT0
, DT1
, 0, 1);
192 #ifdef CONFIG_USER_ONLY
193 GEN_FCMP(fcmpq
, float128
, QT0
, QT1
, 0, 0);
194 GEN_FCMP(fcmpeq
, float128
, QT0
, QT1
, 0, 1);
197 #ifdef TARGET_SPARC64
198 GEN_FCMP(fcmps_fcc1
, float32
, FT0
, FT1
, 22, 0);
199 GEN_FCMP(fcmpd_fcc1
, float64
, DT0
, DT1
, 22, 0);
201 GEN_FCMP(fcmps_fcc2
, float32
, FT0
, FT1
, 24, 0);
202 GEN_FCMP(fcmpd_fcc2
, float64
, DT0
, DT1
, 24, 0);
204 GEN_FCMP(fcmps_fcc3
, float32
, FT0
, FT1
, 26, 0);
205 GEN_FCMP(fcmpd_fcc3
, float64
, DT0
, DT1
, 26, 0);
207 GEN_FCMP(fcmpes_fcc1
, float32
, FT0
, FT1
, 22, 1);
208 GEN_FCMP(fcmped_fcc1
, float64
, DT0
, DT1
, 22, 1);
210 GEN_FCMP(fcmpes_fcc2
, float32
, FT0
, FT1
, 24, 1);
211 GEN_FCMP(fcmped_fcc2
, float64
, DT0
, DT1
, 24, 1);
213 GEN_FCMP(fcmpes_fcc3
, float32
, FT0
, FT1
, 26, 1);
214 GEN_FCMP(fcmped_fcc3
, float64
, DT0
, DT1
, 26, 1);
215 #ifdef CONFIG_USER_ONLY
216 GEN_FCMP(fcmpq_fcc1
, float128
, QT0
, QT1
, 22, 0);
217 GEN_FCMP(fcmpq_fcc2
, float128
, QT0
, QT1
, 24, 0);
218 GEN_FCMP(fcmpq_fcc3
, float128
, QT0
, QT1
, 26, 0);
219 GEN_FCMP(fcmpeq_fcc1
, float128
, QT0
, QT1
, 22, 1);
220 GEN_FCMP(fcmpeq_fcc2
, float128
, QT0
, QT1
, 24, 1);
221 GEN_FCMP(fcmpeq_fcc3
, float128
, QT0
, QT1
, 26, 1);
225 #ifndef TARGET_SPARC64
226 #ifndef CONFIG_USER_ONLY
229 static void dump_mxcc(CPUState
*env
)
231 printf("mxccdata: %016llx %016llx %016llx %016llx\n",
232 env
->mxccdata
[0], env
->mxccdata
[1], env
->mxccdata
[2], env
->mxccdata
[3]);
233 printf("mxccregs: %016llx %016llx %016llx %016llx\n"
234 " %016llx %016llx %016llx %016llx\n",
235 env
->mxccregs
[0], env
->mxccregs
[1], env
->mxccregs
[2], env
->mxccregs
[3],
236 env
->mxccregs
[4], env
->mxccregs
[5], env
->mxccregs
[6], env
->mxccregs
[7]);
241 static void dump_asi(const char * txt
, uint32_t addr
, int asi
, int size
,
242 uint32_t r1
, uint32_t r2
)
247 DPRINTF_ASI("%s %08x asi 0x%02x = %02x\n", txt
, addr
, asi
, r1
& 0xff);
250 DPRINTF_ASI("%s %08x asi 0x%02x = %04x\n", txt
, addr
, asi
, r1
& 0xffff);
253 DPRINTF_ASI("%s %08x asi 0x%02x = %08x\n", txt
, addr
, asi
, r1
);
256 DPRINTF_ASI("%s %08x asi 0x%02x = %016llx\n", txt
, addr
, asi
,
257 r2
| ((uint64_t)r1
<< 32));
263 void helper_ld_asi(int asi
, int size
, int sign
)
267 #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
268 uint32_t last_T0
= T0
;
272 case 2: /* SuperSparc MXCC registers */
274 case 0x01c00a00: /* MXCC control register */
276 ret
= env
->mxccregs
[3] >> 32;
277 T0
= env
->mxccregs
[3];
279 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
281 case 0x01c00a04: /* MXCC control register */
283 ret
= env
->mxccregs
[3];
285 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
287 case 0x01c00c00: /* Module reset register */
289 ret
= env
->mxccregs
[5] >> 32;
290 T0
= env
->mxccregs
[5];
291 // should we do something here?
293 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
295 case 0x01c00f00: /* MBus port address register */
297 ret
= env
->mxccregs
[7] >> 32;
298 T0
= env
->mxccregs
[7];
300 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
303 DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0
, size
);
306 DPRINTF_MXCC("asi = %d, size = %d, sign = %d, T0 = %08x -> ret = %08x,"
307 "T0 = %08x\n", asi
, size
, sign
, last_T0
, ret
, T0
);
312 case 3: /* MMU probe */
316 mmulev
= (T0
>> 8) & 15;
320 ret
= mmu_probe(env
, T0
, mmulev
);
323 DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0
, mmulev
, ret
);
326 case 4: /* read MMU regs */
328 int reg
= (T0
>> 8) & 0x1f;
330 ret
= env
->mmuregs
[reg
];
331 if (reg
== 3) /* Fault status cleared on read */
333 else if (reg
== 0x13) /* Fault status read */
334 ret
= env
->mmuregs
[3];
335 else if (reg
== 0x14) /* Fault address read */
336 ret
= env
->mmuregs
[4];
337 DPRINTF_MMU("mmu_read: reg[%d] = 0x%08x\n", reg
, ret
);
340 case 5: // Turbosparc ITLB Diagnostic
341 case 6: // Turbosparc DTLB Diagnostic
342 case 7: // Turbosparc IOTLB Diagnostic
344 case 9: /* Supervisor code access */
350 ret
= lduw_code(T0
& ~1);
354 ret
= ldl_code(T0
& ~3);
357 tmp
= ldq_code(T0
& ~7);
363 case 0xa: /* User data access */
369 ret
= lduw_user(T0
& ~1);
373 ret
= ldl_user(T0
& ~3);
376 tmp
= ldq_user(T0
& ~7);
382 case 0xb: /* Supervisor data access */
385 ret
= ldub_kernel(T0
);
388 ret
= lduw_kernel(T0
& ~1);
392 ret
= ldl_kernel(T0
& ~3);
395 tmp
= ldq_kernel(T0
& ~7);
401 case 0xc: /* I-cache tag */
402 case 0xd: /* I-cache data */
403 case 0xe: /* D-cache tag */
404 case 0xf: /* D-cache data */
406 case 0x20: /* MMU passthrough */
412 ret
= lduw_phys(T0
& ~1);
416 ret
= ldl_phys(T0
& ~3);
419 tmp
= ldq_phys(T0
& ~7);
425 case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
428 ret
= ldub_phys((target_phys_addr_t
)T0
429 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
432 ret
= lduw_phys((target_phys_addr_t
)(T0
& ~1)
433 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
437 ret
= ldl_phys((target_phys_addr_t
)(T0
& ~3)
438 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
441 tmp
= ldq_phys((target_phys_addr_t
)(T0
& ~7)
442 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
448 case 0x30: // Turbosparc secondary cache diagnostic
449 case 0x31: // Turbosparc RAM snoop
450 case 0x32: // Turbosparc page table descriptor diagnostic
451 case 0x39: /* data cache diagnostic register */
454 case 8: /* User code access, XXX */
456 do_unassigned_access(T0
, 0, 0, asi
);
476 dump_asi("read ", last_T0
, asi
, size
, T1
, T0
);
480 void helper_st_asi(int asi
, int size
)
483 case 2: /* SuperSparc MXCC registers */
485 case 0x01c00000: /* MXCC stream data register 0 */
487 env
->mxccdata
[0] = ((uint64_t)T1
<< 32) | T2
;
489 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
491 case 0x01c00008: /* MXCC stream data register 1 */
493 env
->mxccdata
[1] = ((uint64_t)T1
<< 32) | T2
;
495 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
497 case 0x01c00010: /* MXCC stream data register 2 */
499 env
->mxccdata
[2] = ((uint64_t)T1
<< 32) | T2
;
501 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
503 case 0x01c00018: /* MXCC stream data register 3 */
505 env
->mxccdata
[3] = ((uint64_t)T1
<< 32) | T2
;
507 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
509 case 0x01c00100: /* MXCC stream source */
511 env
->mxccregs
[0] = ((uint64_t)T1
<< 32) | T2
;
513 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
514 env
->mxccdata
[0] = ldq_phys((env
->mxccregs
[0] & 0xffffffffULL
) + 0);
515 env
->mxccdata
[1] = ldq_phys((env
->mxccregs
[0] & 0xffffffffULL
) + 8);
516 env
->mxccdata
[2] = ldq_phys((env
->mxccregs
[0] & 0xffffffffULL
) + 16);
517 env
->mxccdata
[3] = ldq_phys((env
->mxccregs
[0] & 0xffffffffULL
) + 24);
519 case 0x01c00200: /* MXCC stream destination */
521 env
->mxccregs
[1] = ((uint64_t)T1
<< 32) | T2
;
523 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
524 stq_phys((env
->mxccregs
[1] & 0xffffffffULL
) + 0, env
->mxccdata
[0]);
525 stq_phys((env
->mxccregs
[1] & 0xffffffffULL
) + 8, env
->mxccdata
[1]);
526 stq_phys((env
->mxccregs
[1] & 0xffffffffULL
) + 16, env
->mxccdata
[2]);
527 stq_phys((env
->mxccregs
[1] & 0xffffffffULL
) + 24, env
->mxccdata
[3]);
529 case 0x01c00a00: /* MXCC control register */
531 env
->mxccregs
[3] = ((uint64_t)T1
<< 32) | T2
;
533 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
535 case 0x01c00a04: /* MXCC control register */
537 env
->mxccregs
[3] = (env
->mxccregs
[0xa] & 0xffffffff00000000ULL
) | T1
;
539 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
541 case 0x01c00e00: /* MXCC error register */
542 // writing a 1 bit clears the error
544 env
->mxccregs
[6] &= ~(((uint64_t)T1
<< 32) | T2
);
546 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
548 case 0x01c00f00: /* MBus port address register */
550 env
->mxccregs
[7] = ((uint64_t)T1
<< 32) | T2
;
552 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0
, size
);
555 DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0
, size
);
558 DPRINTF_MXCC("asi = %d, size = %d, T0 = %08x, T1 = %08x\n", asi
, size
, T0
, T1
);
563 case 3: /* MMU flush */
567 mmulev
= (T0
>> 8) & 15;
568 DPRINTF_MMU("mmu flush level %d\n", mmulev
);
570 case 0: // flush page
571 tlb_flush_page(env
, T0
& 0xfffff000);
573 case 1: // flush segment (256k)
574 case 2: // flush region (16M)
575 case 3: // flush context (4G)
576 case 4: // flush entire
587 case 4: /* write MMU regs */
589 int reg
= (T0
>> 8) & 0x1f;
592 oldreg
= env
->mmuregs
[reg
];
595 env
->mmuregs
[reg
] = (env
->mmuregs
[reg
] & 0xff000000) |
597 // Mappings generated during no-fault mode or MMU
598 // disabled mode are invalid in normal mode
599 if ((oldreg
& (MMU_E
| MMU_NF
| env
->mmu_bm
)) !=
600 (env
->mmuregs
[reg
] & (MMU_E
| MMU_NF
| env
->mmu_bm
)))
604 env
->mmuregs
[reg
] = T1
;
605 if (oldreg
!= env
->mmuregs
[reg
]) {
606 /* we flush when the MMU context changes because
607 QEMU has no MMU context support */
615 env
->mmuregs
[3] = T1
;
618 env
->mmuregs
[4] = T1
;
621 env
->mmuregs
[reg
] = T1
;
624 if (oldreg
!= env
->mmuregs
[reg
]) {
625 DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg
, oldreg
, env
->mmuregs
[reg
]);
632 case 5: // Turbosparc ITLB Diagnostic
633 case 6: // Turbosparc DTLB Diagnostic
634 case 7: // Turbosparc IOTLB Diagnostic
636 case 0xa: /* User data access */
642 stw_user(T0
& ~1, T1
);
646 stl_user(T0
& ~3, T1
);
649 stq_user(T0
& ~7, ((uint64_t)T1
<< 32) | T2
);
653 case 0xb: /* Supervisor data access */
659 stw_kernel(T0
& ~1, T1
);
663 stl_kernel(T0
& ~3, T1
);
666 stq_kernel(T0
& ~7, ((uint64_t)T1
<< 32) | T2
);
670 case 0xc: /* I-cache tag */
671 case 0xd: /* I-cache data */
672 case 0xe: /* D-cache tag */
673 case 0xf: /* D-cache data */
674 case 0x10: /* I/D-cache flush page */
675 case 0x11: /* I/D-cache flush segment */
676 case 0x12: /* I/D-cache flush region */
677 case 0x13: /* I/D-cache flush context */
678 case 0x14: /* I/D-cache flush user */
680 case 0x17: /* Block copy, sta access */
683 // address (T0) = dst
686 uint32_t src
= T1
& ~3, dst
= T0
& ~3, temp
;
688 for (i
= 0; i
< 32; i
+= 4, src
+= 4, dst
+= 4) {
689 temp
= ldl_kernel(src
);
690 stl_kernel(dst
, temp
);
694 case 0x1f: /* Block fill, stda access */
697 // address (T0) = dst
700 uint32_t dst
= T0
& 7;
703 val
= (((uint64_t)T1
) << 32) | T2
;
705 for (i
= 0; i
< 32; i
+= 8, dst
+= 8)
706 stq_kernel(dst
, val
);
709 case 0x20: /* MMU passthrough */
716 stw_phys(T0
& ~1, T1
);
720 stl_phys(T0
& ~3, T1
);
723 stq_phys(T0
& ~7, ((uint64_t)T1
<< 32) | T2
);
728 case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
732 stb_phys((target_phys_addr_t
)T0
733 | ((target_phys_addr_t
)(asi
& 0xf) << 32), T1
);
736 stw_phys((target_phys_addr_t
)(T0
& ~1)
737 | ((target_phys_addr_t
)(asi
& 0xf) << 32), T1
);
741 stl_phys((target_phys_addr_t
)(T0
& ~3)
742 | ((target_phys_addr_t
)(asi
& 0xf) << 32), T1
);
745 stq_phys((target_phys_addr_t
)(T0
& ~7)
746 | ((target_phys_addr_t
)(asi
& 0xf) << 32),
747 ((uint64_t)T1
<< 32) | T2
);
752 case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
753 case 0x31: // store buffer data, Ross RT620 I-cache flush or
754 // Turbosparc snoop RAM
755 case 0x32: // store buffer control or Turbosparc page table descriptor diagnostic
756 case 0x36: /* I-cache flash clear */
757 case 0x37: /* D-cache flash clear */
758 case 0x38: /* breakpoint diagnostics */
759 case 0x4c: /* breakpoint action */
761 case 8: /* User code access, XXX */
762 case 9: /* Supervisor code access, XXX */
764 do_unassigned_access(T0
, 1, 0, asi
);
768 dump_asi("write", T0
, asi
, size
, T1
, T2
);
772 #endif /* CONFIG_USER_ONLY */
773 #else /* TARGET_SPARC64 */
775 #ifdef CONFIG_USER_ONLY
776 void helper_ld_asi(int asi
, int size
, int sign
)
781 raise_exception(TT_PRIV_ACT
);
784 case 0x80: // Primary
785 case 0x82: // Primary no-fault
786 case 0x88: // Primary LE
787 case 0x8a: // Primary no-fault LE
794 ret
= lduw_raw(T0
& ~1);
797 ret
= ldl_raw(T0
& ~3);
801 ret
= ldq_raw(T0
& ~7);
806 case 0x81: // Secondary
807 case 0x83: // Secondary no-fault
808 case 0x89: // Secondary LE
809 case 0x8b: // Secondary no-fault LE
816 /* Convert from little endian */
818 case 0x88: // Primary LE
819 case 0x89: // Secondary LE
820 case 0x8a: // Primary no-fault LE
821 case 0x8b: // Secondary no-fault LE
839 /* Convert to signed number */
858 void helper_st_asi(int asi
, int size
)
861 raise_exception(TT_PRIV_ACT
);
863 /* Convert to little endian */
865 case 0x88: // Primary LE
866 case 0x89: // Secondary LE
885 case 0x80: // Primary
886 case 0x88: // Primary LE
893 stw_raw(T0
& ~1, T1
);
896 stl_raw(T0
& ~3, T1
);
900 stq_raw(T0
& ~7, T1
);
905 case 0x81: // Secondary
906 case 0x89: // Secondary LE
910 case 0x82: // Primary no-fault, RO
911 case 0x83: // Secondary no-fault, RO
912 case 0x8a: // Primary no-fault LE, RO
913 case 0x8b: // Secondary no-fault LE, RO
915 do_unassigned_access(T0
, 1, 0, 1);
920 #else /* CONFIG_USER_ONLY */
922 void helper_ld_asi(int asi
, int size
, int sign
)
926 if ((asi
< 0x80 && (env
->pstate
& PS_PRIV
) == 0)
927 || (asi
>= 0x30 && asi
< 0x80 && !(env
->hpstate
& HS_PRIV
)))
928 raise_exception(TT_PRIV_ACT
);
931 case 0x10: // As if user primary
932 case 0x18: // As if user primary LE
933 case 0x80: // Primary
934 case 0x82: // Primary no-fault
935 case 0x88: // Primary LE
936 case 0x8a: // Primary no-fault LE
937 if ((asi
& 0x80) && (env
->pstate
& PS_PRIV
)) {
938 if (env
->hpstate
& HS_PRIV
) {
944 ret
= lduw_hypv(T0
& ~1);
947 ret
= ldl_hypv(T0
& ~3);
951 ret
= ldq_hypv(T0
& ~7);
957 ret
= ldub_kernel(T0
);
960 ret
= lduw_kernel(T0
& ~1);
963 ret
= ldl_kernel(T0
& ~3);
967 ret
= ldq_kernel(T0
& ~7);
977 ret
= lduw_user(T0
& ~1);
980 ret
= ldl_user(T0
& ~3);
984 ret
= ldq_user(T0
& ~7);
990 case 0x15: // Bypass, non-cacheable
991 case 0x1c: // Bypass LE
992 case 0x1d: // Bypass, non-cacheable LE
999 ret
= lduw_phys(T0
& ~1);
1002 ret
= ldl_phys(T0
& ~3);
1006 ret
= ldq_phys(T0
& ~7);
1011 case 0x04: // Nucleus
1012 case 0x0c: // Nucleus Little Endian (LE)
1013 case 0x11: // As if user secondary
1014 case 0x19: // As if user secondary LE
1015 case 0x24: // Nucleus quad LDD 128 bit atomic
1016 case 0x2c: // Nucleus quad LDD 128 bit atomic
1017 case 0x4a: // UPA config
1018 case 0x81: // Secondary
1019 case 0x83: // Secondary no-fault
1020 case 0x89: // Secondary LE
1021 case 0x8b: // Secondary no-fault LE
1027 case 0x50: // I-MMU regs
1029 int reg
= (T0
>> 3) & 0xf;
1031 ret
= env
->immuregs
[reg
];
1034 case 0x51: // I-MMU 8k TSB pointer
1035 case 0x52: // I-MMU 64k TSB pointer
1036 case 0x55: // I-MMU data access
1039 case 0x56: // I-MMU tag read
1043 for (i
= 0; i
< 64; i
++) {
1044 // Valid, ctx match, vaddr match
1045 if ((env
->itlb_tte
[i
] & 0x8000000000000000ULL
) != 0 &&
1046 env
->itlb_tag
[i
] == T0
) {
1047 ret
= env
->itlb_tag
[i
];
1053 case 0x58: // D-MMU regs
1055 int reg
= (T0
>> 3) & 0xf;
1057 ret
= env
->dmmuregs
[reg
];
1060 case 0x5e: // D-MMU tag read
1064 for (i
= 0; i
< 64; i
++) {
1065 // Valid, ctx match, vaddr match
1066 if ((env
->dtlb_tte
[i
] & 0x8000000000000000ULL
) != 0 &&
1067 env
->dtlb_tag
[i
] == T0
) {
1068 ret
= env
->dtlb_tag
[i
];
1074 case 0x59: // D-MMU 8k TSB pointer
1075 case 0x5a: // D-MMU 64k TSB pointer
1076 case 0x5b: // D-MMU data pointer
1077 case 0x5d: // D-MMU data access
1078 case 0x48: // Interrupt dispatch, RO
1079 case 0x49: // Interrupt data receive
1080 case 0x7f: // Incoming interrupt vector, RO
1083 case 0x54: // I-MMU data in, WO
1084 case 0x57: // I-MMU demap, WO
1085 case 0x5c: // D-MMU data in, WO
1086 case 0x5f: // D-MMU demap, WO
1087 case 0x77: // Interrupt vector, WO
1089 do_unassigned_access(T0
, 0, 0, 1);
1094 /* Convert from little endian */
1096 case 0x0c: // Nucleus Little Endian (LE)
1097 case 0x18: // As if user primary LE
1098 case 0x19: // As if user secondary LE
1099 case 0x1c: // Bypass LE
1100 case 0x1d: // Bypass, non-cacheable LE
1101 case 0x88: // Primary LE
1102 case 0x89: // Secondary LE
1103 case 0x8a: // Primary no-fault LE
1104 case 0x8b: // Secondary no-fault LE
1122 /* Convert to signed number */
1129 ret
= (int16_t) ret
;
1132 ret
= (int32_t) ret
;
1141 void helper_st_asi(int asi
, int size
)
1143 if ((asi
< 0x80 && (env
->pstate
& PS_PRIV
) == 0)
1144 || (asi
>= 0x30 && asi
< 0x80 && !(env
->hpstate
& HS_PRIV
)))
1145 raise_exception(TT_PRIV_ACT
);
1147 /* Convert to little endian */
1149 case 0x0c: // Nucleus Little Endian (LE)
1150 case 0x18: // As if user primary LE
1151 case 0x19: // As if user secondary LE
1152 case 0x1c: // Bypass LE
1153 case 0x1d: // Bypass, non-cacheable LE
1154 case 0x88: // Primary LE
1155 case 0x89: // Secondary LE
1174 case 0x10: // As if user primary
1175 case 0x18: // As if user primary LE
1176 case 0x80: // Primary
1177 case 0x88: // Primary LE
1178 if ((asi
& 0x80) && (env
->pstate
& PS_PRIV
)) {
1179 if (env
->hpstate
& HS_PRIV
) {
1185 stw_hypv(T0
& ~1, T1
);
1188 stl_hypv(T0
& ~3, T1
);
1192 stq_hypv(T0
& ~7, T1
);
1201 stw_kernel(T0
& ~1, T1
);
1204 stl_kernel(T0
& ~3, T1
);
1208 stq_kernel(T0
& ~7, T1
);
1218 stw_user(T0
& ~1, T1
);
1221 stl_user(T0
& ~3, T1
);
1225 stq_user(T0
& ~7, T1
);
1230 case 0x14: // Bypass
1231 case 0x15: // Bypass, non-cacheable
1232 case 0x1c: // Bypass LE
1233 case 0x1d: // Bypass, non-cacheable LE
1240 stw_phys(T0
& ~1, T1
);
1243 stl_phys(T0
& ~3, T1
);
1247 stq_phys(T0
& ~7, T1
);
1252 case 0x04: // Nucleus
1253 case 0x0c: // Nucleus Little Endian (LE)
1254 case 0x11: // As if user secondary
1255 case 0x19: // As if user secondary LE
1256 case 0x24: // Nucleus quad LDD 128 bit atomic
1257 case 0x2c: // Nucleus quad LDD 128 bit atomic
1258 case 0x4a: // UPA config
1259 case 0x81: // Secondary
1260 case 0x89: // Secondary LE
1268 env
->lsu
= T1
& (DMMU_E
| IMMU_E
);
1269 // Mappings generated during D/I MMU disabled mode are
1270 // invalid in normal mode
1271 if (oldreg
!= env
->lsu
) {
1272 DPRINTF_MMU("LSU change: 0x%" PRIx64
" -> 0x%" PRIx64
"\n", oldreg
, env
->lsu
);
1280 case 0x50: // I-MMU regs
1282 int reg
= (T0
>> 3) & 0xf;
1285 oldreg
= env
->immuregs
[reg
];
1290 case 1: // Not in I-MMU
1297 T1
= 0; // Clear SFSR
1299 case 5: // TSB access
1300 case 6: // Tag access
1304 env
->immuregs
[reg
] = T1
;
1305 if (oldreg
!= env
->immuregs
[reg
]) {
1306 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64
" -> 0x%08" PRIx64
"\n", reg
, oldreg
, env
->immuregs
[reg
]);
1313 case 0x54: // I-MMU data in
1317 // Try finding an invalid entry
1318 for (i
= 0; i
< 64; i
++) {
1319 if ((env
->itlb_tte
[i
] & 0x8000000000000000ULL
) == 0) {
1320 env
->itlb_tag
[i
] = env
->immuregs
[6];
1321 env
->itlb_tte
[i
] = T1
;
1325 // Try finding an unlocked entry
1326 for (i
= 0; i
< 64; i
++) {
1327 if ((env
->itlb_tte
[i
] & 0x40) == 0) {
1328 env
->itlb_tag
[i
] = env
->immuregs
[6];
1329 env
->itlb_tte
[i
] = T1
;
1336 case 0x55: // I-MMU data access
1338 unsigned int i
= (T0
>> 3) & 0x3f;
1340 env
->itlb_tag
[i
] = env
->immuregs
[6];
1341 env
->itlb_tte
[i
] = T1
;
1344 case 0x57: // I-MMU demap
1347 case 0x58: // D-MMU regs
1349 int reg
= (T0
>> 3) & 0xf;
1352 oldreg
= env
->dmmuregs
[reg
];
1358 if ((T1
& 1) == 0) {
1359 T1
= 0; // Clear SFSR, Fault address
1360 env
->dmmuregs
[4] = 0;
1362 env
->dmmuregs
[reg
] = T1
;
1364 case 1: // Primary context
1365 case 2: // Secondary context
1366 case 5: // TSB access
1367 case 6: // Tag access
1368 case 7: // Virtual Watchpoint
1369 case 8: // Physical Watchpoint
1373 env
->dmmuregs
[reg
] = T1
;
1374 if (oldreg
!= env
->dmmuregs
[reg
]) {
1375 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64
" -> 0x%08" PRIx64
"\n", reg
, oldreg
, env
->dmmuregs
[reg
]);
1382 case 0x5c: // D-MMU data in
1386 // Try finding an invalid entry
1387 for (i
= 0; i
< 64; i
++) {
1388 if ((env
->dtlb_tte
[i
] & 0x8000000000000000ULL
) == 0) {
1389 env
->dtlb_tag
[i
] = env
->dmmuregs
[6];
1390 env
->dtlb_tte
[i
] = T1
;
1394 // Try finding an unlocked entry
1395 for (i
= 0; i
< 64; i
++) {
1396 if ((env
->dtlb_tte
[i
] & 0x40) == 0) {
1397 env
->dtlb_tag
[i
] = env
->dmmuregs
[6];
1398 env
->dtlb_tte
[i
] = T1
;
1405 case 0x5d: // D-MMU data access
1407 unsigned int i
= (T0
>> 3) & 0x3f;
1409 env
->dtlb_tag
[i
] = env
->dmmuregs
[6];
1410 env
->dtlb_tte
[i
] = T1
;
1413 case 0x5f: // D-MMU demap
1414 case 0x49: // Interrupt data receive
1417 case 0x51: // I-MMU 8k TSB pointer, RO
1418 case 0x52: // I-MMU 64k TSB pointer, RO
1419 case 0x56: // I-MMU tag read, RO
1420 case 0x59: // D-MMU 8k TSB pointer, RO
1421 case 0x5a: // D-MMU 64k TSB pointer, RO
1422 case 0x5b: // D-MMU data pointer, RO
1423 case 0x5e: // D-MMU tag read, RO
1424 case 0x48: // Interrupt dispatch, RO
1425 case 0x7f: // Incoming interrupt vector, RO
1426 case 0x82: // Primary no-fault, RO
1427 case 0x83: // Secondary no-fault, RO
1428 case 0x8a: // Primary no-fault LE, RO
1429 case 0x8b: // Secondary no-fault LE, RO
1431 do_unassigned_access(T0
, 1, 0, 1);
1435 #endif /* CONFIG_USER_ONLY */
1437 void helper_ldf_asi(int asi
, int size
, int rd
)
1439 target_ulong tmp_T0
= T0
, tmp_T1
= T1
;
1443 case 0xf0: // Block load primary
1444 case 0xf1: // Block load secondary
1445 case 0xf8: // Block load primary LE
1446 case 0xf9: // Block load secondary LE
1448 raise_exception(TT_ILL_INSN
);
1452 raise_exception(TT_UNALIGNED
);
1455 for (i
= 0; i
< 16; i
++) {
1456 helper_ld_asi(asi
& 0x8f, 4, 0);
1457 *(uint32_t *)&env
->fpr
[rd
++] = T1
;
1468 helper_ld_asi(asi
, size
, 0);
1472 *((uint32_t *)&FT0
) = T1
;
1475 *((int64_t *)&DT0
) = T1
;
1477 #if defined(CONFIG_USER_ONLY)
1486 void helper_stf_asi(int asi
, int size
, int rd
)
1488 target_ulong tmp_T0
= T0
, tmp_T1
= T1
;
1492 case 0xf0: // Block store primary
1493 case 0xf1: // Block store secondary
1494 case 0xf8: // Block store primary LE
1495 case 0xf9: // Block store secondary LE
1497 raise_exception(TT_ILL_INSN
);
1501 raise_exception(TT_UNALIGNED
);
1504 for (i
= 0; i
< 16; i
++) {
1505 T1
= *(uint32_t *)&env
->fpr
[rd
++];
1506 helper_st_asi(asi
& 0x8f, 4);
1520 T1
= *((uint32_t *)&FT0
);
1523 T1
= *((int64_t *)&DT0
);
1525 #if defined(CONFIG_USER_ONLY)
1531 helper_st_asi(asi
, size
);
1535 #endif /* TARGET_SPARC64 */
1537 #ifndef TARGET_SPARC64
1542 if (env
->psret
== 1)
1543 raise_exception(TT_ILL_INSN
);
1546 cwp
= (env
->cwp
+ 1) & (NWINDOWS
- 1);
1547 if (env
->wim
& (1 << cwp
)) {
1548 raise_exception(TT_WIN_UNF
);
1551 env
->psrs
= env
->psrps
;
1555 void helper_ldfsr(void)
1558 switch (env
->fsr
& FSR_RD_MASK
) {
1559 case FSR_RD_NEAREST
:
1560 rnd_mode
= float_round_nearest_even
;
1564 rnd_mode
= float_round_to_zero
;
1567 rnd_mode
= float_round_up
;
1570 rnd_mode
= float_round_down
;
1573 set_float_rounding_mode(rnd_mode
, &env
->fp_status
);
1578 env
->exception_index
= EXCP_DEBUG
;
1582 #ifndef TARGET_SPARC64
1585 if ((T0
& PSR_CWP
) >= NWINDOWS
)
1586 raise_exception(TT_ILL_INSN
);
1603 static inline uint64_t *get_gregset(uint64_t pstate
)
1618 static inline void change_pstate(uint64_t new_pstate
)
1620 uint64_t pstate_regs
, new_pstate_regs
;
1621 uint64_t *src
, *dst
;
1623 pstate_regs
= env
->pstate
& 0xc01;
1624 new_pstate_regs
= new_pstate
& 0xc01;
1625 if (new_pstate_regs
!= pstate_regs
) {
1626 // Switch global register bank
1627 src
= get_gregset(new_pstate_regs
);
1628 dst
= get_gregset(pstate_regs
);
1629 memcpy32(dst
, env
->gregs
);
1630 memcpy32(env
->gregs
, src
);
1632 env
->pstate
= new_pstate
;
1635 void do_wrpstate(void)
1637 change_pstate(T0
& 0xf3f);
1643 env
->pc
= env
->tnpc
[env
->tl
];
1644 env
->npc
= env
->tnpc
[env
->tl
] + 4;
1645 PUT_CCR(env
, env
->tstate
[env
->tl
] >> 32);
1646 env
->asi
= (env
->tstate
[env
->tl
] >> 24) & 0xff;
1647 change_pstate((env
->tstate
[env
->tl
] >> 8) & 0xf3f);
1648 PUT_CWP64(env
, env
->tstate
[env
->tl
] & 0xff);
1654 env
->pc
= env
->tpc
[env
->tl
];
1655 env
->npc
= env
->tnpc
[env
->tl
];
1656 PUT_CCR(env
, env
->tstate
[env
->tl
] >> 32);
1657 env
->asi
= (env
->tstate
[env
->tl
] >> 24) & 0xff;
1658 change_pstate((env
->tstate
[env
->tl
] >> 8) & 0xf3f);
1659 PUT_CWP64(env
, env
->tstate
[env
->tl
] & 0xff);
1663 void set_cwp(int new_cwp
)
1665 /* put the modified wrap registers at their proper location */
1666 if (env
->cwp
== (NWINDOWS
- 1))
1667 memcpy32(env
->regbase
, env
->regbase
+ NWINDOWS
* 16);
1669 /* put the wrap registers at their temporary location */
1670 if (new_cwp
== (NWINDOWS
- 1))
1671 memcpy32(env
->regbase
+ NWINDOWS
* 16, env
->regbase
);
1672 env
->regwptr
= env
->regbase
+ (new_cwp
* 16);
1673 REGWPTR
= env
->regwptr
;
1676 void cpu_set_cwp(CPUState
*env1
, int new_cwp
)
1678 CPUState
*saved_env
;
1680 target_ulong
*saved_regwptr
;
1685 saved_regwptr
= REGWPTR
;
1691 REGWPTR
= saved_regwptr
;
1695 #ifdef TARGET_SPARC64
1697 static const char * const excp_names
[0x50] = {
1698 [TT_TFAULT
] = "Instruction Access Fault",
1699 [TT_TMISS
] = "Instruction Access MMU Miss",
1700 [TT_CODE_ACCESS
] = "Instruction Access Error",
1701 [TT_ILL_INSN
] = "Illegal Instruction",
1702 [TT_PRIV_INSN
] = "Privileged Instruction",
1703 [TT_NFPU_INSN
] = "FPU Disabled",
1704 [TT_FP_EXCP
] = "FPU Exception",
1705 [TT_TOVF
] = "Tag Overflow",
1706 [TT_CLRWIN
] = "Clean Windows",
1707 [TT_DIV_ZERO
] = "Division By Zero",
1708 [TT_DFAULT
] = "Data Access Fault",
1709 [TT_DMISS
] = "Data Access MMU Miss",
1710 [TT_DATA_ACCESS
] = "Data Access Error",
1711 [TT_DPROT
] = "Data Protection Error",
1712 [TT_UNALIGNED
] = "Unaligned Memory Access",
1713 [TT_PRIV_ACT
] = "Privileged Action",
1714 [TT_EXTINT
| 0x1] = "External Interrupt 1",
1715 [TT_EXTINT
| 0x2] = "External Interrupt 2",
1716 [TT_EXTINT
| 0x3] = "External Interrupt 3",
1717 [TT_EXTINT
| 0x4] = "External Interrupt 4",
1718 [TT_EXTINT
| 0x5] = "External Interrupt 5",
1719 [TT_EXTINT
| 0x6] = "External Interrupt 6",
1720 [TT_EXTINT
| 0x7] = "External Interrupt 7",
1721 [TT_EXTINT
| 0x8] = "External Interrupt 8",
1722 [TT_EXTINT
| 0x9] = "External Interrupt 9",
1723 [TT_EXTINT
| 0xa] = "External Interrupt 10",
1724 [TT_EXTINT
| 0xb] = "External Interrupt 11",
1725 [TT_EXTINT
| 0xc] = "External Interrupt 12",
1726 [TT_EXTINT
| 0xd] = "External Interrupt 13",
1727 [TT_EXTINT
| 0xe] = "External Interrupt 14",
1728 [TT_EXTINT
| 0xf] = "External Interrupt 15",
1732 void do_interrupt(int intno
)
1735 if (loglevel
& CPU_LOG_INT
) {
1739 if (intno
< 0 || intno
>= 0x180 || (intno
> 0x4f && intno
< 0x80))
1741 else if (intno
>= 0x100)
1742 name
= "Trap Instruction";
1743 else if (intno
>= 0xc0)
1744 name
= "Window Fill";
1745 else if (intno
>= 0x80)
1746 name
= "Window Spill";
1748 name
= excp_names
[intno
];
1753 fprintf(logfile
, "%6d: %s (v=%04x) pc=%016" PRIx64
" npc=%016" PRIx64
1754 " SP=%016" PRIx64
"\n",
1757 env
->npc
, env
->regwptr
[6]);
1758 cpu_dump_state(env
, logfile
, fprintf
, 0);
1764 fprintf(logfile
, " code=");
1765 ptr
= (uint8_t *)env
->pc
;
1766 for(i
= 0; i
< 16; i
++) {
1767 fprintf(logfile
, " %02x", ldub(ptr
+ i
));
1769 fprintf(logfile
, "\n");
1775 #if !defined(CONFIG_USER_ONLY)
1776 if (env
->tl
== MAXTL
) {
1777 cpu_abort(env
, "Trap 0x%04x while trap level is MAXTL, Error state", env
->exception_index
);
1781 env
->tstate
[env
->tl
] = ((uint64_t)GET_CCR(env
) << 32) | ((env
->asi
& 0xff) << 24) |
1782 ((env
->pstate
& 0xf3f) << 8) | GET_CWP64(env
);
1783 env
->tpc
[env
->tl
] = env
->pc
;
1784 env
->tnpc
[env
->tl
] = env
->npc
;
1785 env
->tt
[env
->tl
] = intno
;
1786 change_pstate(PS_PEF
| PS_PRIV
| PS_AG
);
1788 if (intno
== TT_CLRWIN
)
1789 set_cwp((env
->cwp
- 1) & (NWINDOWS
- 1));
1790 else if ((intno
& 0x1c0) == TT_SPILL
)
1791 set_cwp((env
->cwp
- env
->cansave
- 2) & (NWINDOWS
- 1));
1792 else if ((intno
& 0x1c0) == TT_FILL
)
1793 set_cwp((env
->cwp
+ 1) & (NWINDOWS
- 1));
1794 env
->tbr
&= ~0x7fffULL
;
1795 env
->tbr
|= ((env
->tl
> 1) ? 1 << 14 : 0) | (intno
<< 5);
1796 if (env
->tl
< MAXTL
- 1) {
1799 env
->pstate
|= PS_RED
;
1800 if (env
->tl
!= MAXTL
)
1804 env
->npc
= env
->pc
+ 4;
1805 env
->exception_index
= 0;
1809 static const char * const excp_names
[0x80] = {
1810 [TT_TFAULT
] = "Instruction Access Fault",
1811 [TT_ILL_INSN
] = "Illegal Instruction",
1812 [TT_PRIV_INSN
] = "Privileged Instruction",
1813 [TT_NFPU_INSN
] = "FPU Disabled",
1814 [TT_WIN_OVF
] = "Window Overflow",
1815 [TT_WIN_UNF
] = "Window Underflow",
1816 [TT_UNALIGNED
] = "Unaligned Memory Access",
1817 [TT_FP_EXCP
] = "FPU Exception",
1818 [TT_DFAULT
] = "Data Access Fault",
1819 [TT_TOVF
] = "Tag Overflow",
1820 [TT_EXTINT
| 0x1] = "External Interrupt 1",
1821 [TT_EXTINT
| 0x2] = "External Interrupt 2",
1822 [TT_EXTINT
| 0x3] = "External Interrupt 3",
1823 [TT_EXTINT
| 0x4] = "External Interrupt 4",
1824 [TT_EXTINT
| 0x5] = "External Interrupt 5",
1825 [TT_EXTINT
| 0x6] = "External Interrupt 6",
1826 [TT_EXTINT
| 0x7] = "External Interrupt 7",
1827 [TT_EXTINT
| 0x8] = "External Interrupt 8",
1828 [TT_EXTINT
| 0x9] = "External Interrupt 9",
1829 [TT_EXTINT
| 0xa] = "External Interrupt 10",
1830 [TT_EXTINT
| 0xb] = "External Interrupt 11",
1831 [TT_EXTINT
| 0xc] = "External Interrupt 12",
1832 [TT_EXTINT
| 0xd] = "External Interrupt 13",
1833 [TT_EXTINT
| 0xe] = "External Interrupt 14",
1834 [TT_EXTINT
| 0xf] = "External Interrupt 15",
1835 [TT_TOVF
] = "Tag Overflow",
1836 [TT_CODE_ACCESS
] = "Instruction Access Error",
1837 [TT_DATA_ACCESS
] = "Data Access Error",
1838 [TT_DIV_ZERO
] = "Division By Zero",
1839 [TT_NCP_INSN
] = "Coprocessor Disabled",
1843 void do_interrupt(int intno
)
1848 if (loglevel
& CPU_LOG_INT
) {
1852 if (intno
< 0 || intno
>= 0x100)
1854 else if (intno
>= 0x80)
1855 name
= "Trap Instruction";
1857 name
= excp_names
[intno
];
1862 fprintf(logfile
, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
1865 env
->npc
, env
->regwptr
[6]);
1866 cpu_dump_state(env
, logfile
, fprintf
, 0);
1872 fprintf(logfile
, " code=");
1873 ptr
= (uint8_t *)env
->pc
;
1874 for(i
= 0; i
< 16; i
++) {
1875 fprintf(logfile
, " %02x", ldub(ptr
+ i
));
1877 fprintf(logfile
, "\n");
1883 #if !defined(CONFIG_USER_ONLY)
1884 if (env
->psret
== 0) {
1885 cpu_abort(env
, "Trap 0x%02x while interrupts disabled, Error state", env
->exception_index
);
1890 cwp
= (env
->cwp
- 1) & (NWINDOWS
- 1);
1892 env
->regwptr
[9] = env
->pc
;
1893 env
->regwptr
[10] = env
->npc
;
1894 env
->psrps
= env
->psrs
;
1896 env
->tbr
= (env
->tbr
& TBR_BASE_MASK
) | (intno
<< 4);
1898 env
->npc
= env
->pc
+ 4;
1899 env
->exception_index
= 0;
1903 #if !defined(CONFIG_USER_ONLY)
1905 static void do_unaligned_access(target_ulong addr
, int is_write
, int is_user
,
1908 #define MMUSUFFIX _mmu
1909 #define ALIGNED_ONLY
1911 # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
1913 # define GETPC() (__builtin_return_address(0))
1917 #include "softmmu_template.h"
1920 #include "softmmu_template.h"
1923 #include "softmmu_template.h"
1926 #include "softmmu_template.h"
1928 static void do_unaligned_access(target_ulong addr
, int is_write
, int is_user
,
1931 #ifdef DEBUG_UNALIGNED
1932 printf("Unaligned access to 0x%x from 0x%x\n", addr
, env
->pc
);
1934 raise_exception(TT_UNALIGNED
);
1937 /* try to fill the TLB and return an exception if error. If retaddr is
1938 NULL, it means that the function was called in C code (i.e. not
1939 from generated code or from helper.c) */
1940 /* XXX: fix it to restore all registers */
1941 void tlb_fill(target_ulong addr
, int is_write
, int mmu_idx
, void *retaddr
)
1943 TranslationBlock
*tb
;
1946 CPUState
*saved_env
;
1948 /* XXX: hack to restore env in all cases, even if not called from
1951 env
= cpu_single_env
;
1953 ret
= cpu_sparc_handle_mmu_fault(env
, addr
, is_write
, mmu_idx
, 1);
1956 /* now we have a real cpu fault */
1957 pc
= (unsigned long)retaddr
;
1958 tb
= tb_find_pc(pc
);
1960 /* the PC is inside the translated code. It means that we have
1961 a virtual CPU fault */
1962 cpu_restore_state(tb
, env
, pc
, (void *)T2
);
1972 #ifndef TARGET_SPARC64
1973 void do_unassigned_access(target_phys_addr_t addr
, int is_write
, int is_exec
,
1976 CPUState
*saved_env
;
1978 /* XXX: hack to restore env in all cases, even if not called from
1981 env
= cpu_single_env
;
1982 #ifdef DEBUG_UNASSIGNED
1984 printf("Unassigned mem %s access to " TARGET_FMT_plx
" asi 0x%02x from "
1986 is_exec
? "exec" : is_write
? "write" : "read", addr
, is_asi
,
1989 printf("Unassigned mem %s access to " TARGET_FMT_plx
" from "
1991 is_exec
? "exec" : is_write
? "write" : "read", addr
, env
->pc
);
1993 if (env
->mmuregs
[3]) /* Fault status register */
1994 env
->mmuregs
[3] = 1; /* overflow (not read before another fault) */
1996 env
->mmuregs
[3] |= 1 << 16;
1998 env
->mmuregs
[3] |= 1 << 5;
2000 env
->mmuregs
[3] |= 1 << 6;
2002 env
->mmuregs
[3] |= 1 << 7;
2003 env
->mmuregs
[3] |= (5 << 2) | 2;
2004 env
->mmuregs
[4] = addr
; /* Fault address register */
2005 if ((env
->mmuregs
[0] & MMU_E
) && !(env
->mmuregs
[0] & MMU_NF
)) {
2007 raise_exception(TT_CODE_ACCESS
);
2009 raise_exception(TT_DATA_ACCESS
);
2014 void do_unassigned_access(target_phys_addr_t addr
, int is_write
, int is_exec
,
2017 #ifdef DEBUG_UNASSIGNED
2018 CPUState
*saved_env
;
2020 /* XXX: hack to restore env in all cases, even if not called from
2023 env
= cpu_single_env
;
2024 printf("Unassigned mem access to " TARGET_FMT_plx
" from " TARGET_FMT_lx
"\n",
2029 raise_exception(TT_CODE_ACCESS
);
2031 raise_exception(TT_DATA_ACCESS
);