]>
git.proxmox.com Git - qemu.git/blob - target-sparc/op_helper.c
2 #include "host-utils.h"
7 //#define DEBUG_UNALIGNED
8 //#define DEBUG_UNASSIGNED
11 //#define DEBUG_PSTATE
14 #define DPRINTF_MMU(fmt, ...) \
15 do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0)
17 #define DPRINTF_MMU(fmt, ...) do {} while (0)
21 #define DPRINTF_MXCC(fmt, ...) \
22 do { printf("MXCC: " fmt , ## __VA_ARGS__); } while (0)
24 #define DPRINTF_MXCC(fmt, ...) do {} while (0)
28 #define DPRINTF_ASI(fmt, ...) \
29 do { printf("ASI: " fmt , ## __VA_ARGS__); } while (0)
33 #define DPRINTF_PSTATE(fmt, ...) \
34 do { printf("PSTATE: " fmt , ## __VA_ARGS__); } while (0)
36 #define DPRINTF_PSTATE(fmt, ...) do {} while (0)
41 #define AM_CHECK(env1) ((env1)->pstate & PS_AM)
43 #define AM_CHECK(env1) (1)
47 #define DT0 (env->dt0)
48 #define DT1 (env->dt1)
49 #define QT0 (env->qt0)
50 #define QT1 (env->qt1)
52 #if defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
53 static void do_unassigned_access(target_ulong addr
, int is_write
, int is_exec
,
54 int is_asi
, int size
);
57 #if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
58 // Calculates TSB pointer value for fault page size 8k or 64k
59 static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register
,
60 uint64_t tag_access_register
,
63 uint64_t tsb_base
= tsb_register
& ~0x1fffULL
;
64 int tsb_split
= (tsb_register
& 0x1000ULL
) ? 1 : 0;
65 int tsb_size
= tsb_register
& 0xf;
67 // discard lower 13 bits which hold tag access context
68 uint64_t tag_access_va
= tag_access_register
& ~0x1fffULL
;
71 uint64_t tsb_base_mask
= ~0x1fffULL
;
72 uint64_t va
= tag_access_va
;
74 // move va bits to correct position
75 if (page_size
== 8*1024) {
77 } else if (page_size
== 64*1024) {
82 tsb_base_mask
<<= tsb_size
;
85 // calculate tsb_base mask and adjust va if split is in use
87 if (page_size
== 8*1024) {
88 va
&= ~(1ULL << (13 + tsb_size
));
89 } else if (page_size
== 64*1024) {
90 va
|= (1ULL << (13 + tsb_size
));
95 return ((tsb_base
& tsb_base_mask
) | (va
& ~tsb_base_mask
)) & ~0xfULL
;
98 // Calculates tag target register value by reordering bits
99 // in tag access register
100 static uint64_t ultrasparc_tag_target(uint64_t tag_access_register
)
102 return ((tag_access_register
& 0x1fff) << 48) | (tag_access_register
>> 22);
105 static void replace_tlb_entry(SparcTLBEntry
*tlb
,
106 uint64_t tlb_tag
, uint64_t tlb_tte
,
109 target_ulong mask
, size
, va
, offset
;
111 // flush page range if translation is valid
112 if (TTE_IS_VALID(tlb
->tte
)) {
114 mask
= 0xffffffffffffe000ULL
;
115 mask
<<= 3 * ((tlb
->tte
>> 61) & 3);
118 va
= tlb
->tag
& mask
;
120 for (offset
= 0; offset
< size
; offset
+= TARGET_PAGE_SIZE
) {
121 tlb_flush_page(env1
, va
+ offset
);
129 static void demap_tlb(SparcTLBEntry
*tlb
, target_ulong demap_addr
,
130 const char* strmmu
, CPUState
*env1
)
136 int is_demap_context
= (demap_addr
>> 6) & 1;
139 switch ((demap_addr
>> 4) & 3) {
141 context
= env1
->dmmu
.mmu_primary_context
;
144 context
= env1
->dmmu
.mmu_secondary_context
;
154 for (i
= 0; i
< 64; i
++) {
155 if (TTE_IS_VALID(tlb
[i
].tte
)) {
157 if (is_demap_context
) {
158 // will remove non-global entries matching context value
159 if (TTE_IS_GLOBAL(tlb
[i
].tte
) ||
160 !tlb_compare_context(&tlb
[i
], context
)) {
165 // will remove any entry matching VA
166 mask
= 0xffffffffffffe000ULL
;
167 mask
<<= 3 * ((tlb
[i
].tte
>> 61) & 3);
169 if (!compare_masked(demap_addr
, tlb
[i
].tag
, mask
)) {
173 // entry should be global or matching context value
174 if (!TTE_IS_GLOBAL(tlb
[i
].tte
) &&
175 !tlb_compare_context(&tlb
[i
], context
)) {
180 replace_tlb_entry(&tlb
[i
], 0, 0, env1
);
182 DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu
, i
);
183 dump_mmu(stdout
, fprintf
, env1
);
189 static void replace_tlb_1bit_lru(SparcTLBEntry
*tlb
,
190 uint64_t tlb_tag
, uint64_t tlb_tte
,
191 const char* strmmu
, CPUState
*env1
)
193 unsigned int i
, replace_used
;
195 // Try replacing invalid entry
196 for (i
= 0; i
< 64; i
++) {
197 if (!TTE_IS_VALID(tlb
[i
].tte
)) {
198 replace_tlb_entry(&tlb
[i
], tlb_tag
, tlb_tte
, env1
);
200 DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu
, i
);
201 dump_mmu(stdout
, fprintf
, env1
);
207 // All entries are valid, try replacing unlocked entry
209 for (replace_used
= 0; replace_used
< 2; ++replace_used
) {
211 // Used entries are not replaced on first pass
213 for (i
= 0; i
< 64; i
++) {
214 if (!TTE_IS_LOCKED(tlb
[i
].tte
) && !TTE_IS_USED(tlb
[i
].tte
)) {
216 replace_tlb_entry(&tlb
[i
], tlb_tag
, tlb_tte
, env1
);
218 DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
219 strmmu
, (replace_used
?"used":"unused"), i
);
220 dump_mmu(stdout
, fprintf
, env1
);
226 // Now reset used bit and search for unused entries again
228 for (i
= 0; i
< 64; i
++) {
229 TTE_SET_UNUSED(tlb
[i
].tte
);
234 DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu
);
241 static inline target_ulong
address_mask(CPUState
*env1
, target_ulong addr
)
243 #ifdef TARGET_SPARC64
245 addr
&= 0xffffffffULL
;
250 /* returns true if access using this ASI is to have address translated by MMU
251 otherwise access is to raw physical address */
252 static inline int is_translating_asi(int asi
)
254 #ifdef TARGET_SPARC64
255 /* Ultrasparc IIi translating asi
256 - note this list is defined by cpu implementation
271 /* TODO: check sparc32 bits */
276 static inline target_ulong
asi_address_mask(CPUState
*env1
,
277 int asi
, target_ulong addr
)
279 if (is_translating_asi(asi
)) {
280 return address_mask(env
, addr
);
286 static void raise_exception(int tt
)
288 env
->exception_index
= tt
;
292 void HELPER(raise_exception
)(int tt
)
297 void helper_check_align(target_ulong addr
, uint32_t align
)
300 #ifdef DEBUG_UNALIGNED
301 printf("Unaligned access to 0x" TARGET_FMT_lx
" from 0x" TARGET_FMT_lx
302 "\n", addr
, env
->pc
);
304 raise_exception(TT_UNALIGNED
);
308 #define F_HELPER(name, p) void helper_f##name##p(void)
310 #define F_BINOP(name) \
311 float32 helper_f ## name ## s (float32 src1, float32 src2) \
313 return float32_ ## name (src1, src2, &env->fp_status); \
317 DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
321 QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \
330 void helper_fsmuld(float32 src1
, float32 src2
)
332 DT0
= float64_mul(float32_to_float64(src1
, &env
->fp_status
),
333 float32_to_float64(src2
, &env
->fp_status
),
337 void helper_fdmulq(void)
339 QT0
= float128_mul(float64_to_float128(DT0
, &env
->fp_status
),
340 float64_to_float128(DT1
, &env
->fp_status
),
344 float32
helper_fnegs(float32 src
)
346 return float32_chs(src
);
349 #ifdef TARGET_SPARC64
352 DT0
= float64_chs(DT1
);
357 QT0
= float128_chs(QT1
);
361 /* Integer to float conversion. */
362 float32
helper_fitos(int32_t src
)
364 return int32_to_float32(src
, &env
->fp_status
);
367 void helper_fitod(int32_t src
)
369 DT0
= int32_to_float64(src
, &env
->fp_status
);
372 void helper_fitoq(int32_t src
)
374 QT0
= int32_to_float128(src
, &env
->fp_status
);
377 #ifdef TARGET_SPARC64
378 float32
helper_fxtos(void)
380 return int64_to_float32(*((int64_t *)&DT1
), &env
->fp_status
);
385 DT0
= int64_to_float64(*((int64_t *)&DT1
), &env
->fp_status
);
390 QT0
= int64_to_float128(*((int64_t *)&DT1
), &env
->fp_status
);
395 /* floating point conversion */
396 float32
helper_fdtos(void)
398 return float64_to_float32(DT1
, &env
->fp_status
);
401 void helper_fstod(float32 src
)
403 DT0
= float32_to_float64(src
, &env
->fp_status
);
406 float32
helper_fqtos(void)
408 return float128_to_float32(QT1
, &env
->fp_status
);
411 void helper_fstoq(float32 src
)
413 QT0
= float32_to_float128(src
, &env
->fp_status
);
416 void helper_fqtod(void)
418 DT0
= float128_to_float64(QT1
, &env
->fp_status
);
421 void helper_fdtoq(void)
423 QT0
= float64_to_float128(DT1
, &env
->fp_status
);
426 /* Float to integer conversion. */
427 int32_t helper_fstoi(float32 src
)
429 return float32_to_int32_round_to_zero(src
, &env
->fp_status
);
432 int32_t helper_fdtoi(void)
434 return float64_to_int32_round_to_zero(DT1
, &env
->fp_status
);
437 int32_t helper_fqtoi(void)
439 return float128_to_int32_round_to_zero(QT1
, &env
->fp_status
);
442 #ifdef TARGET_SPARC64
443 void helper_fstox(float32 src
)
445 *((int64_t *)&DT0
) = float32_to_int64_round_to_zero(src
, &env
->fp_status
);
448 void helper_fdtox(void)
450 *((int64_t *)&DT0
) = float64_to_int64_round_to_zero(DT1
, &env
->fp_status
);
453 void helper_fqtox(void)
455 *((int64_t *)&DT0
) = float128_to_int64_round_to_zero(QT1
, &env
->fp_status
);
458 void helper_faligndata(void)
462 tmp
= (*((uint64_t *)&DT0
)) << ((env
->gsr
& 7) * 8);
463 /* on many architectures a shift of 64 does nothing */
464 if ((env
->gsr
& 7) != 0) {
465 tmp
|= (*((uint64_t *)&DT1
)) >> (64 - (env
->gsr
& 7) * 8);
467 *((uint64_t *)&DT0
) = tmp
;
470 #ifdef HOST_WORDS_BIGENDIAN
471 #define VIS_B64(n) b[7 - (n)]
472 #define VIS_W64(n) w[3 - (n)]
473 #define VIS_SW64(n) sw[3 - (n)]
474 #define VIS_L64(n) l[1 - (n)]
475 #define VIS_B32(n) b[3 - (n)]
476 #define VIS_W32(n) w[1 - (n)]
478 #define VIS_B64(n) b[n]
479 #define VIS_W64(n) w[n]
480 #define VIS_SW64(n) sw[n]
481 #define VIS_L64(n) l[n]
482 #define VIS_B32(n) b[n]
483 #define VIS_W32(n) w[n]
501 void helper_fpmerge(void)
508 // Reverse calculation order to handle overlap
509 d
.VIS_B64(7) = s
.VIS_B64(3);
510 d
.VIS_B64(6) = d
.VIS_B64(3);
511 d
.VIS_B64(5) = s
.VIS_B64(2);
512 d
.VIS_B64(4) = d
.VIS_B64(2);
513 d
.VIS_B64(3) = s
.VIS_B64(1);
514 d
.VIS_B64(2) = d
.VIS_B64(1);
515 d
.VIS_B64(1) = s
.VIS_B64(0);
516 //d.VIS_B64(0) = d.VIS_B64(0);
521 void helper_fmul8x16(void)
530 tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r); \
531 if ((tmp & 0xff) > 0x7f) \
533 d.VIS_W64(r) = tmp >> 8;
544 void helper_fmul8x16al(void)
553 tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r); \
554 if ((tmp & 0xff) > 0x7f) \
556 d.VIS_W64(r) = tmp >> 8;
567 void helper_fmul8x16au(void)
576 tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r); \
577 if ((tmp & 0xff) > 0x7f) \
579 d.VIS_W64(r) = tmp >> 8;
590 void helper_fmul8sux16(void)
599 tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
600 if ((tmp & 0xff) > 0x7f) \
602 d.VIS_W64(r) = tmp >> 8;
613 void helper_fmul8ulx16(void)
622 tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
623 if ((tmp & 0xff) > 0x7f) \
625 d.VIS_W64(r) = tmp >> 8;
636 void helper_fmuld8sux16(void)
645 tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
646 if ((tmp & 0xff) > 0x7f) \
650 // Reverse calculation order to handle overlap
658 void helper_fmuld8ulx16(void)
667 tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
668 if ((tmp & 0xff) > 0x7f) \
672 // Reverse calculation order to handle overlap
680 void helper_fexpand(void)
685 s
.l
= (uint32_t)(*(uint64_t *)&DT0
& 0xffffffff);
687 d
.VIS_W64(0) = s
.VIS_B32(0) << 4;
688 d
.VIS_W64(1) = s
.VIS_B32(1) << 4;
689 d
.VIS_W64(2) = s
.VIS_B32(2) << 4;
690 d
.VIS_W64(3) = s
.VIS_B32(3) << 4;
695 #define VIS_HELPER(name, F) \
696 void name##16(void) \
703 d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0)); \
704 d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1)); \
705 d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2)); \
706 d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3)); \
711 uint32_t name##16s(uint32_t src1, uint32_t src2) \
718 d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0)); \
719 d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1)); \
724 void name##32(void) \
731 d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0)); \
732 d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1)); \
737 uint32_t name##32s(uint32_t src1, uint32_t src2) \
749 #define FADD(a, b) ((a) + (b))
750 #define FSUB(a, b) ((a) - (b))
751 VIS_HELPER(helper_fpadd
, FADD
)
752 VIS_HELPER(helper_fpsub
, FSUB
)
754 #define VIS_CMPHELPER(name, F) \
755 void name##16(void) \
762 d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0; \
763 d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0; \
764 d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0; \
765 d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0; \
770 void name##32(void) \
777 d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0; \
778 d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0; \
783 #define FCMPGT(a, b) ((a) > (b))
784 #define FCMPEQ(a, b) ((a) == (b))
785 #define FCMPLE(a, b) ((a) <= (b))
786 #define FCMPNE(a, b) ((a) != (b))
788 VIS_CMPHELPER(helper_fcmpgt
, FCMPGT
)
789 VIS_CMPHELPER(helper_fcmpeq
, FCMPEQ
)
790 VIS_CMPHELPER(helper_fcmple
, FCMPLE
)
791 VIS_CMPHELPER(helper_fcmpne
, FCMPNE
)
794 void helper_check_ieee_exceptions(void)
798 status
= get_float_exception_flags(&env
->fp_status
);
800 /* Copy IEEE 754 flags into FSR */
801 if (status
& float_flag_invalid
)
803 if (status
& float_flag_overflow
)
805 if (status
& float_flag_underflow
)
807 if (status
& float_flag_divbyzero
)
809 if (status
& float_flag_inexact
)
812 if ((env
->fsr
& FSR_CEXC_MASK
) & ((env
->fsr
& FSR_TEM_MASK
) >> 23)) {
813 /* Unmasked exception, generate a trap */
814 env
->fsr
|= FSR_FTT_IEEE_EXCP
;
815 raise_exception(TT_FP_EXCP
);
817 /* Accumulate exceptions */
818 env
->fsr
|= (env
->fsr
& FSR_CEXC_MASK
) << 5;
823 void helper_clear_float_exceptions(void)
825 set_float_exception_flags(0, &env
->fp_status
);
828 float32
helper_fabss(float32 src
)
830 return float32_abs(src
);
833 #ifdef TARGET_SPARC64
834 void helper_fabsd(void)
836 DT0
= float64_abs(DT1
);
839 void helper_fabsq(void)
841 QT0
= float128_abs(QT1
);
845 float32
helper_fsqrts(float32 src
)
847 return float32_sqrt(src
, &env
->fp_status
);
850 void helper_fsqrtd(void)
852 DT0
= float64_sqrt(DT1
, &env
->fp_status
);
855 void helper_fsqrtq(void)
857 QT0
= float128_sqrt(QT1
, &env
->fp_status
);
860 #define GEN_FCMP(name, size, reg1, reg2, FS, E) \
861 void glue(helper_, name) (void) \
863 env->fsr &= FSR_FTT_NMASK; \
864 if (E && (glue(size, _is_any_nan)(reg1) || \
865 glue(size, _is_any_nan)(reg2)) && \
866 (env->fsr & FSR_NVM)) { \
867 env->fsr |= FSR_NVC; \
868 env->fsr |= FSR_FTT_IEEE_EXCP; \
869 raise_exception(TT_FP_EXCP); \
871 switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
872 case float_relation_unordered: \
873 if ((env->fsr & FSR_NVM)) { \
874 env->fsr |= FSR_NVC; \
875 env->fsr |= FSR_FTT_IEEE_EXCP; \
876 raise_exception(TT_FP_EXCP); \
878 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
879 env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
880 env->fsr |= FSR_NVA; \
883 case float_relation_less: \
884 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
885 env->fsr |= FSR_FCC0 << FS; \
887 case float_relation_greater: \
888 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
889 env->fsr |= FSR_FCC1 << FS; \
892 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
896 #define GEN_FCMPS(name, size, FS, E) \
897 void glue(helper_, name)(float32 src1, float32 src2) \
899 env->fsr &= FSR_FTT_NMASK; \
900 if (E && (glue(size, _is_any_nan)(src1) || \
901 glue(size, _is_any_nan)(src2)) && \
902 (env->fsr & FSR_NVM)) { \
903 env->fsr |= FSR_NVC; \
904 env->fsr |= FSR_FTT_IEEE_EXCP; \
905 raise_exception(TT_FP_EXCP); \
907 switch (glue(size, _compare) (src1, src2, &env->fp_status)) { \
908 case float_relation_unordered: \
909 if ((env->fsr & FSR_NVM)) { \
910 env->fsr |= FSR_NVC; \
911 env->fsr |= FSR_FTT_IEEE_EXCP; \
912 raise_exception(TT_FP_EXCP); \
914 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
915 env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
916 env->fsr |= FSR_NVA; \
919 case float_relation_less: \
920 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
921 env->fsr |= FSR_FCC0 << FS; \
923 case float_relation_greater: \
924 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
925 env->fsr |= FSR_FCC1 << FS; \
928 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
933 GEN_FCMPS(fcmps
, float32
, 0, 0);
934 GEN_FCMP(fcmpd
, float64
, DT0
, DT1
, 0, 0);
936 GEN_FCMPS(fcmpes
, float32
, 0, 1);
937 GEN_FCMP(fcmped
, float64
, DT0
, DT1
, 0, 1);
939 GEN_FCMP(fcmpq
, float128
, QT0
, QT1
, 0, 0);
940 GEN_FCMP(fcmpeq
, float128
, QT0
, QT1
, 0, 1);
942 static uint32_t compute_all_flags(void)
944 return env
->psr
& PSR_ICC
;
947 static uint32_t compute_C_flags(void)
949 return env
->psr
& PSR_CARRY
;
952 static inline uint32_t get_NZ_icc(int32_t dst
)
958 } else if (dst
< 0) {
964 #ifdef TARGET_SPARC64
965 static uint32_t compute_all_flags_xcc(void)
967 return env
->xcc
& PSR_ICC
;
970 static uint32_t compute_C_flags_xcc(void)
972 return env
->xcc
& PSR_CARRY
;
975 static inline uint32_t get_NZ_xcc(target_long dst
)
981 } else if (dst
< 0) {
988 static inline uint32_t get_V_div_icc(target_ulong src2
)
998 static uint32_t compute_all_div(void)
1002 ret
= get_NZ_icc(CC_DST
);
1003 ret
|= get_V_div_icc(CC_SRC2
);
1007 static uint32_t compute_C_div(void)
1012 static inline uint32_t get_C_add_icc(uint32_t dst
, uint32_t src1
)
1022 static inline uint32_t get_C_addx_icc(uint32_t dst
, uint32_t src1
,
1027 if (((src1
& src2
) | (~dst
& (src1
| src2
))) & (1U << 31)) {
1033 static inline uint32_t get_V_add_icc(uint32_t dst
, uint32_t src1
,
1038 if (((src1
^ src2
^ -1) & (src1
^ dst
)) & (1U << 31)) {
1044 #ifdef TARGET_SPARC64
1045 static inline uint32_t get_C_add_xcc(target_ulong dst
, target_ulong src1
)
1055 static inline uint32_t get_C_addx_xcc(target_ulong dst
, target_ulong src1
,
1060 if (((src1
& src2
) | (~dst
& (src1
| src2
))) & (1ULL << 63)) {
1066 static inline uint32_t get_V_add_xcc(target_ulong dst
, target_ulong src1
,
1071 if (((src1
^ src2
^ -1) & (src1
^ dst
)) & (1ULL << 63)) {
1077 static uint32_t compute_all_add_xcc(void)
1081 ret
= get_NZ_xcc(CC_DST
);
1082 ret
|= get_C_add_xcc(CC_DST
, CC_SRC
);
1083 ret
|= get_V_add_xcc(CC_DST
, CC_SRC
, CC_SRC2
);
1087 static uint32_t compute_C_add_xcc(void)
1089 return get_C_add_xcc(CC_DST
, CC_SRC
);
1093 static uint32_t compute_all_add(void)
1097 ret
= get_NZ_icc(CC_DST
);
1098 ret
|= get_C_add_icc(CC_DST
, CC_SRC
);
1099 ret
|= get_V_add_icc(CC_DST
, CC_SRC
, CC_SRC2
);
1103 static uint32_t compute_C_add(void)
1105 return get_C_add_icc(CC_DST
, CC_SRC
);
1108 #ifdef TARGET_SPARC64
1109 static uint32_t compute_all_addx_xcc(void)
1113 ret
= get_NZ_xcc(CC_DST
);
1114 ret
|= get_C_addx_xcc(CC_DST
, CC_SRC
, CC_SRC2
);
1115 ret
|= get_V_add_xcc(CC_DST
, CC_SRC
, CC_SRC2
);
1119 static uint32_t compute_C_addx_xcc(void)
1123 ret
= get_C_addx_xcc(CC_DST
, CC_SRC
, CC_SRC2
);
1128 static uint32_t compute_all_addx(void)
1132 ret
= get_NZ_icc(CC_DST
);
1133 ret
|= get_C_addx_icc(CC_DST
, CC_SRC
, CC_SRC2
);
1134 ret
|= get_V_add_icc(CC_DST
, CC_SRC
, CC_SRC2
);
1138 static uint32_t compute_C_addx(void)
1142 ret
= get_C_addx_icc(CC_DST
, CC_SRC
, CC_SRC2
);
1146 static inline uint32_t get_V_tag_icc(target_ulong src1
, target_ulong src2
)
1150 if ((src1
| src2
) & 0x3) {
1156 static uint32_t compute_all_tadd(void)
1160 ret
= get_NZ_icc(CC_DST
);
1161 ret
|= get_C_add_icc(CC_DST
, CC_SRC
);
1162 ret
|= get_V_add_icc(CC_DST
, CC_SRC
, CC_SRC2
);
1163 ret
|= get_V_tag_icc(CC_SRC
, CC_SRC2
);
1167 static uint32_t compute_all_taddtv(void)
1171 ret
= get_NZ_icc(CC_DST
);
1172 ret
|= get_C_add_icc(CC_DST
, CC_SRC
);
1176 static inline uint32_t get_C_sub_icc(uint32_t src1
, uint32_t src2
)
1186 static inline uint32_t get_C_subx_icc(uint32_t dst
, uint32_t src1
,
1191 if (((~src1
& src2
) | (dst
& (~src1
| src2
))) & (1U << 31)) {
1197 static inline uint32_t get_V_sub_icc(uint32_t dst
, uint32_t src1
,
1202 if (((src1
^ src2
) & (src1
^ dst
)) & (1U << 31)) {
1209 #ifdef TARGET_SPARC64
1210 static inline uint32_t get_C_sub_xcc(target_ulong src1
, target_ulong src2
)
1220 static inline uint32_t get_C_subx_xcc(target_ulong dst
, target_ulong src1
,
1225 if (((~src1
& src2
) | (dst
& (~src1
| src2
))) & (1ULL << 63)) {
1231 static inline uint32_t get_V_sub_xcc(target_ulong dst
, target_ulong src1
,
1236 if (((src1
^ src2
) & (src1
^ dst
)) & (1ULL << 63)) {
1242 static uint32_t compute_all_sub_xcc(void)
1246 ret
= get_NZ_xcc(CC_DST
);
1247 ret
|= get_C_sub_xcc(CC_SRC
, CC_SRC2
);
1248 ret
|= get_V_sub_xcc(CC_DST
, CC_SRC
, CC_SRC2
);
1252 static uint32_t compute_C_sub_xcc(void)
1254 return get_C_sub_xcc(CC_SRC
, CC_SRC2
);
1258 static uint32_t compute_all_sub(void)
1262 ret
= get_NZ_icc(CC_DST
);
1263 ret
|= get_C_sub_icc(CC_SRC
, CC_SRC2
);
1264 ret
|= get_V_sub_icc(CC_DST
, CC_SRC
, CC_SRC2
);
1268 static uint32_t compute_C_sub(void)
1270 return get_C_sub_icc(CC_SRC
, CC_SRC2
);
1273 #ifdef TARGET_SPARC64
1274 static uint32_t compute_all_subx_xcc(void)
1278 ret
= get_NZ_xcc(CC_DST
);
1279 ret
|= get_C_subx_xcc(CC_DST
, CC_SRC
, CC_SRC2
);
1280 ret
|= get_V_sub_xcc(CC_DST
, CC_SRC
, CC_SRC2
);
1284 static uint32_t compute_C_subx_xcc(void)
1288 ret
= get_C_subx_xcc(CC_DST
, CC_SRC
, CC_SRC2
);
1293 static uint32_t compute_all_subx(void)
1297 ret
= get_NZ_icc(CC_DST
);
1298 ret
|= get_C_subx_icc(CC_DST
, CC_SRC
, CC_SRC2
);
1299 ret
|= get_V_sub_icc(CC_DST
, CC_SRC
, CC_SRC2
);
1303 static uint32_t compute_C_subx(void)
1307 ret
= get_C_subx_icc(CC_DST
, CC_SRC
, CC_SRC2
);
1311 static uint32_t compute_all_tsub(void)
1315 ret
= get_NZ_icc(CC_DST
);
1316 ret
|= get_C_sub_icc(CC_SRC
, CC_SRC2
);
1317 ret
|= get_V_sub_icc(CC_DST
, CC_SRC
, CC_SRC2
);
1318 ret
|= get_V_tag_icc(CC_SRC
, CC_SRC2
);
1322 static uint32_t compute_all_tsubtv(void)
1326 ret
= get_NZ_icc(CC_DST
);
1327 ret
|= get_C_sub_icc(CC_SRC
, CC_SRC2
);
1331 static uint32_t compute_all_logic(void)
1333 return get_NZ_icc(CC_DST
);
1336 static uint32_t compute_C_logic(void)
1341 #ifdef TARGET_SPARC64
1342 static uint32_t compute_all_logic_xcc(void)
1344 return get_NZ_xcc(CC_DST
);
1348 typedef struct CCTable
{
1349 uint32_t (*compute_all
)(void); /* return all the flags */
1350 uint32_t (*compute_c
)(void); /* return the C flag */
1353 static const CCTable icc_table
[CC_OP_NB
] = {
1354 /* CC_OP_DYNAMIC should never happen */
1355 [CC_OP_FLAGS
] = { compute_all_flags
, compute_C_flags
},
1356 [CC_OP_DIV
] = { compute_all_div
, compute_C_div
},
1357 [CC_OP_ADD
] = { compute_all_add
, compute_C_add
},
1358 [CC_OP_ADDX
] = { compute_all_addx
, compute_C_addx
},
1359 [CC_OP_TADD
] = { compute_all_tadd
, compute_C_add
},
1360 [CC_OP_TADDTV
] = { compute_all_taddtv
, compute_C_add
},
1361 [CC_OP_SUB
] = { compute_all_sub
, compute_C_sub
},
1362 [CC_OP_SUBX
] = { compute_all_subx
, compute_C_subx
},
1363 [CC_OP_TSUB
] = { compute_all_tsub
, compute_C_sub
},
1364 [CC_OP_TSUBTV
] = { compute_all_tsubtv
, compute_C_sub
},
1365 [CC_OP_LOGIC
] = { compute_all_logic
, compute_C_logic
},
1368 #ifdef TARGET_SPARC64
1369 static const CCTable xcc_table
[CC_OP_NB
] = {
1370 /* CC_OP_DYNAMIC should never happen */
1371 [CC_OP_FLAGS
] = { compute_all_flags_xcc
, compute_C_flags_xcc
},
1372 [CC_OP_DIV
] = { compute_all_logic_xcc
, compute_C_logic
},
1373 [CC_OP_ADD
] = { compute_all_add_xcc
, compute_C_add_xcc
},
1374 [CC_OP_ADDX
] = { compute_all_addx_xcc
, compute_C_addx_xcc
},
1375 [CC_OP_TADD
] = { compute_all_add_xcc
, compute_C_add_xcc
},
1376 [CC_OP_TADDTV
] = { compute_all_add_xcc
, compute_C_add_xcc
},
1377 [CC_OP_SUB
] = { compute_all_sub_xcc
, compute_C_sub_xcc
},
1378 [CC_OP_SUBX
] = { compute_all_subx_xcc
, compute_C_subx_xcc
},
1379 [CC_OP_TSUB
] = { compute_all_sub_xcc
, compute_C_sub_xcc
},
1380 [CC_OP_TSUBTV
] = { compute_all_sub_xcc
, compute_C_sub_xcc
},
1381 [CC_OP_LOGIC
] = { compute_all_logic_xcc
, compute_C_logic
},
1385 void helper_compute_psr(void)
1389 new_psr
= icc_table
[CC_OP
].compute_all();
1391 #ifdef TARGET_SPARC64
1392 new_psr
= xcc_table
[CC_OP
].compute_all();
1395 CC_OP
= CC_OP_FLAGS
;
1398 uint32_t helper_compute_C_icc(void)
1402 ret
= icc_table
[CC_OP
].compute_c() >> PSR_CARRY_SHIFT
;
1406 static inline void memcpy32(target_ulong
*dst
, const target_ulong
*src
)
1418 static void set_cwp(int new_cwp
)
1420 /* put the modified wrap registers at their proper location */
1421 if (env
->cwp
== env
->nwindows
- 1) {
1422 memcpy32(env
->regbase
, env
->regbase
+ env
->nwindows
* 16);
1426 /* put the wrap registers at their temporary location */
1427 if (new_cwp
== env
->nwindows
- 1) {
1428 memcpy32(env
->regbase
+ env
->nwindows
* 16, env
->regbase
);
1430 env
->regwptr
= env
->regbase
+ (new_cwp
* 16);
1433 void cpu_set_cwp(CPUState
*env1
, int new_cwp
)
1435 CPUState
*saved_env
;
1443 static target_ulong
get_psr(void)
1445 helper_compute_psr();
1447 #if !defined (TARGET_SPARC64)
1448 return env
->version
| (env
->psr
& PSR_ICC
) |
1449 (env
->psref
? PSR_EF
: 0) |
1450 (env
->psrpil
<< 8) |
1451 (env
->psrs
? PSR_S
: 0) |
1452 (env
->psrps
? PSR_PS
: 0) |
1453 (env
->psret
? PSR_ET
: 0) | env
->cwp
;
1455 return env
->psr
& PSR_ICC
;
1459 target_ulong
cpu_get_psr(CPUState
*env1
)
1461 CPUState
*saved_env
;
1471 static void put_psr(target_ulong val
)
1473 env
->psr
= val
& PSR_ICC
;
1474 #if !defined (TARGET_SPARC64)
1475 env
->psref
= (val
& PSR_EF
)? 1 : 0;
1476 env
->psrpil
= (val
& PSR_PIL
) >> 8;
1478 #if ((!defined (TARGET_SPARC64)) && !defined(CONFIG_USER_ONLY))
1479 cpu_check_irqs(env
);
1481 #if !defined (TARGET_SPARC64)
1482 env
->psrs
= (val
& PSR_S
)? 1 : 0;
1483 env
->psrps
= (val
& PSR_PS
)? 1 : 0;
1484 env
->psret
= (val
& PSR_ET
)? 1 : 0;
1485 set_cwp(val
& PSR_CWP
);
1487 env
->cc_op
= CC_OP_FLAGS
;
1490 void cpu_put_psr(CPUState
*env1
, target_ulong val
)
1492 CPUState
*saved_env
;
1500 static int cwp_inc(int cwp
)
1502 if (unlikely(cwp
>= env
->nwindows
)) {
1503 cwp
-= env
->nwindows
;
1508 int cpu_cwp_inc(CPUState
*env1
, int cwp
)
1510 CPUState
*saved_env
;
1520 static int cwp_dec(int cwp
)
1522 if (unlikely(cwp
< 0)) {
1523 cwp
+= env
->nwindows
;
1528 int cpu_cwp_dec(CPUState
*env1
, int cwp
)
1530 CPUState
*saved_env
;
1540 #ifdef TARGET_SPARC64
1541 GEN_FCMPS(fcmps_fcc1
, float32
, 22, 0);
1542 GEN_FCMP(fcmpd_fcc1
, float64
, DT0
, DT1
, 22, 0);
1543 GEN_FCMP(fcmpq_fcc1
, float128
, QT0
, QT1
, 22, 0);
1545 GEN_FCMPS(fcmps_fcc2
, float32
, 24, 0);
1546 GEN_FCMP(fcmpd_fcc2
, float64
, DT0
, DT1
, 24, 0);
1547 GEN_FCMP(fcmpq_fcc2
, float128
, QT0
, QT1
, 24, 0);
1549 GEN_FCMPS(fcmps_fcc3
, float32
, 26, 0);
1550 GEN_FCMP(fcmpd_fcc3
, float64
, DT0
, DT1
, 26, 0);
1551 GEN_FCMP(fcmpq_fcc3
, float128
, QT0
, QT1
, 26, 0);
1553 GEN_FCMPS(fcmpes_fcc1
, float32
, 22, 1);
1554 GEN_FCMP(fcmped_fcc1
, float64
, DT0
, DT1
, 22, 1);
1555 GEN_FCMP(fcmpeq_fcc1
, float128
, QT0
, QT1
, 22, 1);
1557 GEN_FCMPS(fcmpes_fcc2
, float32
, 24, 1);
1558 GEN_FCMP(fcmped_fcc2
, float64
, DT0
, DT1
, 24, 1);
1559 GEN_FCMP(fcmpeq_fcc2
, float128
, QT0
, QT1
, 24, 1);
1561 GEN_FCMPS(fcmpes_fcc3
, float32
, 26, 1);
1562 GEN_FCMP(fcmped_fcc3
, float64
, DT0
, DT1
, 26, 1);
1563 GEN_FCMP(fcmpeq_fcc3
, float128
, QT0
, QT1
, 26, 1);
1567 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
1569 static void dump_mxcc(CPUState
*env
)
1571 printf("mxccdata: %016" PRIx64
" %016" PRIx64
" %016" PRIx64
" %016" PRIx64
1573 env
->mxccdata
[0], env
->mxccdata
[1],
1574 env
->mxccdata
[2], env
->mxccdata
[3]);
1575 printf("mxccregs: %016" PRIx64
" %016" PRIx64
" %016" PRIx64
" %016" PRIx64
1577 " %016" PRIx64
" %016" PRIx64
" %016" PRIx64
" %016" PRIx64
1579 env
->mxccregs
[0], env
->mxccregs
[1],
1580 env
->mxccregs
[2], env
->mxccregs
[3],
1581 env
->mxccregs
[4], env
->mxccregs
[5],
1582 env
->mxccregs
[6], env
->mxccregs
[7]);
1586 #if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
1587 && defined(DEBUG_ASI)
1588 static void dump_asi(const char *txt
, target_ulong addr
, int asi
, int size
,
1594 DPRINTF_ASI("%s "TARGET_FMT_lx
" asi 0x%02x = %02" PRIx64
"\n", txt
,
1595 addr
, asi
, r1
& 0xff);
1598 DPRINTF_ASI("%s "TARGET_FMT_lx
" asi 0x%02x = %04" PRIx64
"\n", txt
,
1599 addr
, asi
, r1
& 0xffff);
1602 DPRINTF_ASI("%s "TARGET_FMT_lx
" asi 0x%02x = %08" PRIx64
"\n", txt
,
1603 addr
, asi
, r1
& 0xffffffff);
1606 DPRINTF_ASI("%s "TARGET_FMT_lx
" asi 0x%02x = %016" PRIx64
"\n", txt
,
1613 #ifndef TARGET_SPARC64
1614 #ifndef CONFIG_USER_ONLY
1615 uint64_t helper_ld_asi(target_ulong addr
, int asi
, int size
, int sign
)
1618 #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
1619 uint32_t last_addr
= addr
;
1622 helper_check_align(addr
, size
- 1);
1624 case 2: /* SuperSparc MXCC registers */
1626 case 0x01c00a00: /* MXCC control register */
1628 ret
= env
->mxccregs
[3];
1630 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr
,
1633 case 0x01c00a04: /* MXCC control register */
1635 ret
= env
->mxccregs
[3];
1637 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr
,
1640 case 0x01c00c00: /* Module reset register */
1642 ret
= env
->mxccregs
[5];
1643 // should we do something here?
1645 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr
,
1648 case 0x01c00f00: /* MBus port address register */
1650 ret
= env
->mxccregs
[7];
1652 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr
,
1656 DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr
,
1660 DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
1661 "addr = %08x -> ret = %" PRIx64
","
1662 "addr = %08x\n", asi
, size
, sign
, last_addr
, ret
, addr
);
1667 case 3: /* MMU probe */
1671 mmulev
= (addr
>> 8) & 15;
1675 ret
= mmu_probe(env
, addr
, mmulev
);
1676 DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64
"\n",
1680 case 4: /* read MMU regs */
1682 int reg
= (addr
>> 8) & 0x1f;
1684 ret
= env
->mmuregs
[reg
];
1685 if (reg
== 3) /* Fault status cleared on read */
1686 env
->mmuregs
[3] = 0;
1687 else if (reg
== 0x13) /* Fault status read */
1688 ret
= env
->mmuregs
[3];
1689 else if (reg
== 0x14) /* Fault address read */
1690 ret
= env
->mmuregs
[4];
1691 DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64
"\n", reg
, ret
);
1694 case 5: // Turbosparc ITLB Diagnostic
1695 case 6: // Turbosparc DTLB Diagnostic
1696 case 7: // Turbosparc IOTLB Diagnostic
1698 case 9: /* Supervisor code access */
1701 ret
= ldub_code(addr
);
1704 ret
= lduw_code(addr
);
1708 ret
= ldl_code(addr
);
1711 ret
= ldq_code(addr
);
1715 case 0xa: /* User data access */
1718 ret
= ldub_user(addr
);
1721 ret
= lduw_user(addr
);
1725 ret
= ldl_user(addr
);
1728 ret
= ldq_user(addr
);
1732 case 0xb: /* Supervisor data access */
1735 ret
= ldub_kernel(addr
);
1738 ret
= lduw_kernel(addr
);
1742 ret
= ldl_kernel(addr
);
1745 ret
= ldq_kernel(addr
);
1749 case 0xc: /* I-cache tag */
1750 case 0xd: /* I-cache data */
1751 case 0xe: /* D-cache tag */
1752 case 0xf: /* D-cache data */
1754 case 0x20: /* MMU passthrough */
1757 ret
= ldub_phys(addr
);
1760 ret
= lduw_phys(addr
);
1764 ret
= ldl_phys(addr
);
1767 ret
= ldq_phys(addr
);
1771 case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1774 ret
= ldub_phys((target_phys_addr_t
)addr
1775 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
1778 ret
= lduw_phys((target_phys_addr_t
)addr
1779 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
1783 ret
= ldl_phys((target_phys_addr_t
)addr
1784 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
1787 ret
= ldq_phys((target_phys_addr_t
)addr
1788 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
1792 case 0x30: // Turbosparc secondary cache diagnostic
1793 case 0x31: // Turbosparc RAM snoop
1794 case 0x32: // Turbosparc page table descriptor diagnostic
1795 case 0x39: /* data cache diagnostic register */
1796 case 0x4c: /* SuperSPARC MMU Breakpoint Action register */
1799 case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
1801 int reg
= (addr
>> 8) & 3;
1804 case 0: /* Breakpoint Value (Addr) */
1805 ret
= env
->mmubpregs
[reg
];
1807 case 1: /* Breakpoint Mask */
1808 ret
= env
->mmubpregs
[reg
];
1810 case 2: /* Breakpoint Control */
1811 ret
= env
->mmubpregs
[reg
];
1813 case 3: /* Breakpoint Status */
1814 ret
= env
->mmubpregs
[reg
];
1815 env
->mmubpregs
[reg
] = 0ULL;
1818 DPRINTF_MMU("read breakpoint reg[%d] 0x%016" PRIx64
"\n", reg
,
1822 case 8: /* User code access, XXX */
1824 do_unassigned_access(addr
, 0, 0, asi
, size
);
1834 ret
= (int16_t) ret
;
1837 ret
= (int32_t) ret
;
1844 dump_asi("read ", last_addr
, asi
, size
, ret
);
1849 void helper_st_asi(target_ulong addr
, uint64_t val
, int asi
, int size
)
1851 helper_check_align(addr
, size
- 1);
1853 case 2: /* SuperSparc MXCC registers */
1855 case 0x01c00000: /* MXCC stream data register 0 */
1857 env
->mxccdata
[0] = val
;
1859 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr
,
1862 case 0x01c00008: /* MXCC stream data register 1 */
1864 env
->mxccdata
[1] = val
;
1866 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr
,
1869 case 0x01c00010: /* MXCC stream data register 2 */
1871 env
->mxccdata
[2] = val
;
1873 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr
,
1876 case 0x01c00018: /* MXCC stream data register 3 */
1878 env
->mxccdata
[3] = val
;
1880 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr
,
1883 case 0x01c00100: /* MXCC stream source */
1885 env
->mxccregs
[0] = val
;
1887 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr
,
1889 env
->mxccdata
[0] = ldq_phys((env
->mxccregs
[0] & 0xffffffffULL
) +
1891 env
->mxccdata
[1] = ldq_phys((env
->mxccregs
[0] & 0xffffffffULL
) +
1893 env
->mxccdata
[2] = ldq_phys((env
->mxccregs
[0] & 0xffffffffULL
) +
1895 env
->mxccdata
[3] = ldq_phys((env
->mxccregs
[0] & 0xffffffffULL
) +
1898 case 0x01c00200: /* MXCC stream destination */
1900 env
->mxccregs
[1] = val
;
1902 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr
,
1904 stq_phys((env
->mxccregs
[1] & 0xffffffffULL
) + 0,
1906 stq_phys((env
->mxccregs
[1] & 0xffffffffULL
) + 8,
1908 stq_phys((env
->mxccregs
[1] & 0xffffffffULL
) + 16,
1910 stq_phys((env
->mxccregs
[1] & 0xffffffffULL
) + 24,
1913 case 0x01c00a00: /* MXCC control register */
1915 env
->mxccregs
[3] = val
;
1917 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr
,
1920 case 0x01c00a04: /* MXCC control register */
1922 env
->mxccregs
[3] = (env
->mxccregs
[3] & 0xffffffff00000000ULL
)
1925 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr
,
1928 case 0x01c00e00: /* MXCC error register */
1929 // writing a 1 bit clears the error
1931 env
->mxccregs
[6] &= ~val
;
1933 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr
,
1936 case 0x01c00f00: /* MBus port address register */
1938 env
->mxccregs
[7] = val
;
1940 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr
,
1944 DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr
,
1948 DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64
"\n",
1949 asi
, size
, addr
, val
);
1954 case 3: /* MMU flush */
1958 mmulev
= (addr
>> 8) & 15;
1959 DPRINTF_MMU("mmu flush level %d\n", mmulev
);
1961 case 0: // flush page
1962 tlb_flush_page(env
, addr
& 0xfffff000);
1964 case 1: // flush segment (256k)
1965 case 2: // flush region (16M)
1966 case 3: // flush context (4G)
1967 case 4: // flush entire
1974 dump_mmu(stdout
, fprintf
, env
);
1978 case 4: /* write MMU regs */
1980 int reg
= (addr
>> 8) & 0x1f;
1983 oldreg
= env
->mmuregs
[reg
];
1985 case 0: // Control Register
1986 env
->mmuregs
[reg
] = (env
->mmuregs
[reg
] & 0xff000000) |
1988 // Mappings generated during no-fault mode or MMU
1989 // disabled mode are invalid in normal mode
1990 if ((oldreg
& (MMU_E
| MMU_NF
| env
->def
->mmu_bm
)) !=
1991 (env
->mmuregs
[reg
] & (MMU_E
| MMU_NF
| env
->def
->mmu_bm
)))
1994 case 1: // Context Table Pointer Register
1995 env
->mmuregs
[reg
] = val
& env
->def
->mmu_ctpr_mask
;
1997 case 2: // Context Register
1998 env
->mmuregs
[reg
] = val
& env
->def
->mmu_cxr_mask
;
1999 if (oldreg
!= env
->mmuregs
[reg
]) {
2000 /* we flush when the MMU context changes because
2001 QEMU has no MMU context support */
2005 case 3: // Synchronous Fault Status Register with Clear
2006 case 4: // Synchronous Fault Address Register
2008 case 0x10: // TLB Replacement Control Register
2009 env
->mmuregs
[reg
] = val
& env
->def
->mmu_trcr_mask
;
2011 case 0x13: // Synchronous Fault Status Register with Read and Clear
2012 env
->mmuregs
[3] = val
& env
->def
->mmu_sfsr_mask
;
2014 case 0x14: // Synchronous Fault Address Register
2015 env
->mmuregs
[4] = val
;
2018 env
->mmuregs
[reg
] = val
;
2021 if (oldreg
!= env
->mmuregs
[reg
]) {
2022 DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
2023 reg
, oldreg
, env
->mmuregs
[reg
]);
2026 dump_mmu(stdout
, fprintf
, env
);
2030 case 5: // Turbosparc ITLB Diagnostic
2031 case 6: // Turbosparc DTLB Diagnostic
2032 case 7: // Turbosparc IOTLB Diagnostic
2034 case 0xa: /* User data access */
2037 stb_user(addr
, val
);
2040 stw_user(addr
, val
);
2044 stl_user(addr
, val
);
2047 stq_user(addr
, val
);
2051 case 0xb: /* Supervisor data access */
2054 stb_kernel(addr
, val
);
2057 stw_kernel(addr
, val
);
2061 stl_kernel(addr
, val
);
2064 stq_kernel(addr
, val
);
2068 case 0xc: /* I-cache tag */
2069 case 0xd: /* I-cache data */
2070 case 0xe: /* D-cache tag */
2071 case 0xf: /* D-cache data */
2072 case 0x10: /* I/D-cache flush page */
2073 case 0x11: /* I/D-cache flush segment */
2074 case 0x12: /* I/D-cache flush region */
2075 case 0x13: /* I/D-cache flush context */
2076 case 0x14: /* I/D-cache flush user */
2078 case 0x17: /* Block copy, sta access */
2084 uint32_t src
= val
& ~3, dst
= addr
& ~3, temp
;
2086 for (i
= 0; i
< 32; i
+= 4, src
+= 4, dst
+= 4) {
2087 temp
= ldl_kernel(src
);
2088 stl_kernel(dst
, temp
);
2092 case 0x1f: /* Block fill, stda access */
2095 // fill 32 bytes with val
2097 uint32_t dst
= addr
& 7;
2099 for (i
= 0; i
< 32; i
+= 8, dst
+= 8)
2100 stq_kernel(dst
, val
);
2103 case 0x20: /* MMU passthrough */
2107 stb_phys(addr
, val
);
2110 stw_phys(addr
, val
);
2114 stl_phys(addr
, val
);
2117 stq_phys(addr
, val
);
2122 case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
2126 stb_phys((target_phys_addr_t
)addr
2127 | ((target_phys_addr_t
)(asi
& 0xf) << 32), val
);
2130 stw_phys((target_phys_addr_t
)addr
2131 | ((target_phys_addr_t
)(asi
& 0xf) << 32), val
);
2135 stl_phys((target_phys_addr_t
)addr
2136 | ((target_phys_addr_t
)(asi
& 0xf) << 32), val
);
2139 stq_phys((target_phys_addr_t
)addr
2140 | ((target_phys_addr_t
)(asi
& 0xf) << 32), val
);
2145 case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
2146 case 0x31: // store buffer data, Ross RT620 I-cache flush or
2147 // Turbosparc snoop RAM
2148 case 0x32: // store buffer control or Turbosparc page table
2149 // descriptor diagnostic
2150 case 0x36: /* I-cache flash clear */
2151 case 0x37: /* D-cache flash clear */
2152 case 0x4c: /* breakpoint action */
2154 case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
2156 int reg
= (addr
>> 8) & 3;
2159 case 0: /* Breakpoint Value (Addr) */
2160 env
->mmubpregs
[reg
] = (val
& 0xfffffffffULL
);
2162 case 1: /* Breakpoint Mask */
2163 env
->mmubpregs
[reg
] = (val
& 0xfffffffffULL
);
2165 case 2: /* Breakpoint Control */
2166 env
->mmubpregs
[reg
] = (val
& 0x7fULL
);
2168 case 3: /* Breakpoint Status */
2169 env
->mmubpregs
[reg
] = (val
& 0xfULL
);
2172 DPRINTF_MMU("write breakpoint reg[%d] 0x%016x\n", reg
,
2176 case 8: /* User code access, XXX */
2177 case 9: /* Supervisor code access, XXX */
2179 do_unassigned_access(addr
, 1, 0, asi
, size
);
2183 dump_asi("write", addr
, asi
, size
, val
);
2187 #endif /* CONFIG_USER_ONLY */
2188 #else /* TARGET_SPARC64 */
2190 #ifdef CONFIG_USER_ONLY
2191 uint64_t helper_ld_asi(target_ulong addr
, int asi
, int size
, int sign
)
2194 #if defined(DEBUG_ASI)
2195 target_ulong last_addr
= addr
;
2199 raise_exception(TT_PRIV_ACT
);
2201 helper_check_align(addr
, size
- 1);
2202 addr
= asi_address_mask(env
, asi
, addr
);
2205 case 0x82: // Primary no-fault
2206 case 0x8a: // Primary no-fault LE
2207 if (page_check_range(addr
, size
, PAGE_READ
) == -1) {
2209 dump_asi("read ", last_addr
, asi
, size
, ret
);
2214 case 0x80: // Primary
2215 case 0x88: // Primary LE
2219 ret
= ldub_raw(addr
);
2222 ret
= lduw_raw(addr
);
2225 ret
= ldl_raw(addr
);
2229 ret
= ldq_raw(addr
);
2234 case 0x83: // Secondary no-fault
2235 case 0x8b: // Secondary no-fault LE
2236 if (page_check_range(addr
, size
, PAGE_READ
) == -1) {
2238 dump_asi("read ", last_addr
, asi
, size
, ret
);
2243 case 0x81: // Secondary
2244 case 0x89: // Secondary LE
2251 /* Convert from little endian */
2253 case 0x88: // Primary LE
2254 case 0x89: // Secondary LE
2255 case 0x8a: // Primary no-fault LE
2256 case 0x8b: // Secondary no-fault LE
2274 /* Convert to signed number */
2281 ret
= (int16_t) ret
;
2284 ret
= (int32_t) ret
;
2291 dump_asi("read ", last_addr
, asi
, size
, ret
);
2296 void helper_st_asi(target_ulong addr
, target_ulong val
, int asi
, int size
)
2299 dump_asi("write", addr
, asi
, size
, val
);
2302 raise_exception(TT_PRIV_ACT
);
2304 helper_check_align(addr
, size
- 1);
2305 addr
= asi_address_mask(env
, asi
, addr
);
2307 /* Convert to little endian */
2309 case 0x88: // Primary LE
2310 case 0x89: // Secondary LE
2329 case 0x80: // Primary
2330 case 0x88: // Primary LE
2349 case 0x81: // Secondary
2350 case 0x89: // Secondary LE
2354 case 0x82: // Primary no-fault, RO
2355 case 0x83: // Secondary no-fault, RO
2356 case 0x8a: // Primary no-fault LE, RO
2357 case 0x8b: // Secondary no-fault LE, RO
2359 do_unassigned_access(addr
, 1, 0, 1, size
);
2364 #else /* CONFIG_USER_ONLY */
2366 uint64_t helper_ld_asi(target_ulong addr
, int asi
, int size
, int sign
)
2369 #if defined(DEBUG_ASI)
2370 target_ulong last_addr
= addr
;
2375 if ((asi
< 0x80 && (env
->pstate
& PS_PRIV
) == 0)
2376 || (cpu_has_hypervisor(env
)
2377 && asi
>= 0x30 && asi
< 0x80
2378 && !(env
->hpstate
& HS_PRIV
)))
2379 raise_exception(TT_PRIV_ACT
);
2381 helper_check_align(addr
, size
- 1);
2382 addr
= asi_address_mask(env
, asi
, addr
);
2385 case 0x82: // Primary no-fault
2386 case 0x8a: // Primary no-fault LE
2387 case 0x83: // Secondary no-fault
2388 case 0x8b: // Secondary no-fault LE
2390 /* secondary space access has lowest asi bit equal to 1 */
2391 int access_mmu_idx
= ( asi
& 1 ) ? MMU_KERNEL_IDX
2392 : MMU_KERNEL_SECONDARY_IDX
;
2394 if (cpu_get_phys_page_nofault(env
, addr
, access_mmu_idx
) == -1ULL) {
2396 dump_asi("read ", last_addr
, asi
, size
, ret
);
2402 case 0x10: // As if user primary
2403 case 0x11: // As if user secondary
2404 case 0x18: // As if user primary LE
2405 case 0x19: // As if user secondary LE
2406 case 0x80: // Primary
2407 case 0x81: // Secondary
2408 case 0x88: // Primary LE
2409 case 0x89: // Secondary LE
2410 case 0xe2: // UA2007 Primary block init
2411 case 0xe3: // UA2007 Secondary block init
2412 if ((asi
& 0x80) && (env
->pstate
& PS_PRIV
)) {
2413 if (cpu_hypervisor_mode(env
)) {
2416 ret
= ldub_hypv(addr
);
2419 ret
= lduw_hypv(addr
);
2422 ret
= ldl_hypv(addr
);
2426 ret
= ldq_hypv(addr
);
2430 /* secondary space access has lowest asi bit equal to 1 */
2434 ret
= ldub_kernel_secondary(addr
);
2437 ret
= lduw_kernel_secondary(addr
);
2440 ret
= ldl_kernel_secondary(addr
);
2444 ret
= ldq_kernel_secondary(addr
);
2450 ret
= ldub_kernel(addr
);
2453 ret
= lduw_kernel(addr
);
2456 ret
= ldl_kernel(addr
);
2460 ret
= ldq_kernel(addr
);
2466 /* secondary space access has lowest asi bit equal to 1 */
2470 ret
= ldub_user_secondary(addr
);
2473 ret
= lduw_user_secondary(addr
);
2476 ret
= ldl_user_secondary(addr
);
2480 ret
= ldq_user_secondary(addr
);
2486 ret
= ldub_user(addr
);
2489 ret
= lduw_user(addr
);
2492 ret
= ldl_user(addr
);
2496 ret
= ldq_user(addr
);
2502 case 0x14: // Bypass
2503 case 0x15: // Bypass, non-cacheable
2504 case 0x1c: // Bypass LE
2505 case 0x1d: // Bypass, non-cacheable LE
2509 ret
= ldub_phys(addr
);
2512 ret
= lduw_phys(addr
);
2515 ret
= ldl_phys(addr
);
2519 ret
= ldq_phys(addr
);
2524 case 0x24: // Nucleus quad LDD 128 bit atomic
2525 case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2526 // Only ldda allowed
2527 raise_exception(TT_ILL_INSN
);
2529 case 0x04: // Nucleus
2530 case 0x0c: // Nucleus Little Endian (LE)
2534 ret
= ldub_nucleus(addr
);
2537 ret
= lduw_nucleus(addr
);
2540 ret
= ldl_nucleus(addr
);
2544 ret
= ldq_nucleus(addr
);
2549 case 0x4a: // UPA config
2555 case 0x50: // I-MMU regs
2557 int reg
= (addr
>> 3) & 0xf;
2560 // I-TSB Tag Target register
2561 ret
= ultrasparc_tag_target(env
->immu
.tag_access
);
2563 ret
= env
->immuregs
[reg
];
2568 case 0x51: // I-MMU 8k TSB pointer
2570 // env->immuregs[5] holds I-MMU TSB register value
2571 // env->immuregs[6] holds I-MMU Tag Access register value
2572 ret
= ultrasparc_tsb_pointer(env
->immu
.tsb
, env
->immu
.tag_access
,
2576 case 0x52: // I-MMU 64k TSB pointer
2578 // env->immuregs[5] holds I-MMU TSB register value
2579 // env->immuregs[6] holds I-MMU Tag Access register value
2580 ret
= ultrasparc_tsb_pointer(env
->immu
.tsb
, env
->immu
.tag_access
,
2584 case 0x55: // I-MMU data access
2586 int reg
= (addr
>> 3) & 0x3f;
2588 ret
= env
->itlb
[reg
].tte
;
2591 case 0x56: // I-MMU tag read
2593 int reg
= (addr
>> 3) & 0x3f;
2595 ret
= env
->itlb
[reg
].tag
;
2598 case 0x58: // D-MMU regs
2600 int reg
= (addr
>> 3) & 0xf;
2603 // D-TSB Tag Target register
2604 ret
= ultrasparc_tag_target(env
->dmmu
.tag_access
);
2606 ret
= env
->dmmuregs
[reg
];
2610 case 0x59: // D-MMU 8k TSB pointer
2612 // env->dmmuregs[5] holds D-MMU TSB register value
2613 // env->dmmuregs[6] holds D-MMU Tag Access register value
2614 ret
= ultrasparc_tsb_pointer(env
->dmmu
.tsb
, env
->dmmu
.tag_access
,
2618 case 0x5a: // D-MMU 64k TSB pointer
2620 // env->dmmuregs[5] holds D-MMU TSB register value
2621 // env->dmmuregs[6] holds D-MMU Tag Access register value
2622 ret
= ultrasparc_tsb_pointer(env
->dmmu
.tsb
, env
->dmmu
.tag_access
,
2626 case 0x5d: // D-MMU data access
2628 int reg
= (addr
>> 3) & 0x3f;
2630 ret
= env
->dtlb
[reg
].tte
;
2633 case 0x5e: // D-MMU tag read
2635 int reg
= (addr
>> 3) & 0x3f;
2637 ret
= env
->dtlb
[reg
].tag
;
2640 case 0x46: // D-cache data
2641 case 0x47: // D-cache tag access
2642 case 0x4b: // E-cache error enable
2643 case 0x4c: // E-cache asynchronous fault status
2644 case 0x4d: // E-cache asynchronous fault address
2645 case 0x4e: // E-cache tag data
2646 case 0x66: // I-cache instruction access
2647 case 0x67: // I-cache tag access
2648 case 0x6e: // I-cache predecode
2649 case 0x6f: // I-cache LRU etc.
2650 case 0x76: // E-cache tag
2651 case 0x7e: // E-cache tag
2653 case 0x5b: // D-MMU data pointer
2654 case 0x48: // Interrupt dispatch, RO
2655 case 0x49: // Interrupt data receive
2656 case 0x7f: // Incoming interrupt vector, RO
2659 case 0x54: // I-MMU data in, WO
2660 case 0x57: // I-MMU demap, WO
2661 case 0x5c: // D-MMU data in, WO
2662 case 0x5f: // D-MMU demap, WO
2663 case 0x77: // Interrupt vector, WO
2665 do_unassigned_access(addr
, 0, 0, 1, size
);
2670 /* Convert from little endian */
2672 case 0x0c: // Nucleus Little Endian (LE)
2673 case 0x18: // As if user primary LE
2674 case 0x19: // As if user secondary LE
2675 case 0x1c: // Bypass LE
2676 case 0x1d: // Bypass, non-cacheable LE
2677 case 0x88: // Primary LE
2678 case 0x89: // Secondary LE
2679 case 0x8a: // Primary no-fault LE
2680 case 0x8b: // Secondary no-fault LE
2698 /* Convert to signed number */
2705 ret
= (int16_t) ret
;
2708 ret
= (int32_t) ret
;
2715 dump_asi("read ", last_addr
, asi
, size
, ret
);
2720 void helper_st_asi(target_ulong addr
, target_ulong val
, int asi
, int size
)
2723 dump_asi("write", addr
, asi
, size
, val
);
2728 if ((asi
< 0x80 && (env
->pstate
& PS_PRIV
) == 0)
2729 || (cpu_has_hypervisor(env
)
2730 && asi
>= 0x30 && asi
< 0x80
2731 && !(env
->hpstate
& HS_PRIV
)))
2732 raise_exception(TT_PRIV_ACT
);
2734 helper_check_align(addr
, size
- 1);
2735 addr
= asi_address_mask(env
, asi
, addr
);
2737 /* Convert to little endian */
2739 case 0x0c: // Nucleus Little Endian (LE)
2740 case 0x18: // As if user primary LE
2741 case 0x19: // As if user secondary LE
2742 case 0x1c: // Bypass LE
2743 case 0x1d: // Bypass, non-cacheable LE
2744 case 0x88: // Primary LE
2745 case 0x89: // Secondary LE
2764 case 0x10: // As if user primary
2765 case 0x11: // As if user secondary
2766 case 0x18: // As if user primary LE
2767 case 0x19: // As if user secondary LE
2768 case 0x80: // Primary
2769 case 0x81: // Secondary
2770 case 0x88: // Primary LE
2771 case 0x89: // Secondary LE
2772 case 0xe2: // UA2007 Primary block init
2773 case 0xe3: // UA2007 Secondary block init
2774 if ((asi
& 0x80) && (env
->pstate
& PS_PRIV
)) {
2775 if (cpu_hypervisor_mode(env
)) {
2778 stb_hypv(addr
, val
);
2781 stw_hypv(addr
, val
);
2784 stl_hypv(addr
, val
);
2788 stq_hypv(addr
, val
);
2792 /* secondary space access has lowest asi bit equal to 1 */
2796 stb_kernel_secondary(addr
, val
);
2799 stw_kernel_secondary(addr
, val
);
2802 stl_kernel_secondary(addr
, val
);
2806 stq_kernel_secondary(addr
, val
);
2812 stb_kernel(addr
, val
);
2815 stw_kernel(addr
, val
);
2818 stl_kernel(addr
, val
);
2822 stq_kernel(addr
, val
);
2828 /* secondary space access has lowest asi bit equal to 1 */
2832 stb_user_secondary(addr
, val
);
2835 stw_user_secondary(addr
, val
);
2838 stl_user_secondary(addr
, val
);
2842 stq_user_secondary(addr
, val
);
2848 stb_user(addr
, val
);
2851 stw_user(addr
, val
);
2854 stl_user(addr
, val
);
2858 stq_user(addr
, val
);
2864 case 0x14: // Bypass
2865 case 0x15: // Bypass, non-cacheable
2866 case 0x1c: // Bypass LE
2867 case 0x1d: // Bypass, non-cacheable LE
2871 stb_phys(addr
, val
);
2874 stw_phys(addr
, val
);
2877 stl_phys(addr
, val
);
2881 stq_phys(addr
, val
);
2886 case 0x24: // Nucleus quad LDD 128 bit atomic
2887 case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2888 // Only ldda allowed
2889 raise_exception(TT_ILL_INSN
);
2891 case 0x04: // Nucleus
2892 case 0x0c: // Nucleus Little Endian (LE)
2896 stb_nucleus(addr
, val
);
2899 stw_nucleus(addr
, val
);
2902 stl_nucleus(addr
, val
);
2906 stq_nucleus(addr
, val
);
2912 case 0x4a: // UPA config
2920 env
->lsu
= val
& (DMMU_E
| IMMU_E
);
2921 // Mappings generated during D/I MMU disabled mode are
2922 // invalid in normal mode
2923 if (oldreg
!= env
->lsu
) {
2924 DPRINTF_MMU("LSU change: 0x%" PRIx64
" -> 0x%" PRIx64
"\n",
2927 dump_mmu(stdout
, fprintf
, env1
);
2933 case 0x50: // I-MMU regs
2935 int reg
= (addr
>> 3) & 0xf;
2938 oldreg
= env
->immuregs
[reg
];
2942 case 1: // Not in I-MMU
2947 val
= 0; // Clear SFSR
2948 env
->immu
.sfsr
= val
;
2952 case 5: // TSB access
2953 DPRINTF_MMU("immu TSB write: 0x%016" PRIx64
" -> 0x%016"
2954 PRIx64
"\n", env
->immu
.tsb
, val
);
2955 env
->immu
.tsb
= val
;
2957 case 6: // Tag access
2958 env
->immu
.tag_access
= val
;
2967 if (oldreg
!= env
->immuregs
[reg
]) {
2968 DPRINTF_MMU("immu change reg[%d]: 0x%016" PRIx64
" -> 0x%016"
2969 PRIx64
"\n", reg
, oldreg
, env
->immuregs
[reg
]);
2972 dump_mmu(stdout
, fprintf
, env
);
2976 case 0x54: // I-MMU data in
2977 replace_tlb_1bit_lru(env
->itlb
, env
->immu
.tag_access
, val
, "immu", env
);
2979 case 0x55: // I-MMU data access
2983 unsigned int i
= (addr
>> 3) & 0x3f;
2985 replace_tlb_entry(&env
->itlb
[i
], env
->immu
.tag_access
, val
, env
);
2988 DPRINTF_MMU("immu data access replaced entry [%i]\n", i
);
2989 dump_mmu(stdout
, fprintf
, env
);
2993 case 0x57: // I-MMU demap
2994 demap_tlb(env
->itlb
, addr
, "immu", env
);
2996 case 0x58: // D-MMU regs
2998 int reg
= (addr
>> 3) & 0xf;
3001 oldreg
= env
->dmmuregs
[reg
];
3007 if ((val
& 1) == 0) {
3008 val
= 0; // Clear SFSR, Fault address
3011 env
->dmmu
.sfsr
= val
;
3013 case 1: // Primary context
3014 env
->dmmu
.mmu_primary_context
= val
;
3015 /* can be optimized to only flush MMU_USER_IDX
3016 and MMU_KERNEL_IDX entries */
3019 case 2: // Secondary context
3020 env
->dmmu
.mmu_secondary_context
= val
;
3021 /* can be optimized to only flush MMU_USER_SECONDARY_IDX
3022 and MMU_KERNEL_SECONDARY_IDX entries */
3025 case 5: // TSB access
3026 DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64
" -> 0x%016"
3027 PRIx64
"\n", env
->dmmu
.tsb
, val
);
3028 env
->dmmu
.tsb
= val
;
3030 case 6: // Tag access
3031 env
->dmmu
.tag_access
= val
;
3033 case 7: // Virtual Watchpoint
3034 case 8: // Physical Watchpoint
3036 env
->dmmuregs
[reg
] = val
;
3040 if (oldreg
!= env
->dmmuregs
[reg
]) {
3041 DPRINTF_MMU("dmmu change reg[%d]: 0x%016" PRIx64
" -> 0x%016"
3042 PRIx64
"\n", reg
, oldreg
, env
->dmmuregs
[reg
]);
3045 dump_mmu(stdout
, fprintf
, env
);
3049 case 0x5c: // D-MMU data in
3050 replace_tlb_1bit_lru(env
->dtlb
, env
->dmmu
.tag_access
, val
, "dmmu", env
);
3052 case 0x5d: // D-MMU data access
3054 unsigned int i
= (addr
>> 3) & 0x3f;
3056 replace_tlb_entry(&env
->dtlb
[i
], env
->dmmu
.tag_access
, val
, env
);
3059 DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i
);
3060 dump_mmu(stdout
, fprintf
, env
);
3064 case 0x5f: // D-MMU demap
3065 demap_tlb(env
->dtlb
, addr
, "dmmu", env
);
3067 case 0x49: // Interrupt data receive
3070 case 0x46: // D-cache data
3071 case 0x47: // D-cache tag access
3072 case 0x4b: // E-cache error enable
3073 case 0x4c: // E-cache asynchronous fault status
3074 case 0x4d: // E-cache asynchronous fault address
3075 case 0x4e: // E-cache tag data
3076 case 0x66: // I-cache instruction access
3077 case 0x67: // I-cache tag access
3078 case 0x6e: // I-cache predecode
3079 case 0x6f: // I-cache LRU etc.
3080 case 0x76: // E-cache tag
3081 case 0x7e: // E-cache tag
3083 case 0x51: // I-MMU 8k TSB pointer, RO
3084 case 0x52: // I-MMU 64k TSB pointer, RO
3085 case 0x56: // I-MMU tag read, RO
3086 case 0x59: // D-MMU 8k TSB pointer, RO
3087 case 0x5a: // D-MMU 64k TSB pointer, RO
3088 case 0x5b: // D-MMU data pointer, RO
3089 case 0x5e: // D-MMU tag read, RO
3090 case 0x48: // Interrupt dispatch, RO
3091 case 0x7f: // Incoming interrupt vector, RO
3092 case 0x82: // Primary no-fault, RO
3093 case 0x83: // Secondary no-fault, RO
3094 case 0x8a: // Primary no-fault LE, RO
3095 case 0x8b: // Secondary no-fault LE, RO
3097 do_unassigned_access(addr
, 1, 0, 1, size
);
3101 #endif /* CONFIG_USER_ONLY */
3103 void helper_ldda_asi(target_ulong addr
, int asi
, int rd
)
3105 if ((asi
< 0x80 && (env
->pstate
& PS_PRIV
) == 0)
3106 || (cpu_has_hypervisor(env
)
3107 && asi
>= 0x30 && asi
< 0x80
3108 && !(env
->hpstate
& HS_PRIV
)))
3109 raise_exception(TT_PRIV_ACT
);
3111 addr
= asi_address_mask(env
, asi
, addr
);
3114 #if !defined(CONFIG_USER_ONLY)
3115 case 0x24: // Nucleus quad LDD 128 bit atomic
3116 case 0x2c: // Nucleus quad LDD 128 bit atomic LE
3117 helper_check_align(addr
, 0xf);
3119 env
->gregs
[1] = ldq_nucleus(addr
+ 8);
3121 bswap64s(&env
->gregs
[1]);
3122 } else if (rd
< 8) {
3123 env
->gregs
[rd
] = ldq_nucleus(addr
);
3124 env
->gregs
[rd
+ 1] = ldq_nucleus(addr
+ 8);
3126 bswap64s(&env
->gregs
[rd
]);
3127 bswap64s(&env
->gregs
[rd
+ 1]);
3130 env
->regwptr
[rd
] = ldq_nucleus(addr
);
3131 env
->regwptr
[rd
+ 1] = ldq_nucleus(addr
+ 8);
3133 bswap64s(&env
->regwptr
[rd
]);
3134 bswap64s(&env
->regwptr
[rd
+ 1]);
3140 helper_check_align(addr
, 0x3);
3142 env
->gregs
[1] = helper_ld_asi(addr
+ 4, asi
, 4, 0);
3144 env
->gregs
[rd
] = helper_ld_asi(addr
, asi
, 4, 0);
3145 env
->gregs
[rd
+ 1] = helper_ld_asi(addr
+ 4, asi
, 4, 0);
3147 env
->regwptr
[rd
] = helper_ld_asi(addr
, asi
, 4, 0);
3148 env
->regwptr
[rd
+ 1] = helper_ld_asi(addr
+ 4, asi
, 4, 0);
3154 void helper_ldf_asi(target_ulong addr
, int asi
, int size
, int rd
)
3159 helper_check_align(addr
, 3);
3160 addr
= asi_address_mask(env
, asi
, addr
);
3163 case 0xf0: // Block load primary
3164 case 0xf1: // Block load secondary
3165 case 0xf8: // Block load primary LE
3166 case 0xf9: // Block load secondary LE
3168 raise_exception(TT_ILL_INSN
);
3171 helper_check_align(addr
, 0x3f);
3172 for (i
= 0; i
< 16; i
++) {
3173 *(uint32_t *)&env
->fpr
[rd
++] = helper_ld_asi(addr
, asi
& 0x8f, 4,
3179 case 0x70: // Block load primary, user privilege
3180 case 0x71: // Block load secondary, user privilege
3182 raise_exception(TT_ILL_INSN
);
3185 helper_check_align(addr
, 0x3f);
3186 for (i
= 0; i
< 16; i
++) {
3187 *(uint32_t *)&env
->fpr
[rd
++] = helper_ld_asi(addr
, asi
& 0x1f, 4,
3197 val
= helper_ld_asi(addr
, asi
, size
, 0);
3201 *((uint32_t *)&env
->fpr
[rd
]) = val
;
3204 *((int64_t *)&DT0
) = val
;
3212 void helper_stf_asi(target_ulong addr
, int asi
, int size
, int rd
)
3215 target_ulong val
= 0;
3217 helper_check_align(addr
, 3);
3218 addr
= asi_address_mask(env
, asi
, addr
);
3221 case 0xe0: // UA2007 Block commit store primary (cache flush)
3222 case 0xe1: // UA2007 Block commit store secondary (cache flush)
3223 case 0xf0: // Block store primary
3224 case 0xf1: // Block store secondary
3225 case 0xf8: // Block store primary LE
3226 case 0xf9: // Block store secondary LE
3228 raise_exception(TT_ILL_INSN
);
3231 helper_check_align(addr
, 0x3f);
3232 for (i
= 0; i
< 16; i
++) {
3233 val
= *(uint32_t *)&env
->fpr
[rd
++];
3234 helper_st_asi(addr
, val
, asi
& 0x8f, 4);
3239 case 0x70: // Block store primary, user privilege
3240 case 0x71: // Block store secondary, user privilege
3242 raise_exception(TT_ILL_INSN
);
3245 helper_check_align(addr
, 0x3f);
3246 for (i
= 0; i
< 16; i
++) {
3247 val
= *(uint32_t *)&env
->fpr
[rd
++];
3248 helper_st_asi(addr
, val
, asi
& 0x1f, 4);
3260 val
= *((uint32_t *)&env
->fpr
[rd
]);
3263 val
= *((int64_t *)&DT0
);
3269 helper_st_asi(addr
, val
, asi
, size
);
3272 target_ulong
helper_cas_asi(target_ulong addr
, target_ulong val1
,
3273 target_ulong val2
, uint32_t asi
)
3277 val2
&= 0xffffffffUL
;
3278 ret
= helper_ld_asi(addr
, asi
, 4, 0);
3279 ret
&= 0xffffffffUL
;
3281 helper_st_asi(addr
, val1
& 0xffffffffUL
, asi
, 4);
3285 target_ulong
helper_casx_asi(target_ulong addr
, target_ulong val1
,
3286 target_ulong val2
, uint32_t asi
)
3290 ret
= helper_ld_asi(addr
, asi
, 8, 0);
3292 helper_st_asi(addr
, val1
, asi
, 8);
3295 #endif /* TARGET_SPARC64 */
3297 #ifndef TARGET_SPARC64
3298 void helper_rett(void)
3302 if (env
->psret
== 1)
3303 raise_exception(TT_ILL_INSN
);
3306 cwp
= cwp_inc(env
->cwp
+ 1) ;
3307 if (env
->wim
& (1 << cwp
)) {
3308 raise_exception(TT_WIN_UNF
);
3311 env
->psrs
= env
->psrps
;
3315 static target_ulong
helper_udiv_common(target_ulong a
, target_ulong b
, int cc
)
3321 x0
= (a
& 0xffffffff) | ((int64_t) (env
->y
) << 32);
3322 x1
= (b
& 0xffffffff);
3325 raise_exception(TT_DIV_ZERO
);
3329 if (x0
> 0xffffffff) {
3336 env
->cc_src2
= overflow
;
3337 env
->cc_op
= CC_OP_DIV
;
3342 target_ulong
helper_udiv(target_ulong a
, target_ulong b
)
3344 return helper_udiv_common(a
, b
, 0);
3347 target_ulong
helper_udiv_cc(target_ulong a
, target_ulong b
)
3349 return helper_udiv_common(a
, b
, 1);
3352 static target_ulong
helper_sdiv_common(target_ulong a
, target_ulong b
, int cc
)
3358 x0
= (a
& 0xffffffff) | ((int64_t) (env
->y
) << 32);
3359 x1
= (b
& 0xffffffff);
3362 raise_exception(TT_DIV_ZERO
);
3366 if ((int32_t) x0
!= x0
) {
3367 x0
= x0
< 0 ? 0x80000000: 0x7fffffff;
3373 env
->cc_src2
= overflow
;
3374 env
->cc_op
= CC_OP_DIV
;
3379 target_ulong
helper_sdiv(target_ulong a
, target_ulong b
)
3381 return helper_sdiv_common(a
, b
, 0);
3384 target_ulong
helper_sdiv_cc(target_ulong a
, target_ulong b
)
3386 return helper_sdiv_common(a
, b
, 1);
3389 void helper_stdf(target_ulong addr
, int mem_idx
)
3391 helper_check_align(addr
, 7);
3392 #if !defined(CONFIG_USER_ONLY)
3395 stfq_user(addr
, DT0
);
3397 case MMU_KERNEL_IDX
:
3398 stfq_kernel(addr
, DT0
);
3400 #ifdef TARGET_SPARC64
3402 stfq_hypv(addr
, DT0
);
3406 DPRINTF_MMU("helper_stdf: need to check MMU idx %d\n", mem_idx
);
3410 stfq_raw(address_mask(env
, addr
), DT0
);
3414 void helper_lddf(target_ulong addr
, int mem_idx
)
3416 helper_check_align(addr
, 7);
3417 #if !defined(CONFIG_USER_ONLY)
3420 DT0
= ldfq_user(addr
);
3422 case MMU_KERNEL_IDX
:
3423 DT0
= ldfq_kernel(addr
);
3425 #ifdef TARGET_SPARC64
3427 DT0
= ldfq_hypv(addr
);
3431 DPRINTF_MMU("helper_lddf: need to check MMU idx %d\n", mem_idx
);
3435 DT0
= ldfq_raw(address_mask(env
, addr
));
3439 void helper_ldqf(target_ulong addr
, int mem_idx
)
3441 // XXX add 128 bit load
3444 helper_check_align(addr
, 7);
3445 #if !defined(CONFIG_USER_ONLY)
3448 u
.ll
.upper
= ldq_user(addr
);
3449 u
.ll
.lower
= ldq_user(addr
+ 8);
3452 case MMU_KERNEL_IDX
:
3453 u
.ll
.upper
= ldq_kernel(addr
);
3454 u
.ll
.lower
= ldq_kernel(addr
+ 8);
3457 #ifdef TARGET_SPARC64
3459 u
.ll
.upper
= ldq_hypv(addr
);
3460 u
.ll
.lower
= ldq_hypv(addr
+ 8);
3465 DPRINTF_MMU("helper_ldqf: need to check MMU idx %d\n", mem_idx
);
3469 u
.ll
.upper
= ldq_raw(address_mask(env
, addr
));
3470 u
.ll
.lower
= ldq_raw(address_mask(env
, addr
+ 8));
3475 void helper_stqf(target_ulong addr
, int mem_idx
)
3477 // XXX add 128 bit store
3480 helper_check_align(addr
, 7);
3481 #if !defined(CONFIG_USER_ONLY)
3485 stq_user(addr
, u
.ll
.upper
);
3486 stq_user(addr
+ 8, u
.ll
.lower
);
3488 case MMU_KERNEL_IDX
:
3490 stq_kernel(addr
, u
.ll
.upper
);
3491 stq_kernel(addr
+ 8, u
.ll
.lower
);
3493 #ifdef TARGET_SPARC64
3496 stq_hypv(addr
, u
.ll
.upper
);
3497 stq_hypv(addr
+ 8, u
.ll
.lower
);
3501 DPRINTF_MMU("helper_stqf: need to check MMU idx %d\n", mem_idx
);
3506 stq_raw(address_mask(env
, addr
), u
.ll
.upper
);
3507 stq_raw(address_mask(env
, addr
+ 8), u
.ll
.lower
);
3511 static inline void set_fsr(void)
3515 switch (env
->fsr
& FSR_RD_MASK
) {
3516 case FSR_RD_NEAREST
:
3517 rnd_mode
= float_round_nearest_even
;
3521 rnd_mode
= float_round_to_zero
;
3524 rnd_mode
= float_round_up
;
3527 rnd_mode
= float_round_down
;
3530 set_float_rounding_mode(rnd_mode
, &env
->fp_status
);
3533 void helper_ldfsr(uint32_t new_fsr
)
3535 env
->fsr
= (new_fsr
& FSR_LDFSR_MASK
) | (env
->fsr
& FSR_LDFSR_OLDMASK
);
3539 #ifdef TARGET_SPARC64
3540 void helper_ldxfsr(uint64_t new_fsr
)
3542 env
->fsr
= (new_fsr
& FSR_LDXFSR_MASK
) | (env
->fsr
& FSR_LDXFSR_OLDMASK
);
3547 void helper_debug(void)
3549 env
->exception_index
= EXCP_DEBUG
;
3553 #ifndef TARGET_SPARC64
3554 /* XXX: use another pointer for %iN registers to avoid slow wrapping
3556 void helper_save(void)
3560 cwp
= cwp_dec(env
->cwp
- 1);
3561 if (env
->wim
& (1 << cwp
)) {
3562 raise_exception(TT_WIN_OVF
);
3567 void helper_restore(void)
3571 cwp
= cwp_inc(env
->cwp
+ 1);
3572 if (env
->wim
& (1 << cwp
)) {
3573 raise_exception(TT_WIN_UNF
);
3578 void helper_wrpsr(target_ulong new_psr
)
3580 if ((new_psr
& PSR_CWP
) >= env
->nwindows
) {
3581 raise_exception(TT_ILL_INSN
);
3583 cpu_put_psr(env
, new_psr
);
3587 target_ulong
helper_rdpsr(void)
3593 /* XXX: use another pointer for %iN registers to avoid slow wrapping
3595 void helper_save(void)
3599 cwp
= cwp_dec(env
->cwp
- 1);
3600 if (env
->cansave
== 0) {
3601 raise_exception(TT_SPILL
| (env
->otherwin
!= 0 ?
3602 (TT_WOTHER
| ((env
->wstate
& 0x38) >> 1)):
3603 ((env
->wstate
& 0x7) << 2)));
3605 if (env
->cleanwin
- env
->canrestore
== 0) {
3606 // XXX Clean windows without trap
3607 raise_exception(TT_CLRWIN
);
3616 void helper_restore(void)
3620 cwp
= cwp_inc(env
->cwp
+ 1);
3621 if (env
->canrestore
== 0) {
3622 raise_exception(TT_FILL
| (env
->otherwin
!= 0 ?
3623 (TT_WOTHER
| ((env
->wstate
& 0x38) >> 1)):
3624 ((env
->wstate
& 0x7) << 2)));
3632 void helper_flushw(void)
3634 if (env
->cansave
!= env
->nwindows
- 2) {
3635 raise_exception(TT_SPILL
| (env
->otherwin
!= 0 ?
3636 (TT_WOTHER
| ((env
->wstate
& 0x38) >> 1)):
3637 ((env
->wstate
& 0x7) << 2)));
3641 void helper_saved(void)
3644 if (env
->otherwin
== 0)
3650 void helper_restored(void)
3653 if (env
->cleanwin
< env
->nwindows
- 1)
3655 if (env
->otherwin
== 0)
3661 static target_ulong
get_ccr(void)
3667 return ((env
->xcc
>> 20) << 4) | ((psr
& PSR_ICC
) >> 20);
3670 target_ulong
cpu_get_ccr(CPUState
*env1
)
3672 CPUState
*saved_env
;
3682 static void put_ccr(target_ulong val
)
3684 target_ulong tmp
= val
;
3686 env
->xcc
= (tmp
>> 4) << 20;
3687 env
->psr
= (tmp
& 0xf) << 20;
3688 CC_OP
= CC_OP_FLAGS
;
3691 void cpu_put_ccr(CPUState
*env1
, target_ulong val
)
3693 CPUState
*saved_env
;
3701 static target_ulong
get_cwp64(void)
3703 return env
->nwindows
- 1 - env
->cwp
;
3706 target_ulong
cpu_get_cwp64(CPUState
*env1
)
3708 CPUState
*saved_env
;
3718 static void put_cwp64(int cwp
)
3720 if (unlikely(cwp
>= env
->nwindows
|| cwp
< 0)) {
3721 cwp
%= env
->nwindows
;
3723 set_cwp(env
->nwindows
- 1 - cwp
);
3726 void cpu_put_cwp64(CPUState
*env1
, int cwp
)
3728 CPUState
*saved_env
;
3736 target_ulong
helper_rdccr(void)
3741 void helper_wrccr(target_ulong new_ccr
)
3746 // CWP handling is reversed in V9, but we still use the V8 register
3748 target_ulong
helper_rdcwp(void)
3753 void helper_wrcwp(target_ulong new_cwp
)
3758 // This function uses non-native bit order
3759 #define GET_FIELD(X, FROM, TO) \
3760 ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
3762 // This function uses the order in the manuals, i.e. bit 0 is 2^0
3763 #define GET_FIELD_SP(X, FROM, TO) \
3764 GET_FIELD(X, 63 - (TO), 63 - (FROM))
3766 target_ulong
helper_array8(target_ulong pixel_addr
, target_ulong cubesize
)
3768 return (GET_FIELD_SP(pixel_addr
, 60, 63) << (17 + 2 * cubesize
)) |
3769 (GET_FIELD_SP(pixel_addr
, 39, 39 + cubesize
- 1) << (17 + cubesize
)) |
3770 (GET_FIELD_SP(pixel_addr
, 17 + cubesize
- 1, 17) << 17) |
3771 (GET_FIELD_SP(pixel_addr
, 56, 59) << 13) |
3772 (GET_FIELD_SP(pixel_addr
, 35, 38) << 9) |
3773 (GET_FIELD_SP(pixel_addr
, 13, 16) << 5) |
3774 (((pixel_addr
>> 55) & 1) << 4) |
3775 (GET_FIELD_SP(pixel_addr
, 33, 34) << 2) |
3776 GET_FIELD_SP(pixel_addr
, 11, 12);
3779 target_ulong
helper_alignaddr(target_ulong addr
, target_ulong offset
)
3783 tmp
= addr
+ offset
;
3785 env
->gsr
|= tmp
& 7ULL;
3789 target_ulong
helper_popc(target_ulong val
)
3791 return ctpop64(val
);
3794 static inline uint64_t *get_gregset(uint32_t pstate
)
3798 DPRINTF_PSTATE("ERROR in get_gregset: active pstate bits=%x%s%s%s\n",
3800 (pstate
& PS_IG
) ? " IG" : "",
3801 (pstate
& PS_MG
) ? " MG" : "",
3802 (pstate
& PS_AG
) ? " AG" : "");
3803 /* pass through to normal set of global registers */
3815 static inline void change_pstate(uint32_t new_pstate
)
3817 uint32_t pstate_regs
, new_pstate_regs
;
3818 uint64_t *src
, *dst
;
3820 if (env
->def
->features
& CPU_FEATURE_GL
) {
3821 // PS_AG is not implemented in this case
3822 new_pstate
&= ~PS_AG
;
3825 pstate_regs
= env
->pstate
& 0xc01;
3826 new_pstate_regs
= new_pstate
& 0xc01;
3828 if (new_pstate_regs
!= pstate_regs
) {
3829 DPRINTF_PSTATE("change_pstate: switching regs old=%x new=%x\n",
3830 pstate_regs
, new_pstate_regs
);
3831 // Switch global register bank
3832 src
= get_gregset(new_pstate_regs
);
3833 dst
= get_gregset(pstate_regs
);
3834 memcpy32(dst
, env
->gregs
);
3835 memcpy32(env
->gregs
, src
);
3838 DPRINTF_PSTATE("change_pstate: regs new=%x (unchanged)\n",
3841 env
->pstate
= new_pstate
;
3844 void helper_wrpstate(target_ulong new_state
)
3846 change_pstate(new_state
& 0xf3f);
3848 #if !defined(CONFIG_USER_ONLY)
3849 if (cpu_interrupts_enabled(env
)) {
3850 cpu_check_irqs(env
);
3855 void helper_wrpil(target_ulong new_pil
)
3857 #if !defined(CONFIG_USER_ONLY)
3858 DPRINTF_PSTATE("helper_wrpil old=%x new=%x\n",
3859 env
->psrpil
, (uint32_t)new_pil
);
3861 env
->psrpil
= new_pil
;
3863 if (cpu_interrupts_enabled(env
)) {
3864 cpu_check_irqs(env
);
3869 void helper_done(void)
3871 trap_state
* tsptr
= cpu_tsptr(env
);
3873 env
->pc
= tsptr
->tnpc
;
3874 env
->npc
= tsptr
->tnpc
+ 4;
3875 put_ccr(tsptr
->tstate
>> 32);
3876 env
->asi
= (tsptr
->tstate
>> 24) & 0xff;
3877 change_pstate((tsptr
->tstate
>> 8) & 0xf3f);
3878 put_cwp64(tsptr
->tstate
& 0xff);
3881 DPRINTF_PSTATE("... helper_done tl=%d\n", env
->tl
);
3883 #if !defined(CONFIG_USER_ONLY)
3884 if (cpu_interrupts_enabled(env
)) {
3885 cpu_check_irqs(env
);
3890 void helper_retry(void)
3892 trap_state
* tsptr
= cpu_tsptr(env
);
3894 env
->pc
= tsptr
->tpc
;
3895 env
->npc
= tsptr
->tnpc
;
3896 put_ccr(tsptr
->tstate
>> 32);
3897 env
->asi
= (tsptr
->tstate
>> 24) & 0xff;
3898 change_pstate((tsptr
->tstate
>> 8) & 0xf3f);
3899 put_cwp64(tsptr
->tstate
& 0xff);
3902 DPRINTF_PSTATE("... helper_retry tl=%d\n", env
->tl
);
3904 #if !defined(CONFIG_USER_ONLY)
3905 if (cpu_interrupts_enabled(env
)) {
3906 cpu_check_irqs(env
);
3911 static void do_modify_softint(const char* operation
, uint32_t value
)
3913 if (env
->softint
!= value
) {
3914 env
->softint
= value
;
3915 DPRINTF_PSTATE(": %s new %08x\n", operation
, env
->softint
);
3916 #if !defined(CONFIG_USER_ONLY)
3917 if (cpu_interrupts_enabled(env
)) {
3918 cpu_check_irqs(env
);
3924 void helper_set_softint(uint64_t value
)
3926 do_modify_softint("helper_set_softint", env
->softint
| (uint32_t)value
);
3929 void helper_clear_softint(uint64_t value
)
3931 do_modify_softint("helper_clear_softint", env
->softint
& (uint32_t)~value
);
3934 void helper_write_softint(uint64_t value
)
3936 do_modify_softint("helper_write_softint", (uint32_t)value
);
3940 void helper_flush(target_ulong addr
)
3943 tb_invalidate_page_range(addr
, addr
+ 8);
3946 #ifdef TARGET_SPARC64
3948 static const char * const excp_names
[0x80] = {
3949 [TT_TFAULT
] = "Instruction Access Fault",
3950 [TT_TMISS
] = "Instruction Access MMU Miss",
3951 [TT_CODE_ACCESS
] = "Instruction Access Error",
3952 [TT_ILL_INSN
] = "Illegal Instruction",
3953 [TT_PRIV_INSN
] = "Privileged Instruction",
3954 [TT_NFPU_INSN
] = "FPU Disabled",
3955 [TT_FP_EXCP
] = "FPU Exception",
3956 [TT_TOVF
] = "Tag Overflow",
3957 [TT_CLRWIN
] = "Clean Windows",
3958 [TT_DIV_ZERO
] = "Division By Zero",
3959 [TT_DFAULT
] = "Data Access Fault",
3960 [TT_DMISS
] = "Data Access MMU Miss",
3961 [TT_DATA_ACCESS
] = "Data Access Error",
3962 [TT_DPROT
] = "Data Protection Error",
3963 [TT_UNALIGNED
] = "Unaligned Memory Access",
3964 [TT_PRIV_ACT
] = "Privileged Action",
3965 [TT_EXTINT
| 0x1] = "External Interrupt 1",
3966 [TT_EXTINT
| 0x2] = "External Interrupt 2",
3967 [TT_EXTINT
| 0x3] = "External Interrupt 3",
3968 [TT_EXTINT
| 0x4] = "External Interrupt 4",
3969 [TT_EXTINT
| 0x5] = "External Interrupt 5",
3970 [TT_EXTINT
| 0x6] = "External Interrupt 6",
3971 [TT_EXTINT
| 0x7] = "External Interrupt 7",
3972 [TT_EXTINT
| 0x8] = "External Interrupt 8",
3973 [TT_EXTINT
| 0x9] = "External Interrupt 9",
3974 [TT_EXTINT
| 0xa] = "External Interrupt 10",
3975 [TT_EXTINT
| 0xb] = "External Interrupt 11",
3976 [TT_EXTINT
| 0xc] = "External Interrupt 12",
3977 [TT_EXTINT
| 0xd] = "External Interrupt 13",
3978 [TT_EXTINT
| 0xe] = "External Interrupt 14",
3979 [TT_EXTINT
| 0xf] = "External Interrupt 15",
3983 trap_state
* cpu_tsptr(CPUState
* env
)
3985 return &env
->ts
[env
->tl
& MAXTL_MASK
];
3988 void do_interrupt(CPUState
*env
)
3990 int intno
= env
->exception_index
;
3994 if (qemu_loglevel_mask(CPU_LOG_INT
)) {
3998 if (intno
< 0 || intno
>= 0x180)
4000 else if (intno
>= 0x100)
4001 name
= "Trap Instruction";
4002 else if (intno
>= 0xc0)
4003 name
= "Window Fill";
4004 else if (intno
>= 0x80)
4005 name
= "Window Spill";
4007 name
= excp_names
[intno
];
4012 qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64
" npc=%016" PRIx64
4013 " SP=%016" PRIx64
"\n",
4016 env
->npc
, env
->regwptr
[6]);
4017 log_cpu_state(env
, 0);
4024 ptr
= (uint8_t *)env
->pc
;
4025 for(i
= 0; i
< 16; i
++) {
4026 qemu_log(" %02x", ldub(ptr
+ i
));
4034 #if !defined(CONFIG_USER_ONLY)
4035 if (env
->tl
>= env
->maxtl
) {
4036 cpu_abort(env
, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
4037 " Error state", env
->exception_index
, env
->tl
, env
->maxtl
);
4041 if (env
->tl
< env
->maxtl
- 1) {
4044 env
->pstate
|= PS_RED
;
4045 if (env
->tl
< env
->maxtl
)
4048 tsptr
= cpu_tsptr(env
);
4050 tsptr
->tstate
= (get_ccr() << 32) |
4051 ((env
->asi
& 0xff) << 24) | ((env
->pstate
& 0xf3f) << 8) |
4053 tsptr
->tpc
= env
->pc
;
4054 tsptr
->tnpc
= env
->npc
;
4059 change_pstate(PS_PEF
| PS_PRIV
| PS_IG
);
4063 case TT_TMISS
... TT_TMISS
+ 3:
4064 case TT_DMISS
... TT_DMISS
+ 3:
4065 case TT_DPROT
... TT_DPROT
+ 3:
4066 change_pstate(PS_PEF
| PS_PRIV
| PS_MG
);
4069 change_pstate(PS_PEF
| PS_PRIV
| PS_AG
);
4073 if (intno
== TT_CLRWIN
) {
4074 set_cwp(cwp_dec(env
->cwp
- 1));
4075 } else if ((intno
& 0x1c0) == TT_SPILL
) {
4076 set_cwp(cwp_dec(env
->cwp
- env
->cansave
- 2));
4077 } else if ((intno
& 0x1c0) == TT_FILL
) {
4078 set_cwp(cwp_inc(env
->cwp
+ 1));
4080 env
->tbr
&= ~0x7fffULL
;
4081 env
->tbr
|= ((env
->tl
> 1) ? 1 << 14 : 0) | (intno
<< 5);
4083 env
->npc
= env
->pc
+ 4;
4084 env
->exception_index
= -1;
4088 static const char * const excp_names
[0x80] = {
4089 [TT_TFAULT
] = "Instruction Access Fault",
4090 [TT_ILL_INSN
] = "Illegal Instruction",
4091 [TT_PRIV_INSN
] = "Privileged Instruction",
4092 [TT_NFPU_INSN
] = "FPU Disabled",
4093 [TT_WIN_OVF
] = "Window Overflow",
4094 [TT_WIN_UNF
] = "Window Underflow",
4095 [TT_UNALIGNED
] = "Unaligned Memory Access",
4096 [TT_FP_EXCP
] = "FPU Exception",
4097 [TT_DFAULT
] = "Data Access Fault",
4098 [TT_TOVF
] = "Tag Overflow",
4099 [TT_EXTINT
| 0x1] = "External Interrupt 1",
4100 [TT_EXTINT
| 0x2] = "External Interrupt 2",
4101 [TT_EXTINT
| 0x3] = "External Interrupt 3",
4102 [TT_EXTINT
| 0x4] = "External Interrupt 4",
4103 [TT_EXTINT
| 0x5] = "External Interrupt 5",
4104 [TT_EXTINT
| 0x6] = "External Interrupt 6",
4105 [TT_EXTINT
| 0x7] = "External Interrupt 7",
4106 [TT_EXTINT
| 0x8] = "External Interrupt 8",
4107 [TT_EXTINT
| 0x9] = "External Interrupt 9",
4108 [TT_EXTINT
| 0xa] = "External Interrupt 10",
4109 [TT_EXTINT
| 0xb] = "External Interrupt 11",
4110 [TT_EXTINT
| 0xc] = "External Interrupt 12",
4111 [TT_EXTINT
| 0xd] = "External Interrupt 13",
4112 [TT_EXTINT
| 0xe] = "External Interrupt 14",
4113 [TT_EXTINT
| 0xf] = "External Interrupt 15",
4114 [TT_TOVF
] = "Tag Overflow",
4115 [TT_CODE_ACCESS
] = "Instruction Access Error",
4116 [TT_DATA_ACCESS
] = "Data Access Error",
4117 [TT_DIV_ZERO
] = "Division By Zero",
4118 [TT_NCP_INSN
] = "Coprocessor Disabled",
4122 void do_interrupt(CPUState
*env
)
4124 int cwp
, intno
= env
->exception_index
;
4127 if (qemu_loglevel_mask(CPU_LOG_INT
)) {
4131 if (intno
< 0 || intno
>= 0x100)
4133 else if (intno
>= 0x80)
4134 name
= "Trap Instruction";
4136 name
= excp_names
[intno
];
4141 qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
4144 env
->npc
, env
->regwptr
[6]);
4145 log_cpu_state(env
, 0);
4152 ptr
= (uint8_t *)env
->pc
;
4153 for(i
= 0; i
< 16; i
++) {
4154 qemu_log(" %02x", ldub(ptr
+ i
));
4162 #if !defined(CONFIG_USER_ONLY)
4163 if (env
->psret
== 0) {
4164 cpu_abort(env
, "Trap 0x%02x while interrupts disabled, Error state",
4165 env
->exception_index
);
4170 cwp
= cwp_dec(env
->cwp
- 1);
4172 env
->regwptr
[9] = env
->pc
;
4173 env
->regwptr
[10] = env
->npc
;
4174 env
->psrps
= env
->psrs
;
4176 env
->tbr
= (env
->tbr
& TBR_BASE_MASK
) | (intno
<< 4);
4178 env
->npc
= env
->pc
+ 4;
4179 env
->exception_index
= -1;
4183 #if !defined(CONFIG_USER_ONLY)
4185 static void do_unaligned_access(target_ulong addr
, int is_write
, int is_user
,
4188 #define MMUSUFFIX _mmu
4189 #define ALIGNED_ONLY
4192 #include "softmmu_template.h"
4195 #include "softmmu_template.h"
4198 #include "softmmu_template.h"
4201 #include "softmmu_template.h"
4203 /* XXX: make it generic ? */
4204 static void cpu_restore_state2(void *retaddr
)
4206 TranslationBlock
*tb
;
4210 /* now we have a real cpu fault */
4211 pc
= (unsigned long)retaddr
;
4212 tb
= tb_find_pc(pc
);
4214 /* the PC is inside the translated code. It means that we have
4215 a virtual CPU fault */
4216 cpu_restore_state(tb
, env
, pc
, (void *)(long)env
->cond
);
4221 static void do_unaligned_access(target_ulong addr
, int is_write
, int is_user
,
4224 #ifdef DEBUG_UNALIGNED
4225 printf("Unaligned access to 0x" TARGET_FMT_lx
" from 0x" TARGET_FMT_lx
4226 "\n", addr
, env
->pc
);
4228 cpu_restore_state2(retaddr
);
4229 raise_exception(TT_UNALIGNED
);
4232 /* try to fill the TLB and return an exception if error. If retaddr is
4233 NULL, it means that the function was called in C code (i.e. not
4234 from generated code or from helper.c) */
4235 /* XXX: fix it to restore all registers */
4236 void tlb_fill(target_ulong addr
, int is_write
, int mmu_idx
, void *retaddr
)
4239 CPUState
*saved_env
;
4241 /* XXX: hack to restore env in all cases, even if not called from
4244 env
= cpu_single_env
;
4246 ret
= cpu_sparc_handle_mmu_fault(env
, addr
, is_write
, mmu_idx
, 1);
4248 cpu_restore_state2(retaddr
);
4254 #endif /* !CONFIG_USER_ONLY */
4256 #ifndef TARGET_SPARC64
4257 #if !defined(CONFIG_USER_ONLY)
4258 void do_unassigned_access(target_phys_addr_t addr
, int is_write
, int is_exec
,
4259 int is_asi
, int size
)
4261 CPUState
*saved_env
;
4264 /* XXX: hack to restore env in all cases, even if not called from
4267 env
= cpu_single_env
;
4268 #ifdef DEBUG_UNASSIGNED
4270 printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
4271 " asi 0x%02x from " TARGET_FMT_lx
"\n",
4272 is_exec
? "exec" : is_write
? "write" : "read", size
,
4273 size
== 1 ? "" : "s", addr
, is_asi
, env
->pc
);
4275 printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
4276 " from " TARGET_FMT_lx
"\n",
4277 is_exec
? "exec" : is_write
? "write" : "read", size
,
4278 size
== 1 ? "" : "s", addr
, env
->pc
);
4280 /* Don't overwrite translation and access faults */
4281 fault_type
= (env
->mmuregs
[3] & 0x1c) >> 2;
4282 if ((fault_type
> 4) || (fault_type
== 0)) {
4283 env
->mmuregs
[3] = 0; /* Fault status register */
4285 env
->mmuregs
[3] |= 1 << 16;
4287 env
->mmuregs
[3] |= 1 << 5;
4289 env
->mmuregs
[3] |= 1 << 6;
4291 env
->mmuregs
[3] |= 1 << 7;
4292 env
->mmuregs
[3] |= (5 << 2) | 2;
4293 /* SuperSPARC will never place instruction fault addresses in the FAR */
4295 env
->mmuregs
[4] = addr
; /* Fault address register */
4298 /* overflow (same type fault was not read before another fault) */
4299 if (fault_type
== ((env
->mmuregs
[3] & 0x1c)) >> 2) {
4300 env
->mmuregs
[3] |= 1;
4303 if ((env
->mmuregs
[0] & MMU_E
) && !(env
->mmuregs
[0] & MMU_NF
)) {
4305 raise_exception(TT_CODE_ACCESS
);
4307 raise_exception(TT_DATA_ACCESS
);
4310 /* flush neverland mappings created during no-fault mode,
4311 so the sequential MMU faults report proper fault types */
4312 if (env
->mmuregs
[0] & MMU_NF
) {
4320 #if defined(CONFIG_USER_ONLY)
4321 static void do_unassigned_access(target_ulong addr
, int is_write
, int is_exec
,
4322 int is_asi
, int size
)
4324 void do_unassigned_access(target_phys_addr_t addr
, int is_write
, int is_exec
,
4325 int is_asi
, int size
)
4328 CPUState
*saved_env
;
4330 /* XXX: hack to restore env in all cases, even if not called from
4333 env
= cpu_single_env
;
4335 #ifdef DEBUG_UNASSIGNED
4336 printf("Unassigned mem access to " TARGET_FMT_plx
" from " TARGET_FMT_lx
4337 "\n", addr
, env
->pc
);
4341 raise_exception(TT_CODE_ACCESS
);
4343 raise_exception(TT_DATA_ACCESS
);
4350 #ifdef TARGET_SPARC64
4351 void helper_tick_set_count(void *opaque
, uint64_t count
)
4353 #if !defined(CONFIG_USER_ONLY)
4354 cpu_tick_set_count(opaque
, count
);
4358 uint64_t helper_tick_get_count(void *opaque
)
4360 #if !defined(CONFIG_USER_ONLY)
4361 return cpu_tick_get_count(opaque
);
4367 void helper_tick_set_limit(void *opaque
, uint64_t limit
)
4369 #if !defined(CONFIG_USER_ONLY)
4370 cpu_tick_set_limit(opaque
, limit
);