2 #include "host-utils.h"
4 #if !defined(CONFIG_USER_ONLY)
5 #include "softmmu_exec.h"
6 #endif /* !defined(CONFIG_USER_ONLY) */
11 //#define DEBUG_UNALIGNED
12 //#define DEBUG_UNASSIGNED
16 #define DPRINTF_MMU(fmt, args...) \
17 do { printf("MMU: " fmt , ##args); } while (0)
19 #define DPRINTF_MMU(fmt, args...) do {} while (0)
23 #define DPRINTF_MXCC(fmt, args...) \
24 do { printf("MXCC: " fmt , ##args); } while (0)
26 #define DPRINTF_MXCC(fmt, args...) do {} while (0)
30 #define DPRINTF_ASI(fmt, args...) \
31 do { printf("ASI: " fmt , ##args); } while (0)
33 #define DPRINTF_ASI(fmt, args...) do {} while (0)
37 #define ABI32_MASK(addr) do { (addr) &= 0xffffffffULL; } while (0)
39 #define ABI32_MASK(addr) do {} while (0)
42 void raise_exception(int tt)
44 env->exception_index = tt;
48 void helper_trap(target_ulong nb_trap)
50 env->exception_index = TT_TRAP + (nb_trap & 0x7f);
54 void helper_trapcc(target_ulong nb_trap, target_ulong do_trap)
57 env->exception_index = TT_TRAP + (nb_trap & 0x7f);
62 void helper_check_align(target_ulong addr, uint32_t align)
65 #ifdef DEBUG_UNALIGNED
66 printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
69 raise_exception(TT_UNALIGNED);
73 #define F_HELPER(name, p) void helper_f##name##p(void)
75 #define F_BINOP(name) \
78 FT0 = float32_ ## name (FT0, FT1, &env->fp_status); \
82 DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
86 QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \
95 void helper_fsmuld(void)
97 DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
98 float32_to_float64(FT1, &env->fp_status),
102 void helper_fdmulq(void)
104 QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
105 float64_to_float128(DT1, &env->fp_status),
111 FT0 = float32_chs(FT1);
114 #ifdef TARGET_SPARC64
117 DT0 = float64_chs(DT1);
122 QT0 = float128_chs(QT1);
126 /* Integer to float conversion. */
129 FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
134 DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
139 QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
142 #ifdef TARGET_SPARC64
145 FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
150 DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
155 QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
160 /* floating point conversion */
161 void helper_fdtos(void)
163 FT0 = float64_to_float32(DT1, &env->fp_status);
166 void helper_fstod(void)
168 DT0 = float32_to_float64(FT1, &env->fp_status);
171 void helper_fqtos(void)
173 FT0 = float128_to_float32(QT1, &env->fp_status);
176 void helper_fstoq(void)
178 QT0 = float32_to_float128(FT1, &env->fp_status);
181 void helper_fqtod(void)
183 DT0 = float128_to_float64(QT1, &env->fp_status);
186 void helper_fdtoq(void)
188 QT0 = float64_to_float128(DT1, &env->fp_status);
191 /* Float to integer conversion. */
192 void helper_fstoi(void)
194 *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
197 void helper_fdtoi(void)
199 *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
202 void helper_fqtoi(void)
204 *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status);
207 #ifdef TARGET_SPARC64
208 void helper_fstox(void)
210 *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
213 void helper_fdtox(void)
215 *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
218 void helper_fqtox(void)
220 *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
223 void helper_faligndata(void)
227 tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
228 tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
229 *((uint64_t *)&DT0) = tmp;
232 void helper_movl_FT0_0(void)
234 *((uint32_t *)&FT0) = 0;
237 void helper_movl_DT0_0(void)
239 *((uint64_t *)&DT0) = 0;
242 void helper_movl_FT0_1(void)
244 *((uint32_t *)&FT0) = 0xffffffff;
247 void helper_movl_DT0_1(void)
249 *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
252 void helper_fnot(void)
254 *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
257 void helper_fnots(void)
259 *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
262 void helper_fnor(void)
264 *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
267 void helper_fnors(void)
269 *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
272 void helper_for(void)
274 *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
277 void helper_fors(void)
279 *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
282 void helper_fxor(void)
284 *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
287 void helper_fxors(void)
289 *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
292 void helper_fand(void)
294 *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
297 void helper_fands(void)
299 *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
302 void helper_fornot(void)
304 *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
307 void helper_fornots(void)
309 *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
312 void helper_fandnot(void)
314 *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
317 void helper_fandnots(void)
319 *(uint32_t *)&FT0 = *(uint32_t *)&FT0 & ~*(uint32_t *)&FT1;
322 void helper_fnand(void)
324 *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
327 void helper_fnands(void)
329 *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 & *(uint32_t *)&FT1);
332 void helper_fxnor(void)
334 *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
337 void helper_fxnors(void)
339 *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
342 #ifdef WORDS_BIGENDIAN
343 #define VIS_B64(n) b[7 - (n)]
344 #define VIS_W64(n) w[3 - (n)]
345 #define VIS_SW64(n) sw[3 - (n)]
346 #define VIS_L64(n) l[1 - (n)]
347 #define VIS_B32(n) b[3 - (n)]
348 #define VIS_W32(n) w[1 - (n)]
350 #define VIS_B64(n) b[n]
351 #define VIS_W64(n) w[n]
352 #define VIS_SW64(n) sw[n]
353 #define VIS_L64(n) l[n]
354 #define VIS_B32(n) b[n]
355 #define VIS_W32(n) w[n]
373 void helper_fpmerge(void)
380 // Reverse calculation order to handle overlap
381 d.VIS_B64(7) = s.VIS_B64(3);
382 d.VIS_B64(6) = d.VIS_B64(3);
383 d.VIS_B64(5) = s.VIS_B64(2);
384 d.VIS_B64(4) = d.VIS_B64(2);
385 d.VIS_B64(3) = s.VIS_B64(1);
386 d.VIS_B64(2) = d.VIS_B64(1);
387 d.VIS_B64(1) = s.VIS_B64(0);
388 //d.VIS_B64(0) = d.VIS_B64(0);
393 void helper_fmul8x16(void)
402 tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r); \
403 if ((tmp & 0xff) > 0x7f) \
405 d.VIS_W64(r) = tmp >> 8;
416 void helper_fmul8x16al(void)
425 tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r); \
426 if ((tmp & 0xff) > 0x7f) \
428 d.VIS_W64(r) = tmp >> 8;
439 void helper_fmul8x16au(void)
448 tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r); \
449 if ((tmp & 0xff) > 0x7f) \
451 d.VIS_W64(r) = tmp >> 8;
462 void helper_fmul8sux16(void)
471 tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
472 if ((tmp & 0xff) > 0x7f) \
474 d.VIS_W64(r) = tmp >> 8;
485 void helper_fmul8ulx16(void)
494 tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
495 if ((tmp & 0xff) > 0x7f) \
497 d.VIS_W64(r) = tmp >> 8;
508 void helper_fmuld8sux16(void)
517 tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
518 if ((tmp & 0xff) > 0x7f) \
522 // Reverse calculation order to handle overlap
530 void helper_fmuld8ulx16(void)
539 tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
540 if ((tmp & 0xff) > 0x7f) \
544 // Reverse calculation order to handle overlap
552 void helper_fexpand(void)
557 s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
559 d.VIS_L64(0) = s.VIS_W32(0) << 4;
560 d.VIS_L64(1) = s.VIS_W32(1) << 4;
561 d.VIS_L64(2) = s.VIS_W32(2) << 4;
562 d.VIS_L64(3) = s.VIS_W32(3) << 4;
567 #define VIS_HELPER(name, F) \
568 void name##16(void) \
575 d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0)); \
576 d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1)); \
577 d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2)); \
578 d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3)); \
583 void name##16s(void) \
590 d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0)); \
591 d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1)); \
596 void name##32(void) \
603 d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0)); \
604 d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1)); \
609 void name##32s(void) \
621 #define FADD(a, b) ((a) + (b))
622 #define FSUB(a, b) ((a) - (b))
623 VIS_HELPER(helper_fpadd, FADD)
624 VIS_HELPER(helper_fpsub, FSUB)
626 #define VIS_CMPHELPER(name, F) \
627 void name##16(void) \
634 d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0; \
635 d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0; \
636 d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0; \
637 d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0; \
642 void name##32(void) \
649 d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0; \
650 d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0; \
655 #define FCMPGT(a, b) ((a) > (b))
656 #define FCMPEQ(a, b) ((a) == (b))
657 #define FCMPLE(a, b) ((a) <= (b))
658 #define FCMPNE(a, b) ((a) != (b))
660 VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
661 VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
662 VIS_CMPHELPER(helper_fcmple, FCMPLE)
663 VIS_CMPHELPER(helper_fcmpne, FCMPNE)
666 void helper_check_ieee_exceptions(void)
670 status = get_float_exception_flags(&env->fp_status);
672 /* Copy IEEE 754 flags into FSR */
673 if (status & float_flag_invalid)
675 if (status & float_flag_overflow)
677 if (status & float_flag_underflow)
679 if (status & float_flag_divbyzero)
681 if (status & float_flag_inexact)
684 if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
685 /* Unmasked exception, generate a trap */
686 env->fsr |= FSR_FTT_IEEE_EXCP;
687 raise_exception(TT_FP_EXCP);
689 /* Accumulate exceptions */
690 env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
695 void helper_clear_float_exceptions(void)
697 set_float_exception_flags(0, &env->fp_status);
700 void helper_fabss(void)
702 FT0 = float32_abs(FT1);
705 #ifdef TARGET_SPARC64
706 void helper_fabsd(void)
708 DT0 = float64_abs(DT1);
711 void helper_fabsq(void)
713 QT0 = float128_abs(QT1);
717 void helper_fsqrts(void)
719 FT0 = float32_sqrt(FT1, &env->fp_status);
722 void helper_fsqrtd(void)
724 DT0 = float64_sqrt(DT1, &env->fp_status);
727 void helper_fsqrtq(void)
729 QT0 = float128_sqrt(QT1, &env->fp_status);
732 #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
733 void glue(helper_, name) (void) \
735 target_ulong new_fsr; \
737 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
738 switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
739 case float_relation_unordered: \
740 new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
741 if ((env->fsr & FSR_NVM) || TRAP) { \
742 env->fsr |= new_fsr; \
743 env->fsr |= FSR_NVC; \
744 env->fsr |= FSR_FTT_IEEE_EXCP; \
745 raise_exception(TT_FP_EXCP); \
747 env->fsr |= FSR_NVA; \
750 case float_relation_less: \
751 new_fsr = FSR_FCC0 << FS; \
753 case float_relation_greater: \
754 new_fsr = FSR_FCC1 << FS; \
760 env->fsr |= new_fsr; \
763 GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
764 GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
766 GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
767 GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
769 GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
770 GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
772 #ifdef TARGET_SPARC64
773 GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
774 GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
775 GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
777 GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
778 GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
779 GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
781 GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
782 GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
783 GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
785 GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
786 GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
787 GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
789 GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
790 GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
791 GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
793 GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
794 GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
795 GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
798 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && defined(DEBUG_MXCC)
799 static void dump_mxcc(CPUState *env)
801 printf("mxccdata: %016llx %016llx %016llx %016llx\n",
802 env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]);
803 printf("mxccregs: %016llx %016llx %016llx %016llx\n"
804 " %016llx %016llx %016llx %016llx\n",
805 env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3],
806 env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]);
810 #if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
811 && defined(DEBUG_ASI)
812 static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
818 DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
819 addr, asi, r1 & 0xff);
822 DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
823 addr, asi, r1 & 0xffff);
826 DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
827 addr, asi, r1 & 0xffffffff);
830 DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
837 #ifndef TARGET_SPARC64
838 #ifndef CONFIG_USER_ONLY
839 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
842 #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
843 uint32_t last_addr = addr;
846 helper_check_align(addr, size - 1);
848 case 2: /* SuperSparc MXCC registers */
850 case 0x01c00a00: /* MXCC control register */
852 ret = env->mxccregs[3];
854 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
856 case 0x01c00a04: /* MXCC control register */
858 ret = env->mxccregs[3];
860 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
862 case 0x01c00c00: /* Module reset register */
864 ret = env->mxccregs[5];
865 // should we do something here?
867 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
869 case 0x01c00f00: /* MBus port address register */
871 ret = env->mxccregs[7];
873 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
876 DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size);
879 DPRINTF_MXCC("asi = %d, size = %d, sign = %d, addr = %08x -> ret = %08x,"
880 "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
885 case 3: /* MMU probe */
889 mmulev = (addr >> 8) & 15;
893 ret = mmu_probe(env, addr, mmulev);
894 DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
898 case 4: /* read MMU regs */
900 int reg = (addr >> 8) & 0x1f;
902 ret = env->mmuregs[reg];
903 if (reg == 3) /* Fault status cleared on read */
905 else if (reg == 0x13) /* Fault status read */
906 ret = env->mmuregs[3];
907 else if (reg == 0x14) /* Fault address read */
908 ret = env->mmuregs[4];
909 DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
912 case 5: // Turbosparc ITLB Diagnostic
913 case 6: // Turbosparc DTLB Diagnostic
914 case 7: // Turbosparc IOTLB Diagnostic
916 case 9: /* Supervisor code access */
919 ret = ldub_code(addr);
922 ret = lduw_code(addr & ~1);
926 ret = ldl_code(addr & ~3);
929 ret = ldq_code(addr & ~7);
933 case 0xa: /* User data access */
936 ret = ldub_user(addr);
939 ret = lduw_user(addr & ~1);
943 ret = ldl_user(addr & ~3);
946 ret = ldq_user(addr & ~7);
950 case 0xb: /* Supervisor data access */
953 ret = ldub_kernel(addr);
956 ret = lduw_kernel(addr & ~1);
960 ret = ldl_kernel(addr & ~3);
963 ret = ldq_kernel(addr & ~7);
967 case 0xc: /* I-cache tag */
968 case 0xd: /* I-cache data */
969 case 0xe: /* D-cache tag */
970 case 0xf: /* D-cache data */
972 case 0x20: /* MMU passthrough */
975 ret = ldub_phys(addr);
978 ret = lduw_phys(addr & ~1);
982 ret = ldl_phys(addr & ~3);
985 ret = ldq_phys(addr & ~7);
989 case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
992 ret = ldub_phys((target_phys_addr_t)addr
993 | ((target_phys_addr_t)(asi & 0xf) << 32));
996 ret = lduw_phys((target_phys_addr_t)(addr & ~1)
997 | ((target_phys_addr_t)(asi & 0xf) << 32));
1001 ret = ldl_phys((target_phys_addr_t)(addr & ~3)
1002 | ((target_phys_addr_t)(asi & 0xf) << 32));
1005 ret = ldq_phys((target_phys_addr_t)(addr & ~7)
1006 | ((target_phys_addr_t)(asi & 0xf) << 32));
1010 case 0x30: // Turbosparc secondary cache diagnostic
1011 case 0x31: // Turbosparc RAM snoop
1012 case 0x32: // Turbosparc page table descriptor diagnostic
1013 case 0x39: /* data cache diagnostic register */
1016 case 8: /* User code access, XXX */
1018 do_unassigned_access(addr, 0, 0, asi);
1028 ret = (int16_t) ret;
1031 ret = (int32_t) ret;
1038 dump_asi("read ", last_addr, asi, size, ret);
1043 void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
1045 helper_check_align(addr, size - 1);
1047 case 2: /* SuperSparc MXCC registers */
1049 case 0x01c00000: /* MXCC stream data register 0 */
1051 env->mxccdata[0] = val;
1053 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1055 case 0x01c00008: /* MXCC stream data register 1 */
1057 env->mxccdata[1] = val;
1059 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1061 case 0x01c00010: /* MXCC stream data register 2 */
1063 env->mxccdata[2] = val;
1065 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1067 case 0x01c00018: /* MXCC stream data register 3 */
1069 env->mxccdata[3] = val;
1071 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1073 case 0x01c00100: /* MXCC stream source */
1075 env->mxccregs[0] = val;
1077 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1078 env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 0);
1079 env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 8);
1080 env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16);
1081 env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24);
1083 case 0x01c00200: /* MXCC stream destination */
1085 env->mxccregs[1] = val;
1087 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1088 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0, env->mxccdata[0]);
1089 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8, env->mxccdata[1]);
1090 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]);
1091 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]);
1093 case 0x01c00a00: /* MXCC control register */
1095 env->mxccregs[3] = val;
1097 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1099 case 0x01c00a04: /* MXCC control register */
1101 env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | val;
1103 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1105 case 0x01c00e00: /* MXCC error register */
1106 // writing a 1 bit clears the error
1108 env->mxccregs[6] &= ~val;
1110 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1112 case 0x01c00f00: /* MBus port address register */
1114 env->mxccregs[7] = val;
1116 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1119 DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size);
1122 DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %08x\n", asi, size, addr, val);
1127 case 3: /* MMU flush */
1131 mmulev = (addr >> 8) & 15;
1132 DPRINTF_MMU("mmu flush level %d\n", mmulev);
1134 case 0: // flush page
1135 tlb_flush_page(env, addr & 0xfffff000);
1137 case 1: // flush segment (256k)
1138 case 2: // flush region (16M)
1139 case 3: // flush context (4G)
1140 case 4: // flush entire
1151 case 4: /* write MMU regs */
1153 int reg = (addr >> 8) & 0x1f;
1156 oldreg = env->mmuregs[reg];
1158 case 0: // Control Register
1159 env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
1161 // Mappings generated during no-fault mode or MMU
1162 // disabled mode are invalid in normal mode
1163 if ((oldreg & (MMU_E | MMU_NF | env->mmu_bm)) !=
1164 (env->mmuregs[reg] & (MMU_E | MMU_NF | env->mmu_bm)))
1167 case 1: // Context Table Pointer Register
1168 env->mmuregs[reg] = val & env->mmu_ctpr_mask;
1170 case 2: // Context Register
1171 env->mmuregs[reg] = val & env->mmu_cxr_mask;
1172 if (oldreg != env->mmuregs[reg]) {
1173 /* we flush when the MMU context changes because
1174 QEMU has no MMU context support */
1178 case 3: // Synchronous Fault Status Register with Clear
1179 case 4: // Synchronous Fault Address Register
1181 case 0x10: // TLB Replacement Control Register
1182 env->mmuregs[reg] = val & env->mmu_trcr_mask;
1184 case 0x13: // Synchronous Fault Status Register with Read and Clear
1185 env->mmuregs[3] = val & env->mmu_sfsr_mask;
1187 case 0x14: // Synchronous Fault Address Register
1188 env->mmuregs[4] = val;
1191 env->mmuregs[reg] = val;
1194 if (oldreg != env->mmuregs[reg]) {
1195 DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
1202 case 5: // Turbosparc ITLB Diagnostic
1203 case 6: // Turbosparc DTLB Diagnostic
1204 case 7: // Turbosparc IOTLB Diagnostic
1206 case 0xa: /* User data access */
1209 stb_user(addr, val);
1212 stw_user(addr & ~1, val);
1216 stl_user(addr & ~3, val);
1219 stq_user(addr & ~7, val);
1223 case 0xb: /* Supervisor data access */
1226 stb_kernel(addr, val);
1229 stw_kernel(addr & ~1, val);
1233 stl_kernel(addr & ~3, val);
1236 stq_kernel(addr & ~7, val);
1240 case 0xc: /* I-cache tag */
1241 case 0xd: /* I-cache data */
1242 case 0xe: /* D-cache tag */
1243 case 0xf: /* D-cache data */
1244 case 0x10: /* I/D-cache flush page */
1245 case 0x11: /* I/D-cache flush segment */
1246 case 0x12: /* I/D-cache flush region */
1247 case 0x13: /* I/D-cache flush context */
1248 case 0x14: /* I/D-cache flush user */
1250 case 0x17: /* Block copy, sta access */
1256 uint32_t src = val & ~3, dst = addr & ~3, temp;
1258 for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1259 temp = ldl_kernel(src);
1260 stl_kernel(dst, temp);
1264 case 0x1f: /* Block fill, stda access */
1267 // fill 32 bytes with val
1269 uint32_t dst = addr & 7;
1271 for (i = 0; i < 32; i += 8, dst += 8)
1272 stq_kernel(dst, val);
1275 case 0x20: /* MMU passthrough */
1279 stb_phys(addr, val);
1282 stw_phys(addr & ~1, val);
1286 stl_phys(addr & ~3, val);
1289 stq_phys(addr & ~7, val);
1294 case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1298 stb_phys((target_phys_addr_t)addr
1299 | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1302 stw_phys((target_phys_addr_t)(addr & ~1)
1303 | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1307 stl_phys((target_phys_addr_t)(addr & ~3)
1308 | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1311 stq_phys((target_phys_addr_t)(addr & ~7)
1312 | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1317 case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
1318 case 0x31: // store buffer data, Ross RT620 I-cache flush or
1319 // Turbosparc snoop RAM
1320 case 0x32: // store buffer control or Turbosparc page table descriptor diagnostic
1321 case 0x36: /* I-cache flash clear */
1322 case 0x37: /* D-cache flash clear */
1323 case 0x38: /* breakpoint diagnostics */
1324 case 0x4c: /* breakpoint action */
1326 case 8: /* User code access, XXX */
1327 case 9: /* Supervisor code access, XXX */
1329 do_unassigned_access(addr, 1, 0, asi);
1333 dump_asi("write", addr, asi, size, val);
1337 #endif /* CONFIG_USER_ONLY */
1338 #else /* TARGET_SPARC64 */
1340 #ifdef CONFIG_USER_ONLY
1341 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1344 #if defined(DEBUG_ASI)
1345 target_ulong last_addr = addr;
1349 raise_exception(TT_PRIV_ACT);
1351 helper_check_align(addr, size - 1);
1355 case 0x80: // Primary
1356 case 0x82: // Primary no-fault
1357 case 0x88: // Primary LE
1358 case 0x8a: // Primary no-fault LE
1362 ret = ldub_raw(addr);
1365 ret = lduw_raw(addr & ~1);
1368 ret = ldl_raw(addr & ~3);
1372 ret = ldq_raw(addr & ~7);
1377 case 0x81: // Secondary
1378 case 0x83: // Secondary no-fault
1379 case 0x89: // Secondary LE
1380 case 0x8b: // Secondary no-fault LE
1387 /* Convert from little endian */
1389 case 0x88: // Primary LE
1390 case 0x89: // Secondary LE
1391 case 0x8a: // Primary no-fault LE
1392 case 0x8b: // Secondary no-fault LE
1410 /* Convert to signed number */
1417 ret = (int16_t) ret;
1420 ret = (int32_t) ret;
1427 dump_asi("read ", last_addr, asi, size, ret);
1432 void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1435 dump_asi("write", addr, asi, size, val);
1438 raise_exception(TT_PRIV_ACT);
1440 helper_check_align(addr, size - 1);
1443 /* Convert to little endian */
1445 case 0x88: // Primary LE
1446 case 0x89: // Secondary LE
1449 addr = bswap16(addr);
1452 addr = bswap32(addr);
1455 addr = bswap64(addr);
1465 case 0x80: // Primary
1466 case 0x88: // Primary LE
1473 stw_raw(addr & ~1, val);
1476 stl_raw(addr & ~3, val);
1480 stq_raw(addr & ~7, val);
1485 case 0x81: // Secondary
1486 case 0x89: // Secondary LE
1490 case 0x82: // Primary no-fault, RO
1491 case 0x83: // Secondary no-fault, RO
1492 case 0x8a: // Primary no-fault LE, RO
1493 case 0x8b: // Secondary no-fault LE, RO
1495 do_unassigned_access(addr, 1, 0, 1);
1500 #else /* CONFIG_USER_ONLY */
1502 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1505 #if defined(DEBUG_ASI)
1506 target_ulong last_addr = addr;
1509 if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1510 || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1511 raise_exception(TT_PRIV_ACT);
1513 helper_check_align(addr, size - 1);
1515 case 0x10: // As if user primary
1516 case 0x18: // As if user primary LE
1517 case 0x80: // Primary
1518 case 0x82: // Primary no-fault
1519 case 0x88: // Primary LE
1520 case 0x8a: // Primary no-fault LE
1521 if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1522 if (env->hpstate & HS_PRIV) {
1525 ret = ldub_hypv(addr);
1528 ret = lduw_hypv(addr & ~1);
1531 ret = ldl_hypv(addr & ~3);
1535 ret = ldq_hypv(addr & ~7);
1541 ret = ldub_kernel(addr);
1544 ret = lduw_kernel(addr & ~1);
1547 ret = ldl_kernel(addr & ~3);
1551 ret = ldq_kernel(addr & ~7);
1558 ret = ldub_user(addr);
1561 ret = lduw_user(addr & ~1);
1564 ret = ldl_user(addr & ~3);
1568 ret = ldq_user(addr & ~7);
1573 case 0x14: // Bypass
1574 case 0x15: // Bypass, non-cacheable
1575 case 0x1c: // Bypass LE
1576 case 0x1d: // Bypass, non-cacheable LE
1580 ret = ldub_phys(addr);
1583 ret = lduw_phys(addr & ~1);
1586 ret = ldl_phys(addr & ~3);
1590 ret = ldq_phys(addr & ~7);
1595 case 0x04: // Nucleus
1596 case 0x0c: // Nucleus Little Endian (LE)
1597 case 0x11: // As if user secondary
1598 case 0x19: // As if user secondary LE
1599 case 0x24: // Nucleus quad LDD 128 bit atomic
1600 case 0x2c: // Nucleus quad LDD 128 bit atomic
1601 case 0x4a: // UPA config
1602 case 0x81: // Secondary
1603 case 0x83: // Secondary no-fault
1604 case 0x89: // Secondary LE
1605 case 0x8b: // Secondary no-fault LE
1611 case 0x50: // I-MMU regs
1613 int reg = (addr >> 3) & 0xf;
1615 ret = env->immuregs[reg];
1618 case 0x51: // I-MMU 8k TSB pointer
1619 case 0x52: // I-MMU 64k TSB pointer
1620 case 0x55: // I-MMU data access
1623 case 0x56: // I-MMU tag read
1627 for (i = 0; i < 64; i++) {
1628 // Valid, ctx match, vaddr match
1629 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1630 env->itlb_tag[i] == addr) {
1631 ret = env->itlb_tag[i];
1637 case 0x58: // D-MMU regs
1639 int reg = (addr >> 3) & 0xf;
1641 ret = env->dmmuregs[reg];
1644 case 0x5e: // D-MMU tag read
1648 for (i = 0; i < 64; i++) {
1649 // Valid, ctx match, vaddr match
1650 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1651 env->dtlb_tag[i] == addr) {
1652 ret = env->dtlb_tag[i];
1658 case 0x59: // D-MMU 8k TSB pointer
1659 case 0x5a: // D-MMU 64k TSB pointer
1660 case 0x5b: // D-MMU data pointer
1661 case 0x5d: // D-MMU data access
1662 case 0x48: // Interrupt dispatch, RO
1663 case 0x49: // Interrupt data receive
1664 case 0x7f: // Incoming interrupt vector, RO
1667 case 0x54: // I-MMU data in, WO
1668 case 0x57: // I-MMU demap, WO
1669 case 0x5c: // D-MMU data in, WO
1670 case 0x5f: // D-MMU demap, WO
1671 case 0x77: // Interrupt vector, WO
1673 do_unassigned_access(addr, 0, 0, 1);
1678 /* Convert from little endian */
1680 case 0x0c: // Nucleus Little Endian (LE)
1681 case 0x18: // As if user primary LE
1682 case 0x19: // As if user secondary LE
1683 case 0x1c: // Bypass LE
1684 case 0x1d: // Bypass, non-cacheable LE
1685 case 0x88: // Primary LE
1686 case 0x89: // Secondary LE
1687 case 0x8a: // Primary no-fault LE
1688 case 0x8b: // Secondary no-fault LE
1706 /* Convert to signed number */
1713 ret = (int16_t) ret;
1716 ret = (int32_t) ret;
1723 dump_asi("read ", last_addr, asi, size, ret);
1728 void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1731 dump_asi("write", addr, asi, size, val);
1733 if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1734 || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1735 raise_exception(TT_PRIV_ACT);
1737 helper_check_align(addr, size - 1);
1738 /* Convert to little endian */
1740 case 0x0c: // Nucleus Little Endian (LE)
1741 case 0x18: // As if user primary LE
1742 case 0x19: // As if user secondary LE
1743 case 0x1c: // Bypass LE
1744 case 0x1d: // Bypass, non-cacheable LE
1745 case 0x88: // Primary LE
1746 case 0x89: // Secondary LE
1749 addr = bswap16(addr);
1752 addr = bswap32(addr);
1755 addr = bswap64(addr);
1765 case 0x10: // As if user primary
1766 case 0x18: // As if user primary LE
1767 case 0x80: // Primary
1768 case 0x88: // Primary LE
1769 if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1770 if (env->hpstate & HS_PRIV) {
1773 stb_hypv(addr, val);
1776 stw_hypv(addr & ~1, val);
1779 stl_hypv(addr & ~3, val);
1783 stq_hypv(addr & ~7, val);
1789 stb_kernel(addr, val);
1792 stw_kernel(addr & ~1, val);
1795 stl_kernel(addr & ~3, val);
1799 stq_kernel(addr & ~7, val);
1806 stb_user(addr, val);
1809 stw_user(addr & ~1, val);
1812 stl_user(addr & ~3, val);
1816 stq_user(addr & ~7, val);
1821 case 0x14: // Bypass
1822 case 0x15: // Bypass, non-cacheable
1823 case 0x1c: // Bypass LE
1824 case 0x1d: // Bypass, non-cacheable LE
1828 stb_phys(addr, val);
1831 stw_phys(addr & ~1, val);
1834 stl_phys(addr & ~3, val);
1838 stq_phys(addr & ~7, val);
1843 case 0x04: // Nucleus
1844 case 0x0c: // Nucleus Little Endian (LE)
1845 case 0x11: // As if user secondary
1846 case 0x19: // As if user secondary LE
1847 case 0x24: // Nucleus quad LDD 128 bit atomic
1848 case 0x2c: // Nucleus quad LDD 128 bit atomic
1849 case 0x4a: // UPA config
1850 case 0x81: // Secondary
1851 case 0x89: // Secondary LE
1859 env->lsu = val & (DMMU_E | IMMU_E);
1860 // Mappings generated during D/I MMU disabled mode are
1861 // invalid in normal mode
1862 if (oldreg != env->lsu) {
1863 DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
1871 case 0x50: // I-MMU regs
1873 int reg = (addr >> 3) & 0xf;
1876 oldreg = env->immuregs[reg];
1881 case 1: // Not in I-MMU
1888 val = 0; // Clear SFSR
1890 case 5: // TSB access
1891 case 6: // Tag access
1895 env->immuregs[reg] = val;
1896 if (oldreg != env->immuregs[reg]) {
1897 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1904 case 0x54: // I-MMU data in
1908 // Try finding an invalid entry
1909 for (i = 0; i < 64; i++) {
1910 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
1911 env->itlb_tag[i] = env->immuregs[6];
1912 env->itlb_tte[i] = val;
1916 // Try finding an unlocked entry
1917 for (i = 0; i < 64; i++) {
1918 if ((env->itlb_tte[i] & 0x40) == 0) {
1919 env->itlb_tag[i] = env->immuregs[6];
1920 env->itlb_tte[i] = val;
1927 case 0x55: // I-MMU data access
1929 unsigned int i = (addr >> 3) & 0x3f;
1931 env->itlb_tag[i] = env->immuregs[6];
1932 env->itlb_tte[i] = val;
1935 case 0x57: // I-MMU demap
1938 case 0x58: // D-MMU regs
1940 int reg = (addr >> 3) & 0xf;
1943 oldreg = env->dmmuregs[reg];
1949 if ((val & 1) == 0) {
1950 val = 0; // Clear SFSR, Fault address
1951 env->dmmuregs[4] = 0;
1953 env->dmmuregs[reg] = val;
1955 case 1: // Primary context
1956 case 2: // Secondary context
1957 case 5: // TSB access
1958 case 6: // Tag access
1959 case 7: // Virtual Watchpoint
1960 case 8: // Physical Watchpoint
1964 env->dmmuregs[reg] = val;
1965 if (oldreg != env->dmmuregs[reg]) {
1966 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
1973 case 0x5c: // D-MMU data in
1977 // Try finding an invalid entry
1978 for (i = 0; i < 64; i++) {
1979 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
1980 env->dtlb_tag[i] = env->dmmuregs[6];
1981 env->dtlb_tte[i] = val;
1985 // Try finding an unlocked entry
1986 for (i = 0; i < 64; i++) {
1987 if ((env->dtlb_tte[i] & 0x40) == 0) {
1988 env->dtlb_tag[i] = env->dmmuregs[6];
1989 env->dtlb_tte[i] = val;
1996 case 0x5d: // D-MMU data access
1998 unsigned int i = (addr >> 3) & 0x3f;
2000 env->dtlb_tag[i] = env->dmmuregs[6];
2001 env->dtlb_tte[i] = val;
2004 case 0x5f: // D-MMU demap
2005 case 0x49: // Interrupt data receive
2008 case 0x51: // I-MMU 8k TSB pointer, RO
2009 case 0x52: // I-MMU 64k TSB pointer, RO
2010 case 0x56: // I-MMU tag read, RO
2011 case 0x59: // D-MMU 8k TSB pointer, RO
2012 case 0x5a: // D-MMU 64k TSB pointer, RO
2013 case 0x5b: // D-MMU data pointer, RO
2014 case 0x5e: // D-MMU tag read, RO
2015 case 0x48: // Interrupt dispatch, RO
2016 case 0x7f: // Incoming interrupt vector, RO
2017 case 0x82: // Primary no-fault, RO
2018 case 0x83: // Secondary no-fault, RO
2019 case 0x8a: // Primary no-fault LE, RO
2020 case 0x8b: // Secondary no-fault LE, RO
2022 do_unassigned_access(addr, 1, 0, 1);
2026 #endif /* CONFIG_USER_ONLY */
2028 void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2033 helper_check_align(addr, 3);
2035 case 0xf0: // Block load primary
2036 case 0xf1: // Block load secondary
2037 case 0xf8: // Block load primary LE
2038 case 0xf9: // Block load secondary LE
2040 raise_exception(TT_ILL_INSN);
2043 helper_check_align(addr, 0x3f);
2044 for (i = 0; i < 16; i++) {
2045 *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, 0);
2054 val = helper_ld_asi(addr, asi, size, 0);
2058 *((uint32_t *)&FT0) = val;
2061 *((int64_t *)&DT0) = val;
2069 void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2072 target_ulong val = 0;
2074 helper_check_align(addr, 3);
2076 case 0xf0: // Block store primary
2077 case 0xf1: // Block store secondary
2078 case 0xf8: // Block store primary LE
2079 case 0xf9: // Block store secondary LE
2081 raise_exception(TT_ILL_INSN);
2084 helper_check_align(addr, 0x3f);
2085 for (i = 0; i < 16; i++) {
2086 val = *(uint32_t *)&env->fpr[rd++];
2087 helper_st_asi(addr, val, asi & 0x8f, 4);
2099 val = *((uint32_t *)&FT0);
2102 val = *((int64_t *)&DT0);
2108 helper_st_asi(addr, val, asi, size);
2111 target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2112 target_ulong val2, uint32_t asi)
2116 val1 &= 0xffffffffUL;
2117 ret = helper_ld_asi(addr, asi, 4, 0);
2118 ret &= 0xffffffffUL;
2120 helper_st_asi(addr, val2 & 0xffffffffUL, asi, 4);
2124 target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2125 target_ulong val2, uint32_t asi)
2129 ret = helper_ld_asi(addr, asi, 8, 0);
2131 helper_st_asi(addr, val2, asi, 8);
2134 #endif /* TARGET_SPARC64 */
2136 #ifndef TARGET_SPARC64
2137 void helper_rett(void)
2141 if (env->psret == 1)
2142 raise_exception(TT_ILL_INSN);
2145 cwp = (env->cwp + 1) & (NWINDOWS - 1);
2146 if (env->wim & (1 << cwp)) {
2147 raise_exception(TT_WIN_UNF);
2150 env->psrs = env->psrps;
2154 target_ulong helper_udiv(target_ulong a, target_ulong b)
2159 x0 = a | ((uint64_t) (env->y) << 32);
2163 raise_exception(TT_DIV_ZERO);
2167 if (x0 > 0xffffffff) {
2176 target_ulong helper_sdiv(target_ulong a, target_ulong b)
2181 x0 = a | ((int64_t) (env->y) << 32);
2185 raise_exception(TT_DIV_ZERO);
2189 if ((int32_t) x0 != x0) {
2191 return x0 < 0? 0x80000000: 0x7fffffff;
2198 uint64_t helper_pack64(target_ulong high, target_ulong low)
2200 return ((uint64_t)high << 32) | (uint64_t)(low & 0xffffffff);
2203 void helper_stdf(target_ulong addr, int mem_idx)
2205 helper_check_align(addr, 7);
2206 #if !defined(CONFIG_USER_ONLY)
2209 stfq_user(addr, DT0);
2212 stfq_kernel(addr, DT0);
2214 #ifdef TARGET_SPARC64
2216 stfq_hypv(addr, DT0);
2224 stfq_raw(addr, DT0);
2228 void helper_lddf(target_ulong addr, int mem_idx)
2230 helper_check_align(addr, 7);
2231 #if !defined(CONFIG_USER_ONLY)
2234 DT0 = ldfq_user(addr);
2237 DT0 = ldfq_kernel(addr);
2239 #ifdef TARGET_SPARC64
2241 DT0 = ldfq_hypv(addr);
2249 DT0 = ldfq_raw(addr);
2253 void helper_ldqf(target_ulong addr, int mem_idx)
2255 // XXX add 128 bit load
2258 helper_check_align(addr, 7);
2259 #if !defined(CONFIG_USER_ONLY)
2262 u.ll.upper = ldq_user(addr);
2263 u.ll.lower = ldq_user(addr + 8);
2267 u.ll.upper = ldq_kernel(addr);
2268 u.ll.lower = ldq_kernel(addr + 8);
2271 #ifdef TARGET_SPARC64
2273 u.ll.upper = ldq_hypv(addr);
2274 u.ll.lower = ldq_hypv(addr + 8);
2283 u.ll.upper = ldq_raw(addr);
2284 u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
2289 void helper_stqf(target_ulong addr, int mem_idx)
2291 // XXX add 128 bit store
2294 helper_check_align(addr, 7);
2295 #if !defined(CONFIG_USER_ONLY)
2299 stq_user(addr, u.ll.upper);
2300 stq_user(addr + 8, u.ll.lower);
2304 stq_kernel(addr, u.ll.upper);
2305 stq_kernel(addr + 8, u.ll.lower);
2307 #ifdef TARGET_SPARC64
2310 stq_hypv(addr, u.ll.upper);
2311 stq_hypv(addr + 8, u.ll.lower);
2320 stq_raw(addr, u.ll.upper);
2321 stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
2325 void helper_ldfsr(void)
2329 PUT_FSR32(env, *((uint32_t *) &FT0));
2330 switch (env->fsr & FSR_RD_MASK) {
2331 case FSR_RD_NEAREST:
2332 rnd_mode = float_round_nearest_even;
2336 rnd_mode = float_round_to_zero;
2339 rnd_mode = float_round_up;
2342 rnd_mode = float_round_down;
2345 set_float_rounding_mode(rnd_mode, &env->fp_status);
2348 void helper_stfsr(void)
2350 *((uint32_t *) &FT0) = GET_FSR32(env);
2353 void helper_debug(void)
2355 env->exception_index = EXCP_DEBUG;
2359 #ifndef TARGET_SPARC64
2360 /* XXX: use another pointer for %iN registers to avoid slow wrapping
2362 void helper_save(void)
2366 cwp = (env->cwp - 1) & (NWINDOWS - 1);
2367 if (env->wim & (1 << cwp)) {
2368 raise_exception(TT_WIN_OVF);
2373 void helper_restore(void)
2377 cwp = (env->cwp + 1) & (NWINDOWS - 1);
2378 if (env->wim & (1 << cwp)) {
2379 raise_exception(TT_WIN_UNF);
2384 void helper_wrpsr(target_ulong new_psr)
2386 if ((new_psr & PSR_CWP) >= NWINDOWS)
2387 raise_exception(TT_ILL_INSN);
2389 PUT_PSR(env, new_psr);
2392 target_ulong helper_rdpsr(void)
2394 return GET_PSR(env);
2398 /* XXX: use another pointer for %iN registers to avoid slow wrapping
2400 void helper_save(void)
2404 cwp = (env->cwp - 1) & (NWINDOWS - 1);
2405 if (env->cansave == 0) {
2406 raise_exception(TT_SPILL | (env->otherwin != 0 ?
2407 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2408 ((env->wstate & 0x7) << 2)));
2410 if (env->cleanwin - env->canrestore == 0) {
2411 // XXX Clean windows without trap
2412 raise_exception(TT_CLRWIN);
2421 void helper_restore(void)
2425 cwp = (env->cwp + 1) & (NWINDOWS - 1);
2426 if (env->canrestore == 0) {
2427 raise_exception(TT_FILL | (env->otherwin != 0 ?
2428 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2429 ((env->wstate & 0x7) << 2)));
2437 void helper_flushw(void)
2439 if (env->cansave != NWINDOWS - 2) {
2440 raise_exception(TT_SPILL | (env->otherwin != 0 ?
2441 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2442 ((env->wstate & 0x7) << 2)));
2446 void helper_saved(void)
2449 if (env->otherwin == 0)
2455 void helper_restored(void)
2458 if (env->cleanwin < NWINDOWS - 1)
2460 if (env->otherwin == 0)
2466 target_ulong helper_rdccr(void)
2468 return GET_CCR(env);
2471 void helper_wrccr(target_ulong new_ccr)
2473 PUT_CCR(env, new_ccr);
2476 // CWP handling is reversed in V9, but we still use the V8 register
2478 target_ulong helper_rdcwp(void)
2480 return GET_CWP64(env);
2483 void helper_wrcwp(target_ulong new_cwp)
2485 PUT_CWP64(env, new_cwp);
2488 // This function uses non-native bit order
2489 #define GET_FIELD(X, FROM, TO) \
2490 ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
2492 // This function uses the order in the manuals, i.e. bit 0 is 2^0
2493 #define GET_FIELD_SP(X, FROM, TO) \
2494 GET_FIELD(X, 63 - (TO), 63 - (FROM))
2496 target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
2498 return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
2499 (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
2500 (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
2501 (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
2502 (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
2503 (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
2504 (((pixel_addr >> 55) & 1) << 4) |
2505 (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
2506 GET_FIELD_SP(pixel_addr, 11, 12);
2509 target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
2513 tmp = addr + offset;
2515 env->gsr |= tmp & 7ULL;
2519 target_ulong helper_popc(target_ulong val)
2521 return ctpop64(val);
2524 static inline uint64_t *get_gregset(uint64_t pstate)
2539 static inline void change_pstate(uint64_t new_pstate)
2541 uint64_t pstate_regs, new_pstate_regs;
2542 uint64_t *src, *dst;
2544 pstate_regs = env->pstate & 0xc01;
2545 new_pstate_regs = new_pstate & 0xc01;
2546 if (new_pstate_regs != pstate_regs) {
2547 // Switch global register bank
2548 src = get_gregset(new_pstate_regs);
2549 dst = get_gregset(pstate_regs);
2550 memcpy32(dst, env->gregs);
2551 memcpy32(env->gregs, src);
2553 env->pstate = new_pstate;
2556 void helper_wrpstate(target_ulong new_state)
2558 change_pstate(new_state & 0xf3f);
2561 void helper_done(void)
2564 env->tsptr = &env->ts[env->tl];
2565 env->pc = env->tsptr->tpc;
2566 env->npc = env->tsptr->tnpc + 4;
2567 PUT_CCR(env, env->tsptr->tstate >> 32);
2568 env->asi = (env->tsptr->tstate >> 24) & 0xff;
2569 change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2570 PUT_CWP64(env, env->tsptr->tstate & 0xff);
2573 void helper_retry(void)
2576 env->tsptr = &env->ts[env->tl];
2577 env->pc = env->tsptr->tpc;
2578 env->npc = env->tsptr->tnpc;
2579 PUT_CCR(env, env->tsptr->tstate >> 32);
2580 env->asi = (env->tsptr->tstate >> 24) & 0xff;
2581 change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2582 PUT_CWP64(env, env->tsptr->tstate & 0xff);
2586 void set_cwp(int new_cwp)
2588 /* put the modified wrap registers at their proper location */
2589 if (env->cwp == (NWINDOWS - 1))
2590 memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
2592 /* put the wrap registers at their temporary location */
2593 if (new_cwp == (NWINDOWS - 1))
2594 memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
2595 env->regwptr = env->regbase + (new_cwp * 16);
2596 REGWPTR = env->regwptr;
2599 void cpu_set_cwp(CPUState *env1, int new_cwp)
2601 CPUState *saved_env;
2603 target_ulong *saved_regwptr;
2608 saved_regwptr = REGWPTR;
2614 REGWPTR = saved_regwptr;
2618 #ifdef TARGET_SPARC64
2620 static const char * const excp_names[0x50] = {
2621 [TT_TFAULT] = "Instruction Access Fault",
2622 [TT_TMISS] = "Instruction Access MMU Miss",
2623 [TT_CODE_ACCESS] = "Instruction Access Error",
2624 [TT_ILL_INSN] = "Illegal Instruction",
2625 [TT_PRIV_INSN] = "Privileged Instruction",
2626 [TT_NFPU_INSN] = "FPU Disabled",
2627 [TT_FP_EXCP] = "FPU Exception",
2628 [TT_TOVF] = "Tag Overflow",
2629 [TT_CLRWIN] = "Clean Windows",
2630 [TT_DIV_ZERO] = "Division By Zero",
2631 [TT_DFAULT] = "Data Access Fault",
2632 [TT_DMISS] = "Data Access MMU Miss",
2633 [TT_DATA_ACCESS] = "Data Access Error",
2634 [TT_DPROT] = "Data Protection Error",
2635 [TT_UNALIGNED] = "Unaligned Memory Access",
2636 [TT_PRIV_ACT] = "Privileged Action",
2637 [TT_EXTINT | 0x1] = "External Interrupt 1",
2638 [TT_EXTINT | 0x2] = "External Interrupt 2",
2639 [TT_EXTINT | 0x3] = "External Interrupt 3",
2640 [TT_EXTINT | 0x4] = "External Interrupt 4",
2641 [TT_EXTINT | 0x5] = "External Interrupt 5",
2642 [TT_EXTINT | 0x6] = "External Interrupt 6",
2643 [TT_EXTINT | 0x7] = "External Interrupt 7",
2644 [TT_EXTINT | 0x8] = "External Interrupt 8",
2645 [TT_EXTINT | 0x9] = "External Interrupt 9",
2646 [TT_EXTINT | 0xa] = "External Interrupt 10",
2647 [TT_EXTINT | 0xb] = "External Interrupt 11",
2648 [TT_EXTINT | 0xc] = "External Interrupt 12",
2649 [TT_EXTINT | 0xd] = "External Interrupt 13",
2650 [TT_EXTINT | 0xe] = "External Interrupt 14",
2651 [TT_EXTINT | 0xf] = "External Interrupt 15",
2655 void do_interrupt(int intno)
2658 if (loglevel & CPU_LOG_INT) {
2662 if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80))
2664 else if (intno >= 0x100)
2665 name = "Trap Instruction";
2666 else if (intno >= 0xc0)
2667 name = "Window Fill";
2668 else if (intno >= 0x80)
2669 name = "Window Spill";
2671 name = excp_names[intno];
2676 fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
2677 " SP=%016" PRIx64 "\n",
2680 env->npc, env->regwptr[6]);
2681 cpu_dump_state(env, logfile, fprintf, 0);
2687 fprintf(logfile, " code=");
2688 ptr = (uint8_t *)env->pc;
2689 for(i = 0; i < 16; i++) {
2690 fprintf(logfile, " %02x", ldub(ptr + i));
2692 fprintf(logfile, "\n");
2698 #if !defined(CONFIG_USER_ONLY)
2699 if (env->tl == MAXTL) {
2700 cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
2704 env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
2705 ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
2707 env->tsptr->tpc = env->pc;
2708 env->tsptr->tnpc = env->npc;
2709 env->tsptr->tt = intno;
2710 change_pstate(PS_PEF | PS_PRIV | PS_AG);
2712 if (intno == TT_CLRWIN)
2713 set_cwp((env->cwp - 1) & (NWINDOWS - 1));
2714 else if ((intno & 0x1c0) == TT_SPILL)
2715 set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1));
2716 else if ((intno & 0x1c0) == TT_FILL)
2717 set_cwp((env->cwp + 1) & (NWINDOWS - 1));
2718 env->tbr &= ~0x7fffULL;
2719 env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
2720 if (env->tl < MAXTL - 1) {
2723 env->pstate |= PS_RED;
2724 if (env->tl != MAXTL)
2727 env->tsptr = &env->ts[env->tl];
2729 env->npc = env->pc + 4;
2730 env->exception_index = 0;
2734 static const char * const excp_names[0x80] = {
2735 [TT_TFAULT] = "Instruction Access Fault",
2736 [TT_ILL_INSN] = "Illegal Instruction",
2737 [TT_PRIV_INSN] = "Privileged Instruction",
2738 [TT_NFPU_INSN] = "FPU Disabled",
2739 [TT_WIN_OVF] = "Window Overflow",
2740 [TT_WIN_UNF] = "Window Underflow",
2741 [TT_UNALIGNED] = "Unaligned Memory Access",
2742 [TT_FP_EXCP] = "FPU Exception",
2743 [TT_DFAULT] = "Data Access Fault",
2744 [TT_TOVF] = "Tag Overflow",
2745 [TT_EXTINT | 0x1] = "External Interrupt 1",
2746 [TT_EXTINT | 0x2] = "External Interrupt 2",
2747 [TT_EXTINT | 0x3] = "External Interrupt 3",
2748 [TT_EXTINT | 0x4] = "External Interrupt 4",
2749 [TT_EXTINT | 0x5] = "External Interrupt 5",
2750 [TT_EXTINT | 0x6] = "External Interrupt 6",
2751 [TT_EXTINT | 0x7] = "External Interrupt 7",
2752 [TT_EXTINT | 0x8] = "External Interrupt 8",
2753 [TT_EXTINT | 0x9] = "External Interrupt 9",
2754 [TT_EXTINT | 0xa] = "External Interrupt 10",
2755 [TT_EXTINT | 0xb] = "External Interrupt 11",
2756 [TT_EXTINT | 0xc] = "External Interrupt 12",
2757 [TT_EXTINT | 0xd] = "External Interrupt 13",
2758 [TT_EXTINT | 0xe] = "External Interrupt 14",
2759 [TT_EXTINT | 0xf] = "External Interrupt 15",
2760 [TT_TOVF] = "Tag Overflow",
2761 [TT_CODE_ACCESS] = "Instruction Access Error",
2762 [TT_DATA_ACCESS] = "Data Access Error",
2763 [TT_DIV_ZERO] = "Division By Zero",
2764 [TT_NCP_INSN] = "Coprocessor Disabled",
2768 void do_interrupt(int intno)
2773 if (loglevel & CPU_LOG_INT) {
2777 if (intno < 0 || intno >= 0x100)
2779 else if (intno >= 0x80)
2780 name = "Trap Instruction";
2782 name = excp_names[intno];
2787 fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
2790 env->npc, env->regwptr[6]);
2791 cpu_dump_state(env, logfile, fprintf, 0);
2797 fprintf(logfile, " code=");
2798 ptr = (uint8_t *)env->pc;
2799 for(i = 0; i < 16; i++) {
2800 fprintf(logfile, " %02x", ldub(ptr + i));
2802 fprintf(logfile, "\n");
2808 #if !defined(CONFIG_USER_ONLY)
2809 if (env->psret == 0) {
2810 cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
2815 cwp = (env->cwp - 1) & (NWINDOWS - 1);
2817 env->regwptr[9] = env->pc;
2818 env->regwptr[10] = env->npc;
2819 env->psrps = env->psrs;
2821 env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
2823 env->npc = env->pc + 4;
2824 env->exception_index = 0;
2828 #if !defined(CONFIG_USER_ONLY)
2830 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2833 #define MMUSUFFIX _mmu
2834 #define ALIGNED_ONLY
2836 # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
2838 # define GETPC() (__builtin_return_address(0))
2842 #include "softmmu_template.h"
2845 #include "softmmu_template.h"
2848 #include "softmmu_template.h"
2851 #include "softmmu_template.h"
2853 /* XXX: make it generic ? */
2854 static void cpu_restore_state2(void *retaddr)
2856 TranslationBlock *tb;
2860 /* now we have a real cpu fault */
2861 pc = (unsigned long)retaddr;
2862 tb = tb_find_pc(pc);
2864 /* the PC is inside the translated code. It means that we have
2865 a virtual CPU fault */
2866 cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
2871 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2874 #ifdef DEBUG_UNALIGNED
2875 printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
2876 "\n", addr, env->pc);
2878 cpu_restore_state2(retaddr);
2879 raise_exception(TT_UNALIGNED);
2882 /* try to fill the TLB and return an exception if error. If retaddr is
2883 NULL, it means that the function was called in C code (i.e. not
2884 from generated code or from helper.c) */
2885 /* XXX: fix it to restore all registers */
2886 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
2889 CPUState *saved_env;
2891 /* XXX: hack to restore env in all cases, even if not called from
2894 env = cpu_single_env;
2896 ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
2898 cpu_restore_state2(retaddr);
2906 #ifndef TARGET_SPARC64
2907 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2910 CPUState *saved_env;
2912 /* XXX: hack to restore env in all cases, even if not called from
2915 env = cpu_single_env;
2916 #ifdef DEBUG_UNASSIGNED
2918 printf("Unassigned mem %s access to " TARGET_FMT_plx " asi 0x%02x from "
2920 is_exec ? "exec" : is_write ? "write" : "read", addr, is_asi,
2923 printf("Unassigned mem %s access to " TARGET_FMT_plx " from "
2925 is_exec ? "exec" : is_write ? "write" : "read", addr, env->pc);
2927 if (env->mmuregs[3]) /* Fault status register */
2928 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
2930 env->mmuregs[3] |= 1 << 16;
2932 env->mmuregs[3] |= 1 << 5;
2934 env->mmuregs[3] |= 1 << 6;
2936 env->mmuregs[3] |= 1 << 7;
2937 env->mmuregs[3] |= (5 << 2) | 2;
2938 env->mmuregs[4] = addr; /* Fault address register */
2939 if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
2941 raise_exception(TT_CODE_ACCESS);
2943 raise_exception(TT_DATA_ACCESS);
2948 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2951 #ifdef DEBUG_UNASSIGNED
2952 CPUState *saved_env;
2954 /* XXX: hack to restore env in all cases, even if not called from
2957 env = cpu_single_env;
2958 printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
2963 raise_exception(TT_CODE_ACCESS);
2965 raise_exception(TT_DATA_ACCESS);