]>
git.proxmox.com Git - qemu.git/blob - target-sparc/op_helper.c
5 //#define DEBUG_UNALIGNED
6 //#define DEBUG_UNASSIGNED
8 void raise_exception(int tt
)
10 env
->exception_index
= tt
;
14 void check_ieee_exceptions()
16 T0
= get_float_exception_flags(&env
->fp_status
);
19 /* Copy IEEE 754 flags into FSR */
20 if (T0
& float_flag_invalid
)
22 if (T0
& float_flag_overflow
)
24 if (T0
& float_flag_underflow
)
26 if (T0
& float_flag_divbyzero
)
28 if (T0
& float_flag_inexact
)
31 if ((env
->fsr
& FSR_CEXC_MASK
) & ((env
->fsr
& FSR_TEM_MASK
) >> 23))
33 /* Unmasked exception, generate a trap */
34 env
->fsr
|= FSR_FTT_IEEE_EXCP
;
35 raise_exception(TT_FP_EXCP
);
39 /* Accumulate exceptions */
40 env
->fsr
|= (env
->fsr
& FSR_CEXC_MASK
) << 5;
45 #ifdef USE_INT_TO_FLOAT_HELPERS
48 set_float_exception_flags(0, &env
->fp_status
);
49 FT0
= int32_to_float32(*((int32_t *)&FT1
), &env
->fp_status
);
50 check_ieee_exceptions();
55 DT0
= int32_to_float64(*((int32_t *)&FT1
), &env
->fp_status
);
61 FT0
= float32_abs(FT1
);
67 DT0
= float64_abs(DT1
);
73 set_float_exception_flags(0, &env
->fp_status
);
74 FT0
= float32_sqrt(FT1
, &env
->fp_status
);
75 check_ieee_exceptions();
80 set_float_exception_flags(0, &env
->fp_status
);
81 DT0
= float64_sqrt(DT1
, &env
->fp_status
);
82 check_ieee_exceptions();
85 #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
86 void glue(do_, name) (void) \
88 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
89 switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
90 case float_relation_unordered: \
91 T0 = (FSR_FCC1 | FSR_FCC0) << FS; \
92 if ((env->fsr & FSR_NVM) || TRAP) { \
94 env->fsr |= FSR_NVC; \
95 env->fsr |= FSR_FTT_IEEE_EXCP; \
96 raise_exception(TT_FP_EXCP); \
98 env->fsr |= FSR_NVA; \
101 case float_relation_less: \
102 T0 = FSR_FCC0 << FS; \
104 case float_relation_greater: \
105 T0 = FSR_FCC1 << FS; \
114 GEN_FCMP(fcmps
, float32
, FT0
, FT1
, 0, 0);
115 GEN_FCMP(fcmpd
, float64
, DT0
, DT1
, 0, 0);
117 GEN_FCMP(fcmpes
, float32
, FT0
, FT1
, 0, 1);
118 GEN_FCMP(fcmped
, float64
, DT0
, DT1
, 0, 1);
120 #ifdef TARGET_SPARC64
121 GEN_FCMP(fcmps_fcc1
, float32
, FT0
, FT1
, 22, 0);
122 GEN_FCMP(fcmpd_fcc1
, float64
, DT0
, DT1
, 22, 0);
124 GEN_FCMP(fcmps_fcc2
, float32
, FT0
, FT1
, 24, 0);
125 GEN_FCMP(fcmpd_fcc2
, float64
, DT0
, DT1
, 24, 0);
127 GEN_FCMP(fcmps_fcc3
, float32
, FT0
, FT1
, 26, 0);
128 GEN_FCMP(fcmpd_fcc3
, float64
, DT0
, DT1
, 26, 0);
130 GEN_FCMP(fcmpes_fcc1
, float32
, FT0
, FT1
, 22, 1);
131 GEN_FCMP(fcmped_fcc1
, float64
, DT0
, DT1
, 22, 1);
133 GEN_FCMP(fcmpes_fcc2
, float32
, FT0
, FT1
, 24, 1);
134 GEN_FCMP(fcmped_fcc2
, float64
, DT0
, DT1
, 24, 1);
136 GEN_FCMP(fcmpes_fcc3
, float32
, FT0
, FT1
, 26, 1);
137 GEN_FCMP(fcmped_fcc3
, float64
, DT0
, DT1
, 26, 1);
140 #ifndef TARGET_SPARC64
141 #ifndef CONFIG_USER_ONLY
142 void helper_ld_asi(int asi
, int size
, int sign
)
147 case 2: /* SuperSparc MXCC registers */
149 case 3: /* MMU probe */
153 mmulev
= (T0
>> 8) & 15;
157 ret
= mmu_probe(env
, T0
, mmulev
);
161 printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0
, mmulev
, ret
);
165 case 4: /* read MMU regs */
167 int reg
= (T0
>> 8) & 0xf;
169 ret
= env
->mmuregs
[reg
];
170 if (reg
== 3) /* Fault status cleared on read */
171 env
->mmuregs
[reg
] = 0;
173 printf("mmu_read: reg[%d] = 0x%08x\n", reg
, ret
);
177 case 9: /* Supervisor code access */
183 ret
= lduw_code(T0
& ~1);
187 ret
= ldl_code(T0
& ~3);
190 ret
= ldl_code(T0
& ~3);
191 T0
= ldl_code((T0
+ 4) & ~3);
195 case 0xa: /* User data access */
201 ret
= lduw_user(T0
& ~1);
205 ret
= ldl_user(T0
& ~3);
208 ret
= ldl_user(T0
& ~3);
209 T0
= ldl_user((T0
+ 4) & ~3);
213 case 0xb: /* Supervisor data access */
216 ret
= ldub_kernel(T0
);
219 ret
= lduw_kernel(T0
& ~1);
223 ret
= ldl_kernel(T0
& ~3);
226 ret
= ldl_kernel(T0
& ~3);
227 T0
= ldl_kernel((T0
+ 4) & ~3);
231 case 0xc: /* I-cache tag */
232 case 0xd: /* I-cache data */
233 case 0xe: /* D-cache tag */
234 case 0xf: /* D-cache data */
236 case 0x20: /* MMU passthrough */
242 ret
= lduw_phys(T0
& ~1);
246 ret
= ldl_phys(T0
& ~3);
249 ret
= ldl_phys(T0
& ~3);
250 T0
= ldl_phys((T0
+ 4) & ~3);
254 case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
255 case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
258 ret
= ldub_phys((target_phys_addr_t
)T0
259 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
262 ret
= lduw_phys((target_phys_addr_t
)(T0
& ~1)
263 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
267 ret
= ldl_phys((target_phys_addr_t
)(T0
& ~3)
268 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
271 ret
= ldl_phys((target_phys_addr_t
)(T0
& ~3)
272 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
273 T0
= ldl_phys((target_phys_addr_t
)((T0
+ 4) & ~3)
274 | ((target_phys_addr_t
)(asi
& 0xf) << 32));
278 case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
280 do_unassigned_access(T0
, 0, 0, 1);
301 void helper_st_asi(int asi
, int size
)
304 case 2: /* SuperSparc MXCC registers */
306 case 3: /* MMU flush */
310 mmulev
= (T0
>> 8) & 15;
312 printf("mmu flush level %d\n", mmulev
);
315 case 0: // flush page
316 tlb_flush_page(env
, T0
& 0xfffff000);
318 case 1: // flush segment (256k)
319 case 2: // flush region (16M)
320 case 3: // flush context (4G)
321 case 4: // flush entire
332 case 4: /* write MMU regs */
334 int reg
= (T0
>> 8) & 0xf;
337 oldreg
= env
->mmuregs
[reg
];
340 env
->mmuregs
[reg
] &= ~(MMU_E
| MMU_NF
| MMU_BM
);
341 env
->mmuregs
[reg
] |= T1
& (MMU_E
| MMU_NF
| MMU_BM
);
342 // Mappings generated during no-fault mode or MMU
343 // disabled mode are invalid in normal mode
344 if (oldreg
!= env
->mmuregs
[reg
])
348 env
->mmuregs
[reg
] = T1
;
349 if (oldreg
!= env
->mmuregs
[reg
]) {
350 /* we flush when the MMU context changes because
351 QEMU has no MMU context support */
359 env
->mmuregs
[reg
] = T1
;
363 if (oldreg
!= env
->mmuregs
[reg
]) {
364 printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg
, oldreg
, env
->mmuregs
[reg
]);
370 case 0xa: /* User data access */
376 stw_user(T0
& ~1, T1
);
380 stl_user(T0
& ~3, T1
);
383 stl_user(T0
& ~3, T1
);
384 stl_user((T0
+ 4) & ~3, T2
);
388 case 0xb: /* Supervisor data access */
394 stw_kernel(T0
& ~1, T1
);
398 stl_kernel(T0
& ~3, T1
);
401 stl_kernel(T0
& ~3, T1
);
402 stl_kernel((T0
+ 4) & ~3, T2
);
406 case 0xc: /* I-cache tag */
407 case 0xd: /* I-cache data */
408 case 0xe: /* D-cache tag */
409 case 0xf: /* D-cache data */
410 case 0x10: /* I/D-cache flush page */
411 case 0x11: /* I/D-cache flush segment */
412 case 0x12: /* I/D-cache flush region */
413 case 0x13: /* I/D-cache flush context */
414 case 0x14: /* I/D-cache flush user */
416 case 0x17: /* Block copy, sta access */
419 // address (T0) = dst
422 uint32_t src
= T1
& ~3, dst
= T0
& ~3, temp
;
424 for (i
= 0; i
< 32; i
+= 4, src
+= 4, dst
+= 4) {
425 temp
= ldl_kernel(src
);
426 stl_kernel(dst
, temp
);
430 case 0x1f: /* Block fill, stda access */
433 // address (T0) = dst
436 uint32_t dst
= T0
& 7;
439 val
= (((uint64_t)T1
) << 32) | T2
;
441 for (i
= 0; i
< 32; i
+= 8, dst
+= 8)
442 stq_kernel(dst
, val
);
445 case 0x20: /* MMU passthrough */
452 stw_phys(T0
& ~1, T1
);
456 stl_phys(T0
& ~3, T1
);
459 stl_phys(T0
& ~3, T1
);
460 stl_phys((T0
+ 4) & ~3, T2
);
465 case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
466 case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
470 stb_phys((target_phys_addr_t
)T0
471 | ((target_phys_addr_t
)(asi
& 0xf) << 32), T1
);
474 stw_phys((target_phys_addr_t
)(T0
& ~1)
475 | ((target_phys_addr_t
)(asi
& 0xf) << 32), T1
);
479 stl_phys((target_phys_addr_t
)(T0
& ~3)
480 | ((target_phys_addr_t
)(asi
& 0xf) << 32), T1
);
483 stl_phys((target_phys_addr_t
)(T0
& ~3)
484 | ((target_phys_addr_t
)(asi
& 0xf) << 32), T1
);
485 stl_phys((target_phys_addr_t
)((T0
+ 4) & ~3)
486 | ((target_phys_addr_t
)(asi
& 0xf) << 32), T1
);
491 case 0x31: /* Ross RT620 I-cache flush */
492 case 0x36: /* I-cache flash clear */
493 case 0x37: /* D-cache flash clear */
495 case 9: /* Supervisor code access, XXX */
496 case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
498 do_unassigned_access(T0
, 1, 0, 1);
503 #endif /* CONFIG_USER_ONLY */
504 #else /* TARGET_SPARC64 */
506 #ifdef CONFIG_USER_ONLY
507 void helper_ld_asi(int asi
, int size
, int sign
)
512 raise_exception(TT_PRIV_ACT
);
515 case 0x80: // Primary
516 case 0x82: // Primary no-fault
517 case 0x88: // Primary LE
518 case 0x8a: // Primary no-fault LE
525 ret
= lduw_raw(T0
& ~1);
528 ret
= ldl_raw(T0
& ~3);
532 ret
= ldq_raw(T0
& ~7);
537 case 0x81: // Secondary
538 case 0x83: // Secondary no-fault
539 case 0x89: // Secondary LE
540 case 0x8b: // Secondary no-fault LE
547 /* Convert from little endian */
549 case 0x88: // Primary LE
550 case 0x89: // Secondary LE
551 case 0x8a: // Primary no-fault LE
552 case 0x8b: // Secondary no-fault LE
570 /* Convert to signed number */
589 void helper_st_asi(int asi
, int size
)
592 raise_exception(TT_PRIV_ACT
);
594 /* Convert to little endian */
596 case 0x88: // Primary LE
597 case 0x89: // Secondary LE
616 case 0x80: // Primary
617 case 0x88: // Primary LE
624 stw_raw(T0
& ~1, T1
);
627 stl_raw(T0
& ~3, T1
);
631 stq_raw(T0
& ~7, T1
);
636 case 0x81: // Secondary
637 case 0x89: // Secondary LE
641 case 0x82: // Primary no-fault, RO
642 case 0x83: // Secondary no-fault, RO
643 case 0x8a: // Primary no-fault LE, RO
644 case 0x8b: // Secondary no-fault LE, RO
646 do_unassigned_access(T0
, 1, 0, 1);
651 #else /* CONFIG_USER_ONLY */
653 void helper_ld_asi(int asi
, int size
, int sign
)
657 if (asi
< 0x80 && (env
->pstate
& PS_PRIV
) == 0)
658 raise_exception(TT_PRIV_ACT
);
661 case 0x10: // As if user primary
662 case 0x18: // As if user primary LE
663 case 0x80: // Primary
664 case 0x82: // Primary no-fault
665 case 0x88: // Primary LE
666 case 0x8a: // Primary no-fault LE
667 if ((asi
& 0x80) && (env
->pstate
& PS_PRIV
)) {
670 ret
= ldub_kernel(T0
);
673 ret
= lduw_kernel(T0
& ~1);
676 ret
= ldl_kernel(T0
& ~3);
680 ret
= ldq_kernel(T0
& ~7);
689 ret
= lduw_user(T0
& ~1);
692 ret
= ldl_user(T0
& ~3);
696 ret
= ldq_user(T0
& ~7);
702 case 0x15: // Bypass, non-cacheable
703 case 0x1c: // Bypass LE
704 case 0x1d: // Bypass, non-cacheable LE
711 ret
= lduw_phys(T0
& ~1);
714 ret
= ldl_phys(T0
& ~3);
718 ret
= ldq_phys(T0
& ~7);
723 case 0x04: // Nucleus
724 case 0x0c: // Nucleus Little Endian (LE)
725 case 0x11: // As if user secondary
726 case 0x19: // As if user secondary LE
727 case 0x24: // Nucleus quad LDD 128 bit atomic
728 case 0x2c: // Nucleus quad LDD 128 bit atomic
729 case 0x4a: // UPA config
730 case 0x81: // Secondary
731 case 0x83: // Secondary no-fault
732 case 0x89: // Secondary LE
733 case 0x8b: // Secondary no-fault LE
739 case 0x50: // I-MMU regs
741 int reg
= (T0
>> 3) & 0xf;
743 ret
= env
->immuregs
[reg
];
746 case 0x51: // I-MMU 8k TSB pointer
747 case 0x52: // I-MMU 64k TSB pointer
748 case 0x55: // I-MMU data access
751 case 0x56: // I-MMU tag read
755 for (i
= 0; i
< 64; i
++) {
756 // Valid, ctx match, vaddr match
757 if ((env
->itlb_tte
[i
] & 0x8000000000000000ULL
) != 0 &&
758 env
->itlb_tag
[i
] == T0
) {
759 ret
= env
->itlb_tag
[i
];
765 case 0x58: // D-MMU regs
767 int reg
= (T0
>> 3) & 0xf;
769 ret
= env
->dmmuregs
[reg
];
772 case 0x5e: // D-MMU tag read
776 for (i
= 0; i
< 64; i
++) {
777 // Valid, ctx match, vaddr match
778 if ((env
->dtlb_tte
[i
] & 0x8000000000000000ULL
) != 0 &&
779 env
->dtlb_tag
[i
] == T0
) {
780 ret
= env
->dtlb_tag
[i
];
786 case 0x59: // D-MMU 8k TSB pointer
787 case 0x5a: // D-MMU 64k TSB pointer
788 case 0x5b: // D-MMU data pointer
789 case 0x5d: // D-MMU data access
790 case 0x48: // Interrupt dispatch, RO
791 case 0x49: // Interrupt data receive
792 case 0x7f: // Incoming interrupt vector, RO
795 case 0x54: // I-MMU data in, WO
796 case 0x57: // I-MMU demap, WO
797 case 0x5c: // D-MMU data in, WO
798 case 0x5f: // D-MMU demap, WO
799 case 0x77: // Interrupt vector, WO
801 do_unassigned_access(T0
, 0, 0, 1);
806 /* Convert from little endian */
808 case 0x0c: // Nucleus Little Endian (LE)
809 case 0x18: // As if user primary LE
810 case 0x19: // As if user secondary LE
811 case 0x1c: // Bypass LE
812 case 0x1d: // Bypass, non-cacheable LE
813 case 0x88: // Primary LE
814 case 0x89: // Secondary LE
815 case 0x8a: // Primary no-fault LE
816 case 0x8b: // Secondary no-fault LE
834 /* Convert to signed number */
853 void helper_st_asi(int asi
, int size
)
855 if (asi
< 0x80 && (env
->pstate
& PS_PRIV
) == 0)
856 raise_exception(TT_PRIV_ACT
);
858 /* Convert to little endian */
860 case 0x0c: // Nucleus Little Endian (LE)
861 case 0x18: // As if user primary LE
862 case 0x19: // As if user secondary LE
863 case 0x1c: // Bypass LE
864 case 0x1d: // Bypass, non-cacheable LE
865 case 0x88: // Primary LE
866 case 0x89: // Secondary LE
885 case 0x10: // As if user primary
886 case 0x18: // As if user primary LE
887 case 0x80: // Primary
888 case 0x88: // Primary LE
889 if ((asi
& 0x80) && (env
->pstate
& PS_PRIV
)) {
895 stw_kernel(T0
& ~1, T1
);
898 stl_kernel(T0
& ~3, T1
);
902 stq_kernel(T0
& ~7, T1
);
911 stw_user(T0
& ~1, T1
);
914 stl_user(T0
& ~3, T1
);
918 stq_user(T0
& ~7, T1
);
924 case 0x15: // Bypass, non-cacheable
925 case 0x1c: // Bypass LE
926 case 0x1d: // Bypass, non-cacheable LE
933 stw_phys(T0
& ~1, T1
);
936 stl_phys(T0
& ~3, T1
);
940 stq_phys(T0
& ~7, T1
);
945 case 0x04: // Nucleus
946 case 0x0c: // Nucleus Little Endian (LE)
947 case 0x11: // As if user secondary
948 case 0x19: // As if user secondary LE
949 case 0x24: // Nucleus quad LDD 128 bit atomic
950 case 0x2c: // Nucleus quad LDD 128 bit atomic
951 case 0x4a: // UPA config
952 case 0x81: // Secondary
953 case 0x89: // Secondary LE
961 env
->lsu
= T1
& (DMMU_E
| IMMU_E
);
962 // Mappings generated during D/I MMU disabled mode are
963 // invalid in normal mode
964 if (oldreg
!= env
->lsu
) {
966 printf("LSU change: 0x%" PRIx64
" -> 0x%" PRIx64
"\n", oldreg
, env
->lsu
);
973 case 0x50: // I-MMU regs
975 int reg
= (T0
>> 3) & 0xf;
978 oldreg
= env
->immuregs
[reg
];
983 case 1: // Not in I-MMU
990 T1
= 0; // Clear SFSR
992 case 5: // TSB access
993 case 6: // Tag access
997 env
->immuregs
[reg
] = T1
;
999 if (oldreg
!= env
->immuregs
[reg
]) {
1000 printf("mmu change reg[%d]: 0x%08" PRIx64
" -> 0x%08" PRIx64
"\n", reg
, oldreg
, env
->immuregs
[reg
]);
1006 case 0x54: // I-MMU data in
1010 // Try finding an invalid entry
1011 for (i
= 0; i
< 64; i
++) {
1012 if ((env
->itlb_tte
[i
] & 0x8000000000000000ULL
) == 0) {
1013 env
->itlb_tag
[i
] = env
->immuregs
[6];
1014 env
->itlb_tte
[i
] = T1
;
1018 // Try finding an unlocked entry
1019 for (i
= 0; i
< 64; i
++) {
1020 if ((env
->itlb_tte
[i
] & 0x40) == 0) {
1021 env
->itlb_tag
[i
] = env
->immuregs
[6];
1022 env
->itlb_tte
[i
] = T1
;
1029 case 0x55: // I-MMU data access
1031 unsigned int i
= (T0
>> 3) & 0x3f;
1033 env
->itlb_tag
[i
] = env
->immuregs
[6];
1034 env
->itlb_tte
[i
] = T1
;
1037 case 0x57: // I-MMU demap
1040 case 0x58: // D-MMU regs
1042 int reg
= (T0
>> 3) & 0xf;
1045 oldreg
= env
->dmmuregs
[reg
];
1051 if ((T1
& 1) == 0) {
1052 T1
= 0; // Clear SFSR, Fault address
1053 env
->dmmuregs
[4] = 0;
1055 env
->dmmuregs
[reg
] = T1
;
1057 case 1: // Primary context
1058 case 2: // Secondary context
1059 case 5: // TSB access
1060 case 6: // Tag access
1061 case 7: // Virtual Watchpoint
1062 case 8: // Physical Watchpoint
1066 env
->dmmuregs
[reg
] = T1
;
1068 if (oldreg
!= env
->dmmuregs
[reg
]) {
1069 printf("mmu change reg[%d]: 0x%08" PRIx64
" -> 0x%08" PRIx64
"\n", reg
, oldreg
, env
->dmmuregs
[reg
]);
1075 case 0x5c: // D-MMU data in
1079 // Try finding an invalid entry
1080 for (i
= 0; i
< 64; i
++) {
1081 if ((env
->dtlb_tte
[i
] & 0x8000000000000000ULL
) == 0) {
1082 env
->dtlb_tag
[i
] = env
->dmmuregs
[6];
1083 env
->dtlb_tte
[i
] = T1
;
1087 // Try finding an unlocked entry
1088 for (i
= 0; i
< 64; i
++) {
1089 if ((env
->dtlb_tte
[i
] & 0x40) == 0) {
1090 env
->dtlb_tag
[i
] = env
->dmmuregs
[6];
1091 env
->dtlb_tte
[i
] = T1
;
1098 case 0x5d: // D-MMU data access
1100 unsigned int i
= (T0
>> 3) & 0x3f;
1102 env
->dtlb_tag
[i
] = env
->dmmuregs
[6];
1103 env
->dtlb_tte
[i
] = T1
;
1106 case 0x5f: // D-MMU demap
1107 case 0x49: // Interrupt data receive
1110 case 0x51: // I-MMU 8k TSB pointer, RO
1111 case 0x52: // I-MMU 64k TSB pointer, RO
1112 case 0x56: // I-MMU tag read, RO
1113 case 0x59: // D-MMU 8k TSB pointer, RO
1114 case 0x5a: // D-MMU 64k TSB pointer, RO
1115 case 0x5b: // D-MMU data pointer, RO
1116 case 0x5e: // D-MMU tag read, RO
1117 case 0x48: // Interrupt dispatch, RO
1118 case 0x7f: // Incoming interrupt vector, RO
1119 case 0x82: // Primary no-fault, RO
1120 case 0x83: // Secondary no-fault, RO
1121 case 0x8a: // Primary no-fault LE, RO
1122 case 0x8b: // Secondary no-fault LE, RO
1124 do_unassigned_access(T0
, 1, 0, 1);
1128 #endif /* CONFIG_USER_ONLY */
1130 void helper_ldf_asi(int asi
, int size
, int rd
)
1132 target_ulong tmp_T0
= T0
, tmp_T1
= T1
;
1136 case 0xf0: // Block load primary
1137 case 0xf1: // Block load secondary
1138 case 0xf8: // Block load primary LE
1139 case 0xf9: // Block load secondary LE
1141 raise_exception(TT_ILL_INSN
);
1145 raise_exception(TT_UNALIGNED
);
1148 for (i
= 0; i
< 16; i
++) {
1149 helper_ld_asi(asi
& 0x8f, 4, 0);
1150 *(uint32_t *)&env
->fpr
[rd
++] = T1
;
1161 helper_ld_asi(asi
, size
, 0);
1165 *((uint32_t *)&FT0
) = T1
;
1168 *((int64_t *)&DT0
) = T1
;
1174 void helper_stf_asi(int asi
, int size
, int rd
)
1176 target_ulong tmp_T0
= T0
, tmp_T1
= T1
;
1180 case 0xf0: // Block store primary
1181 case 0xf1: // Block store secondary
1182 case 0xf8: // Block store primary LE
1183 case 0xf9: // Block store secondary LE
1185 raise_exception(TT_ILL_INSN
);
1189 raise_exception(TT_UNALIGNED
);
1192 for (i
= 0; i
< 16; i
++) {
1193 T1
= *(uint32_t *)&env
->fpr
[rd
++];
1194 helper_st_asi(asi
& 0x8f, 4);
1208 T1
= *((uint32_t *)&FT0
);
1211 T1
= *((int64_t *)&DT0
);
1214 helper_st_asi(asi
, size
);
1218 #endif /* TARGET_SPARC64 */
1220 #ifndef TARGET_SPARC64
1225 if (env
->psret
== 1)
1226 raise_exception(TT_ILL_INSN
);
1229 cwp
= (env
->cwp
+ 1) & (NWINDOWS
- 1);
1230 if (env
->wim
& (1 << cwp
)) {
1231 raise_exception(TT_WIN_UNF
);
1234 env
->psrs
= env
->psrps
;
1238 void helper_ldfsr(void)
1241 switch (env
->fsr
& FSR_RD_MASK
) {
1242 case FSR_RD_NEAREST
:
1243 rnd_mode
= float_round_nearest_even
;
1247 rnd_mode
= float_round_to_zero
;
1250 rnd_mode
= float_round_up
;
1253 rnd_mode
= float_round_down
;
1256 set_float_rounding_mode(rnd_mode
, &env
->fp_status
);
1261 env
->exception_index
= EXCP_DEBUG
;
1265 #ifndef TARGET_SPARC64
1268 if ((T0
& PSR_CWP
) >= NWINDOWS
)
1269 raise_exception(TT_ILL_INSN
);
1283 T0
= (T1
& 0x5555555555555555ULL
) + ((T1
>> 1) & 0x5555555555555555ULL
);
1284 T0
= (T0
& 0x3333333333333333ULL
) + ((T0
>> 2) & 0x3333333333333333ULL
);
1285 T0
= (T0
& 0x0f0f0f0f0f0f0f0fULL
) + ((T0
>> 4) & 0x0f0f0f0f0f0f0f0fULL
);
1286 T0
= (T0
& 0x00ff00ff00ff00ffULL
) + ((T0
>> 8) & 0x00ff00ff00ff00ffULL
);
1287 T0
= (T0
& 0x0000ffff0000ffffULL
) + ((T0
>> 16) & 0x0000ffff0000ffffULL
);
1288 T0
= (T0
& 0x00000000ffffffffULL
) + ((T0
>> 32) & 0x00000000ffffffffULL
);
1291 static inline uint64_t *get_gregset(uint64_t pstate
)
1306 static inline void change_pstate(uint64_t new_pstate
)
1308 uint64_t pstate_regs
, new_pstate_regs
;
1309 uint64_t *src
, *dst
;
1311 pstate_regs
= env
->pstate
& 0xc01;
1312 new_pstate_regs
= new_pstate
& 0xc01;
1313 if (new_pstate_regs
!= pstate_regs
) {
1314 // Switch global register bank
1315 src
= get_gregset(new_pstate_regs
);
1316 dst
= get_gregset(pstate_regs
);
1317 memcpy32(dst
, env
->gregs
);
1318 memcpy32(env
->gregs
, src
);
1320 env
->pstate
= new_pstate
;
1323 void do_wrpstate(void)
1325 change_pstate(T0
& 0xf3f);
1331 env
->pc
= env
->tnpc
[env
->tl
];
1332 env
->npc
= env
->tnpc
[env
->tl
] + 4;
1333 PUT_CCR(env
, env
->tstate
[env
->tl
] >> 32);
1334 env
->asi
= (env
->tstate
[env
->tl
] >> 24) & 0xff;
1335 change_pstate((env
->tstate
[env
->tl
] >> 8) & 0xf3f);
1336 PUT_CWP64(env
, env
->tstate
[env
->tl
] & 0xff);
1342 env
->pc
= env
->tpc
[env
->tl
];
1343 env
->npc
= env
->tnpc
[env
->tl
];
1344 PUT_CCR(env
, env
->tstate
[env
->tl
] >> 32);
1345 env
->asi
= (env
->tstate
[env
->tl
] >> 24) & 0xff;
1346 change_pstate((env
->tstate
[env
->tl
] >> 8) & 0xf3f);
1347 PUT_CWP64(env
, env
->tstate
[env
->tl
] & 0xff);
1351 void set_cwp(int new_cwp
)
1353 /* put the modified wrap registers at their proper location */
1354 if (env
->cwp
== (NWINDOWS
- 1))
1355 memcpy32(env
->regbase
, env
->regbase
+ NWINDOWS
* 16);
1357 /* put the wrap registers at their temporary location */
1358 if (new_cwp
== (NWINDOWS
- 1))
1359 memcpy32(env
->regbase
+ NWINDOWS
* 16, env
->regbase
);
1360 env
->regwptr
= env
->regbase
+ (new_cwp
* 16);
1361 REGWPTR
= env
->regwptr
;
1364 void cpu_set_cwp(CPUState
*env1
, int new_cwp
)
1366 CPUState
*saved_env
;
1368 target_ulong
*saved_regwptr
;
1373 saved_regwptr
= REGWPTR
;
1379 REGWPTR
= saved_regwptr
;
1383 #ifdef TARGET_SPARC64
1384 void do_interrupt(int intno
)
1387 if (loglevel
& CPU_LOG_INT
) {
1389 fprintf(logfile
, "%6d: v=%04x pc=%016" PRIx64
" npc=%016" PRIx64
" SP=%016" PRIx64
"\n",
1392 env
->npc
, env
->regwptr
[6]);
1393 cpu_dump_state(env
, logfile
, fprintf
, 0);
1399 fprintf(logfile
, " code=");
1400 ptr
= (uint8_t *)env
->pc
;
1401 for(i
= 0; i
< 16; i
++) {
1402 fprintf(logfile
, " %02x", ldub(ptr
+ i
));
1404 fprintf(logfile
, "\n");
1410 #if !defined(CONFIG_USER_ONLY)
1411 if (env
->tl
== MAXTL
) {
1412 cpu_abort(env
, "Trap 0x%04x while trap level is MAXTL, Error state", env
->exception_index
);
1416 env
->tstate
[env
->tl
] = ((uint64_t)GET_CCR(env
) << 32) | ((env
->asi
& 0xff) << 24) |
1417 ((env
->pstate
& 0xf3f) << 8) | GET_CWP64(env
);
1418 env
->tpc
[env
->tl
] = env
->pc
;
1419 env
->tnpc
[env
->tl
] = env
->npc
;
1420 env
->tt
[env
->tl
] = intno
;
1421 change_pstate(PS_PEF
| PS_PRIV
| PS_AG
);
1423 if (intno
== TT_CLRWIN
)
1424 set_cwp((env
->cwp
- 1) & (NWINDOWS
- 1));
1425 else if ((intno
& 0x1c0) == TT_SPILL
)
1426 set_cwp((env
->cwp
- env
->cansave
- 2) & (NWINDOWS
- 1));
1427 else if ((intno
& 0x1c0) == TT_FILL
)
1428 set_cwp((env
->cwp
+ 1) & (NWINDOWS
- 1));
1429 env
->tbr
&= ~0x7fffULL
;
1430 env
->tbr
|= ((env
->tl
> 1) ? 1 << 14 : 0) | (intno
<< 5);
1431 if (env
->tl
< MAXTL
- 1) {
1434 env
->pstate
|= PS_RED
;
1435 if (env
->tl
!= MAXTL
)
1439 env
->npc
= env
->pc
+ 4;
1440 env
->exception_index
= 0;
1443 void do_interrupt(int intno
)
1448 if (loglevel
& CPU_LOG_INT
) {
1450 fprintf(logfile
, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
1453 env
->npc
, env
->regwptr
[6]);
1454 cpu_dump_state(env
, logfile
, fprintf
, 0);
1460 fprintf(logfile
, " code=");
1461 ptr
= (uint8_t *)env
->pc
;
1462 for(i
= 0; i
< 16; i
++) {
1463 fprintf(logfile
, " %02x", ldub(ptr
+ i
));
1465 fprintf(logfile
, "\n");
1471 #if !defined(CONFIG_USER_ONLY)
1472 if (env
->psret
== 0) {
1473 cpu_abort(env
, "Trap 0x%02x while interrupts disabled, Error state", env
->exception_index
);
1478 cwp
= (env
->cwp
- 1) & (NWINDOWS
- 1);
1480 env
->regwptr
[9] = env
->pc
;
1481 env
->regwptr
[10] = env
->npc
;
1482 env
->psrps
= env
->psrs
;
1484 env
->tbr
= (env
->tbr
& TBR_BASE_MASK
) | (intno
<< 4);
1486 env
->npc
= env
->pc
+ 4;
1487 env
->exception_index
= 0;
1491 #if !defined(CONFIG_USER_ONLY)
1493 static void do_unaligned_access(target_ulong addr
, int is_write
, int is_user
,
1496 #define MMUSUFFIX _mmu
1497 #define ALIGNED_ONLY
1498 #define GETPC() (__builtin_return_address(0))
1501 #include "softmmu_template.h"
1504 #include "softmmu_template.h"
1507 #include "softmmu_template.h"
1510 #include "softmmu_template.h"
1512 static void do_unaligned_access(target_ulong addr
, int is_write
, int is_user
,
1515 #ifdef DEBUG_UNALIGNED
1516 printf("Unaligned access to 0x%x from 0x%x\n", addr
, env
->pc
);
1518 raise_exception(TT_UNALIGNED
);
1521 /* try to fill the TLB and return an exception if error. If retaddr is
1522 NULL, it means that the function was called in C code (i.e. not
1523 from generated code or from helper.c) */
1524 /* XXX: fix it to restore all registers */
1525 void tlb_fill(target_ulong addr
, int is_write
, int is_user
, void *retaddr
)
1527 TranslationBlock
*tb
;
1530 CPUState
*saved_env
;
1532 /* XXX: hack to restore env in all cases, even if not called from
1535 env
= cpu_single_env
;
1537 ret
= cpu_sparc_handle_mmu_fault(env
, addr
, is_write
, is_user
, 1);
1540 /* now we have a real cpu fault */
1541 pc
= (unsigned long)retaddr
;
1542 tb
= tb_find_pc(pc
);
1544 /* the PC is inside the translated code. It means that we have
1545 a virtual CPU fault */
1546 cpu_restore_state(tb
, env
, pc
, (void *)T2
);
1556 #ifndef TARGET_SPARC64
1557 void do_unassigned_access(target_phys_addr_t addr
, int is_write
, int is_exec
,
1560 CPUState
*saved_env
;
1562 /* XXX: hack to restore env in all cases, even if not called from
1565 env
= cpu_single_env
;
1566 if (env
->mmuregs
[3]) /* Fault status register */
1567 env
->mmuregs
[3] = 1; /* overflow (not read before another fault) */
1569 env
->mmuregs
[3] |= 1 << 16;
1571 env
->mmuregs
[3] |= 1 << 5;
1573 env
->mmuregs
[3] |= 1 << 6;
1575 env
->mmuregs
[3] |= 1 << 7;
1576 env
->mmuregs
[3] |= (5 << 2) | 2;
1577 env
->mmuregs
[4] = addr
; /* Fault address register */
1578 if ((env
->mmuregs
[0] & MMU_E
) && !(env
->mmuregs
[0] & MMU_NF
)) {
1579 #ifdef DEBUG_UNASSIGNED
1580 printf("Unassigned mem access to " TARGET_FMT_plx
" from " TARGET_FMT_lx
1581 "\n", addr
, env
->pc
);
1584 raise_exception(TT_CODE_ACCESS
);
1586 raise_exception(TT_DATA_ACCESS
);
1591 void do_unassigned_access(target_phys_addr_t addr
, int is_write
, int is_exec
,
1594 #ifdef DEBUG_UNASSIGNED
1595 CPUState
*saved_env
;
1597 /* XXX: hack to restore env in all cases, even if not called from
1600 env
= cpu_single_env
;
1601 printf("Unassigned mem access to " TARGET_FMT_plx
" from " TARGET_FMT_lx
"\n",
1606 raise_exception(TT_CODE_ACCESS
);
1608 raise_exception(TT_DATA_ACCESS
);
1612 #ifdef TARGET_SPARC64
1613 void do_tick_set_count(void *opaque
, uint64_t count
)
1615 #if !defined(CONFIG_USER_ONLY)
1616 ptimer_set_count(opaque
, -count
);
1620 uint64_t do_tick_get_count(void *opaque
)
1622 #if !defined(CONFIG_USER_ONLY)
1623 return -ptimer_get_count(opaque
);
1629 void do_tick_set_limit(void *opaque
, uint64_t limit
)
1631 #if !defined(CONFIG_USER_ONLY)
1632 ptimer_set_limit(opaque
, -limit
, 0);