|
|
1.1 root 1: #include "exec.h"
1.1.1.5 root 2: #include "host-utils.h"
1.1.1.6 root 3: #include "helper.h"
4: #if !defined(CONFIG_USER_ONLY)
5: #include "softmmu_exec.h"
6: #endif /* !defined(CONFIG_USER_ONLY) */
1.1 root 7:
8: //#define DEBUG_MMU
1.1.1.5 root 9: //#define DEBUG_MXCC
10: //#define DEBUG_UNALIGNED
11: //#define DEBUG_UNASSIGNED
12: //#define DEBUG_ASI
1.1.1.6 root 13: //#define DEBUG_PCALL
1.1.1.5 root 14:
15: #ifdef DEBUG_MMU
1.1.1.7 root 16: #define DPRINTF_MMU(fmt, ...) \
17: do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0)
1.1.1.5 root 18: #else
1.1.1.7 root 19: #define DPRINTF_MMU(fmt, ...) do {} while (0)
1.1.1.5 root 20: #endif
21:
22: #ifdef DEBUG_MXCC
1.1.1.7 root 23: #define DPRINTF_MXCC(fmt, ...) \
24: do { printf("MXCC: " fmt , ## __VA_ARGS__); } while (0)
1.1.1.5 root 25: #else
1.1.1.7 root 26: #define DPRINTF_MXCC(fmt, ...) do {} while (0)
1.1.1.5 root 27: #endif
28:
29: #ifdef DEBUG_ASI
1.1.1.7 root 30: #define DPRINTF_ASI(fmt, ...) \
31: do { printf("ASI: " fmt , ## __VA_ARGS__); } while (0)
1.1.1.6 root 32: #endif
33:
34: #ifdef TARGET_SPARC64
35: #ifndef TARGET_ABI32
36: #define AM_CHECK(env1) ((env1)->pstate & PS_AM)
37: #else
38: #define AM_CHECK(env1) (1)
39: #endif
1.1.1.5 root 40: #endif
1.1 root 41:
1.1.1.7 root 42: #if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
43: // Calculates TSB pointer value for fault page size 8k or 64k
44: static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
45: uint64_t tag_access_register,
46: int page_size)
47: {
48: uint64_t tsb_base = tsb_register & ~0x1fffULL;
1.1.1.8 ! root 49: int tsb_split = (tsb_register & 0x1000ULL) ? 1 : 0;
! 50: int tsb_size = tsb_register & 0xf;
1.1.1.7 root 51:
52: // discard lower 13 bits which hold tag access context
53: uint64_t tag_access_va = tag_access_register & ~0x1fffULL;
54:
55: // now reorder bits
56: uint64_t tsb_base_mask = ~0x1fffULL;
57: uint64_t va = tag_access_va;
58:
59: // move va bits to correct position
60: if (page_size == 8*1024) {
61: va >>= 9;
62: } else if (page_size == 64*1024) {
63: va >>= 12;
64: }
65:
66: if (tsb_size) {
67: tsb_base_mask <<= tsb_size;
68: }
69:
70: // calculate tsb_base mask and adjust va if split is in use
71: if (tsb_split) {
72: if (page_size == 8*1024) {
73: va &= ~(1ULL << (13 + tsb_size));
74: } else if (page_size == 64*1024) {
75: va |= (1ULL << (13 + tsb_size));
76: }
77: tsb_base_mask <<= 1;
78: }
79:
80: return ((tsb_base & tsb_base_mask) | (va & ~tsb_base_mask)) & ~0xfULL;
81: }
82:
83: // Calculates tag target register value by reordering bits
84: // in tag access register
85: static uint64_t ultrasparc_tag_target(uint64_t tag_access_register)
86: {
87: return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 22);
88: }
89:
1.1.1.8 ! root 90: static void replace_tlb_entry(SparcTLBEntry *tlb,
! 91: uint64_t tlb_tag, uint64_t tlb_tte,
! 92: CPUState *env1)
! 93: {
! 94: target_ulong mask, size, va, offset;
! 95:
! 96: // flush page range if translation is valid
! 97: if (TTE_IS_VALID(tlb->tte)) {
! 98:
! 99: mask = 0xffffffffffffe000ULL;
! 100: mask <<= 3 * ((tlb->tte >> 61) & 3);
! 101: size = ~mask + 1;
! 102:
! 103: va = tlb->tag & mask;
! 104:
! 105: for (offset = 0; offset < size; offset += TARGET_PAGE_SIZE) {
! 106: tlb_flush_page(env1, va + offset);
! 107: }
! 108: }
! 109:
! 110: tlb->tag = tlb_tag;
! 111: tlb->tte = tlb_tte;
! 112: }
! 113:
! 114: static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
! 115: const char* strmmu, CPUState *env1)
! 116: {
! 117: unsigned int i;
! 118: target_ulong mask;
! 119:
! 120: for (i = 0; i < 64; i++) {
! 121: if (TTE_IS_VALID(tlb[i].tte)) {
! 122:
! 123: mask = 0xffffffffffffe000ULL;
! 124: mask <<= 3 * ((tlb[i].tte >> 61) & 3);
! 125:
! 126: if ((demap_addr & mask) == (tlb[i].tag & mask)) {
! 127: replace_tlb_entry(&tlb[i], 0, 0, env1);
! 128: #ifdef DEBUG_MMU
! 129: DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
! 130: dump_mmu(env1);
! 131: #endif
! 132: }
! 133: //return;
! 134: }
! 135: }
! 136:
! 137: }
! 138:
! 139: static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
! 140: uint64_t tlb_tag, uint64_t tlb_tte,
! 141: const char* strmmu, CPUState *env1)
! 142: {
! 143: unsigned int i, replace_used;
! 144:
! 145: // Try replacing invalid entry
! 146: for (i = 0; i < 64; i++) {
! 147: if (!TTE_IS_VALID(tlb[i].tte)) {
! 148: replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
! 149: #ifdef DEBUG_MMU
! 150: DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i);
! 151: dump_mmu(env1);
! 152: #endif
! 153: return;
! 154: }
! 155: }
! 156:
! 157: // All entries are valid, try replacing unlocked entry
! 158:
! 159: for (replace_used = 0; replace_used < 2; ++replace_used) {
! 160:
! 161: // Used entries are not replaced on first pass
! 162:
! 163: for (i = 0; i < 64; i++) {
! 164: if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) {
! 165:
! 166: replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
! 167: #ifdef DEBUG_MMU
! 168: DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
! 169: strmmu, (replace_used?"used":"unused"), i);
! 170: dump_mmu(env1);
! 171: #endif
! 172: return;
! 173: }
! 174: }
! 175:
! 176: // Now reset used bit and search for unused entries again
! 177:
! 178: for (i = 0; i < 64; i++) {
! 179: TTE_SET_UNUSED(tlb[i].tte);
! 180: }
! 181: }
! 182:
! 183: #ifdef DEBUG_MMU
! 184: DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu);
! 185: #endif
! 186: // error state?
! 187: }
! 188:
1.1.1.7 root 189: #endif
190:
1.1.1.6 root 191: static inline void address_mask(CPUState *env1, target_ulong *addr)
192: {
193: #ifdef TARGET_SPARC64
194: if (AM_CHECK(env1))
195: *addr &= 0xffffffffULL;
196: #endif
197: }
198:
199: static void raise_exception(int tt)
1.1 root 200: {
201: env->exception_index = tt;
202: cpu_loop_exit();
1.1.1.5 root 203: }
204:
1.1.1.6 root 205: void HELPER(raise_exception)(int tt)
1.1.1.5 root 206: {
1.1.1.6 root 207: raise_exception(tt);
208: }
1.1.1.5 root 209:
1.1.1.6 root 210: static inline void set_cwp(int new_cwp)
211: {
212: cpu_set_cwp(env, new_cwp);
1.1.1.5 root 213: }
1.1 root 214:
1.1.1.6 root 215: void helper_check_align(target_ulong addr, uint32_t align)
1.1 root 216: {
1.1.1.6 root 217: if (addr & align) {
218: #ifdef DEBUG_UNALIGNED
219: printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
220: "\n", addr, env->pc);
221: #endif
222: raise_exception(TT_UNALIGNED);
223: }
224: }
225:
226: #define F_HELPER(name, p) void helper_f##name##p(void)
227:
228: #define F_BINOP(name) \
229: float32 helper_f ## name ## s (float32 src1, float32 src2) \
230: { \
231: return float32_ ## name (src1, src2, &env->fp_status); \
232: } \
233: F_HELPER(name, d) \
234: { \
235: DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
236: } \
237: F_HELPER(name, q) \
238: { \
239: QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \
240: }
241:
242: F_BINOP(add);
243: F_BINOP(sub);
244: F_BINOP(mul);
245: F_BINOP(div);
246: #undef F_BINOP
247:
248: void helper_fsmuld(float32 src1, float32 src2)
249: {
250: DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
251: float32_to_float64(src2, &env->fp_status),
252: &env->fp_status);
253: }
254:
255: void helper_fdmulq(void)
256: {
257: QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
258: float64_to_float128(DT1, &env->fp_status),
259: &env->fp_status);
260: }
261:
262: float32 helper_fnegs(float32 src)
263: {
264: return float32_chs(src);
1.1 root 265: }
266:
1.1.1.6 root 267: #ifdef TARGET_SPARC64
268: F_HELPER(neg, d)
1.1 root 269: {
1.1.1.6 root 270: DT0 = float64_chs(DT1);
1.1 root 271: }
1.1.1.5 root 272:
1.1.1.6 root 273: F_HELPER(neg, q)
1.1.1.5 root 274: {
1.1.1.6 root 275: QT0 = float128_chs(QT1);
1.1.1.5 root 276: }
277: #endif
278:
1.1.1.6 root 279: /* Integer to float conversion. */
280: float32 helper_fitos(int32_t src)
281: {
282: return int32_to_float32(src, &env->fp_status);
283: }
284:
285: void helper_fitod(int32_t src)
286: {
287: DT0 = int32_to_float64(src, &env->fp_status);
288: }
289:
290: void helper_fitoq(int32_t src)
291: {
292: QT0 = int32_to_float128(src, &env->fp_status);
293: }
294:
1.1.1.5 root 295: #ifdef TARGET_SPARC64
1.1.1.6 root 296: float32 helper_fxtos(void)
1.1.1.5 root 297: {
1.1.1.6 root 298: return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
1.1.1.5 root 299: }
300:
1.1.1.6 root 301: F_HELPER(xto, d)
1.1.1.5 root 302: {
303: DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
304: }
305:
1.1.1.6 root 306: F_HELPER(xto, q)
1.1.1.5 root 307: {
1.1.1.6 root 308: QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
1.1.1.5 root 309: }
310: #endif
1.1.1.6 root 311: #undef F_HELPER
312:
313: /* floating point conversion */
314: float32 helper_fdtos(void)
315: {
316: return float64_to_float32(DT1, &env->fp_status);
317: }
318:
319: void helper_fstod(float32 src)
320: {
321: DT0 = float32_to_float64(src, &env->fp_status);
322: }
323:
324: float32 helper_fqtos(void)
325: {
326: return float128_to_float32(QT1, &env->fp_status);
327: }
328:
329: void helper_fstoq(float32 src)
330: {
331: QT0 = float32_to_float128(src, &env->fp_status);
332: }
333:
334: void helper_fqtod(void)
335: {
336: DT0 = float128_to_float64(QT1, &env->fp_status);
337: }
338:
339: void helper_fdtoq(void)
340: {
341: QT0 = float64_to_float128(DT1, &env->fp_status);
342: }
343:
344: /* Float to integer conversion. */
345: int32_t helper_fstoi(float32 src)
346: {
347: return float32_to_int32_round_to_zero(src, &env->fp_status);
348: }
349:
350: int32_t helper_fdtoi(void)
351: {
352: return float64_to_int32_round_to_zero(DT1, &env->fp_status);
353: }
354:
355: int32_t helper_fqtoi(void)
356: {
357: return float128_to_int32_round_to_zero(QT1, &env->fp_status);
358: }
359:
360: #ifdef TARGET_SPARC64
361: void helper_fstox(float32 src)
362: {
363: *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
364: }
365:
366: void helper_fdtox(void)
367: {
368: *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
369: }
370:
371: void helper_fqtox(void)
372: {
373: *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
374: }
375:
376: void helper_faligndata(void)
377: {
378: uint64_t tmp;
379:
380: tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
381: /* on many architectures a shift of 64 does nothing */
382: if ((env->gsr & 7) != 0) {
383: tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
384: }
385: *((uint64_t *)&DT0) = tmp;
386: }
387:
1.1.1.8 ! root 388: #ifdef HOST_WORDS_BIGENDIAN
1.1.1.6 root 389: #define VIS_B64(n) b[7 - (n)]
390: #define VIS_W64(n) w[3 - (n)]
391: #define VIS_SW64(n) sw[3 - (n)]
392: #define VIS_L64(n) l[1 - (n)]
393: #define VIS_B32(n) b[3 - (n)]
394: #define VIS_W32(n) w[1 - (n)]
395: #else
396: #define VIS_B64(n) b[n]
397: #define VIS_W64(n) w[n]
398: #define VIS_SW64(n) sw[n]
399: #define VIS_L64(n) l[n]
400: #define VIS_B32(n) b[n]
401: #define VIS_W32(n) w[n]
402: #endif
403:
404: typedef union {
405: uint8_t b[8];
406: uint16_t w[4];
407: int16_t sw[4];
408: uint32_t l[2];
409: float64 d;
410: } vis64;
411:
412: typedef union {
413: uint8_t b[4];
414: uint16_t w[2];
415: uint32_t l;
416: float32 f;
417: } vis32;
418:
419: void helper_fpmerge(void)
420: {
421: vis64 s, d;
422:
423: s.d = DT0;
424: d.d = DT1;
425:
426: // Reverse calculation order to handle overlap
427: d.VIS_B64(7) = s.VIS_B64(3);
428: d.VIS_B64(6) = d.VIS_B64(3);
429: d.VIS_B64(5) = s.VIS_B64(2);
430: d.VIS_B64(4) = d.VIS_B64(2);
431: d.VIS_B64(3) = s.VIS_B64(1);
432: d.VIS_B64(2) = d.VIS_B64(1);
433: d.VIS_B64(1) = s.VIS_B64(0);
434: //d.VIS_B64(0) = d.VIS_B64(0);
435:
436: DT0 = d.d;
437: }
438:
439: void helper_fmul8x16(void)
440: {
441: vis64 s, d;
442: uint32_t tmp;
443:
444: s.d = DT0;
445: d.d = DT1;
446:
447: #define PMUL(r) \
448: tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r); \
449: if ((tmp & 0xff) > 0x7f) \
450: tmp += 0x100; \
451: d.VIS_W64(r) = tmp >> 8;
452:
453: PMUL(0);
454: PMUL(1);
455: PMUL(2);
456: PMUL(3);
457: #undef PMUL
458:
459: DT0 = d.d;
460: }
461:
462: void helper_fmul8x16al(void)
463: {
464: vis64 s, d;
465: uint32_t tmp;
466:
467: s.d = DT0;
468: d.d = DT1;
469:
470: #define PMUL(r) \
471: tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r); \
472: if ((tmp & 0xff) > 0x7f) \
473: tmp += 0x100; \
474: d.VIS_W64(r) = tmp >> 8;
475:
476: PMUL(0);
477: PMUL(1);
478: PMUL(2);
479: PMUL(3);
480: #undef PMUL
481:
482: DT0 = d.d;
483: }
484:
485: void helper_fmul8x16au(void)
486: {
487: vis64 s, d;
488: uint32_t tmp;
489:
490: s.d = DT0;
491: d.d = DT1;
492:
493: #define PMUL(r) \
494: tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r); \
495: if ((tmp & 0xff) > 0x7f) \
496: tmp += 0x100; \
497: d.VIS_W64(r) = tmp >> 8;
498:
499: PMUL(0);
500: PMUL(1);
501: PMUL(2);
502: PMUL(3);
503: #undef PMUL
504:
505: DT0 = d.d;
506: }
507:
508: void helper_fmul8sux16(void)
509: {
510: vis64 s, d;
511: uint32_t tmp;
512:
513: s.d = DT0;
514: d.d = DT1;
515:
516: #define PMUL(r) \
517: tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
518: if ((tmp & 0xff) > 0x7f) \
519: tmp += 0x100; \
520: d.VIS_W64(r) = tmp >> 8;
521:
522: PMUL(0);
523: PMUL(1);
524: PMUL(2);
525: PMUL(3);
526: #undef PMUL
527:
528: DT0 = d.d;
529: }
530:
531: void helper_fmul8ulx16(void)
532: {
533: vis64 s, d;
534: uint32_t tmp;
535:
536: s.d = DT0;
537: d.d = DT1;
538:
539: #define PMUL(r) \
540: tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
541: if ((tmp & 0xff) > 0x7f) \
542: tmp += 0x100; \
543: d.VIS_W64(r) = tmp >> 8;
544:
545: PMUL(0);
546: PMUL(1);
547: PMUL(2);
548: PMUL(3);
549: #undef PMUL
550:
551: DT0 = d.d;
552: }
553:
554: void helper_fmuld8sux16(void)
555: {
556: vis64 s, d;
557: uint32_t tmp;
558:
559: s.d = DT0;
560: d.d = DT1;
561:
562: #define PMUL(r) \
563: tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
564: if ((tmp & 0xff) > 0x7f) \
565: tmp += 0x100; \
566: d.VIS_L64(r) = tmp;
567:
568: // Reverse calculation order to handle overlap
569: PMUL(1);
570: PMUL(0);
571: #undef PMUL
572:
573: DT0 = d.d;
574: }
575:
576: void helper_fmuld8ulx16(void)
577: {
578: vis64 s, d;
579: uint32_t tmp;
580:
581: s.d = DT0;
582: d.d = DT1;
583:
584: #define PMUL(r) \
585: tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
586: if ((tmp & 0xff) > 0x7f) \
587: tmp += 0x100; \
588: d.VIS_L64(r) = tmp;
589:
590: // Reverse calculation order to handle overlap
591: PMUL(1);
592: PMUL(0);
593: #undef PMUL
594:
595: DT0 = d.d;
596: }
597:
598: void helper_fexpand(void)
599: {
600: vis32 s;
601: vis64 d;
602:
603: s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
604: d.d = DT1;
605: d.VIS_W64(0) = s.VIS_B32(0) << 4;
606: d.VIS_W64(1) = s.VIS_B32(1) << 4;
607: d.VIS_W64(2) = s.VIS_B32(2) << 4;
608: d.VIS_W64(3) = s.VIS_B32(3) << 4;
609:
610: DT0 = d.d;
611: }
612:
613: #define VIS_HELPER(name, F) \
614: void name##16(void) \
615: { \
616: vis64 s, d; \
617: \
618: s.d = DT0; \
619: d.d = DT1; \
620: \
621: d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0)); \
622: d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1)); \
623: d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2)); \
624: d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3)); \
625: \
626: DT0 = d.d; \
627: } \
628: \
629: uint32_t name##16s(uint32_t src1, uint32_t src2) \
630: { \
631: vis32 s, d; \
632: \
633: s.l = src1; \
634: d.l = src2; \
635: \
636: d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0)); \
637: d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1)); \
638: \
639: return d.l; \
640: } \
641: \
642: void name##32(void) \
643: { \
644: vis64 s, d; \
645: \
646: s.d = DT0; \
647: d.d = DT1; \
648: \
649: d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0)); \
650: d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1)); \
651: \
652: DT0 = d.d; \
653: } \
654: \
655: uint32_t name##32s(uint32_t src1, uint32_t src2) \
656: { \
657: vis32 s, d; \
658: \
659: s.l = src1; \
660: d.l = src2; \
661: \
662: d.l = F(d.l, s.l); \
663: \
664: return d.l; \
665: }
666:
667: #define FADD(a, b) ((a) + (b))
668: #define FSUB(a, b) ((a) - (b))
669: VIS_HELPER(helper_fpadd, FADD)
670: VIS_HELPER(helper_fpsub, FSUB)
671:
672: #define VIS_CMPHELPER(name, F) \
673: void name##16(void) \
674: { \
675: vis64 s, d; \
676: \
677: s.d = DT0; \
678: d.d = DT1; \
679: \
680: d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0; \
681: d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0; \
682: d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0; \
683: d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0; \
684: \
685: DT0 = d.d; \
686: } \
687: \
688: void name##32(void) \
689: { \
690: vis64 s, d; \
691: \
692: s.d = DT0; \
693: d.d = DT1; \
694: \
695: d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0; \
696: d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0; \
697: \
698: DT0 = d.d; \
699: }
700:
701: #define FCMPGT(a, b) ((a) > (b))
702: #define FCMPEQ(a, b) ((a) == (b))
703: #define FCMPLE(a, b) ((a) <= (b))
704: #define FCMPNE(a, b) ((a) != (b))
705:
706: VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
707: VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
708: VIS_CMPHELPER(helper_fcmple, FCMPLE)
709: VIS_CMPHELPER(helper_fcmpne, FCMPNE)
1.1.1.5 root 710: #endif
1.1 root 711:
1.1.1.6 root 712: void helper_check_ieee_exceptions(void)
713: {
714: target_ulong status;
715:
716: status = get_float_exception_flags(&env->fp_status);
717: if (status) {
718: /* Copy IEEE 754 flags into FSR */
719: if (status & float_flag_invalid)
720: env->fsr |= FSR_NVC;
721: if (status & float_flag_overflow)
722: env->fsr |= FSR_OFC;
723: if (status & float_flag_underflow)
724: env->fsr |= FSR_UFC;
725: if (status & float_flag_divbyzero)
726: env->fsr |= FSR_DZC;
727: if (status & float_flag_inexact)
728: env->fsr |= FSR_NXC;
729:
730: if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
731: /* Unmasked exception, generate a trap */
732: env->fsr |= FSR_FTT_IEEE_EXCP;
733: raise_exception(TT_FP_EXCP);
734: } else {
735: /* Accumulate exceptions */
736: env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
737: }
738: }
739: }
740:
741: void helper_clear_float_exceptions(void)
742: {
743: set_float_exception_flags(0, &env->fp_status);
744: }
745:
746: float32 helper_fabss(float32 src)
1.1 root 747: {
1.1.1.6 root 748: return float32_abs(src);
1.1 root 749: }
750:
751: #ifdef TARGET_SPARC64
1.1.1.6 root 752: void helper_fabsd(void)
1.1 root 753: {
754: DT0 = float64_abs(DT1);
755: }
1.1.1.5 root 756:
1.1.1.6 root 757: void helper_fabsq(void)
1.1.1.5 root 758: {
759: QT0 = float128_abs(QT1);
760: }
761: #endif
1.1 root 762:
1.1.1.6 root 763: float32 helper_fsqrts(float32 src)
1.1 root 764: {
1.1.1.6 root 765: return float32_sqrt(src, &env->fp_status);
1.1 root 766: }
767:
1.1.1.6 root 768: void helper_fsqrtd(void)
1.1 root 769: {
770: DT0 = float64_sqrt(DT1, &env->fp_status);
771: }
772:
1.1.1.6 root 773: void helper_fsqrtq(void)
1.1.1.5 root 774: {
775: QT0 = float128_sqrt(QT1, &env->fp_status);
776: }
777:
778: #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
1.1.1.6 root 779: void glue(helper_, name) (void) \
1.1.1.3 root 780: { \
1.1.1.6 root 781: target_ulong new_fsr; \
782: \
1.1.1.3 root 783: env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
784: switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
785: case float_relation_unordered: \
1.1.1.6 root 786: new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
787: if ((env->fsr & FSR_NVM) || TRAP) { \
788: env->fsr |= new_fsr; \
789: env->fsr |= FSR_NVC; \
790: env->fsr |= FSR_FTT_IEEE_EXCP; \
791: raise_exception(TT_FP_EXCP); \
792: } else { \
793: env->fsr |= FSR_NVA; \
794: } \
795: break; \
796: case float_relation_less: \
797: new_fsr = FSR_FCC0 << FS; \
798: break; \
799: case float_relation_greater: \
800: new_fsr = FSR_FCC1 << FS; \
801: break; \
802: default: \
803: new_fsr = 0; \
804: break; \
805: } \
806: env->fsr |= new_fsr; \
807: }
808: #define GEN_FCMPS(name, size, FS, TRAP) \
809: void glue(helper_, name)(float32 src1, float32 src2) \
810: { \
811: target_ulong new_fsr; \
812: \
813: env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
814: switch (glue(size, _compare) (src1, src2, &env->fp_status)) { \
815: case float_relation_unordered: \
816: new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
1.1.1.5 root 817: if ((env->fsr & FSR_NVM) || TRAP) { \
1.1.1.6 root 818: env->fsr |= new_fsr; \
1.1.1.5 root 819: env->fsr |= FSR_NVC; \
820: env->fsr |= FSR_FTT_IEEE_EXCP; \
1.1.1.3 root 821: raise_exception(TT_FP_EXCP); \
822: } else { \
823: env->fsr |= FSR_NVA; \
824: } \
825: break; \
826: case float_relation_less: \
1.1.1.6 root 827: new_fsr = FSR_FCC0 << FS; \
1.1.1.3 root 828: break; \
829: case float_relation_greater: \
1.1.1.6 root 830: new_fsr = FSR_FCC1 << FS; \
1.1.1.3 root 831: break; \
832: default: \
1.1.1.6 root 833: new_fsr = 0; \
1.1.1.3 root 834: break; \
835: } \
1.1.1.6 root 836: env->fsr |= new_fsr; \
1.1 root 837: }
838:
1.1.1.6 root 839: GEN_FCMPS(fcmps, float32, 0, 0);
1.1.1.5 root 840: GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
841:
1.1.1.6 root 842: GEN_FCMPS(fcmpes, float32, 0, 1);
1.1.1.5 root 843: GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
844:
845: GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
846: GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
1.1 root 847:
1.1.1.7 root 848: static uint32_t compute_all_flags(void)
849: {
850: return env->psr & PSR_ICC;
851: }
852:
853: static uint32_t compute_C_flags(void)
854: {
855: return env->psr & PSR_CARRY;
856: }
857:
858: static inline uint32_t get_NZ_icc(target_ulong dst)
859: {
860: uint32_t ret = 0;
861:
862: if (!(dst & 0xffffffffULL))
863: ret |= PSR_ZERO;
864: if ((int32_t) (dst & 0xffffffffULL) < 0)
865: ret |= PSR_NEG;
866: return ret;
867: }
868:
869: #ifdef TARGET_SPARC64
870: static uint32_t compute_all_flags_xcc(void)
871: {
872: return env->xcc & PSR_ICC;
873: }
874:
875: static uint32_t compute_C_flags_xcc(void)
876: {
877: return env->xcc & PSR_CARRY;
878: }
879:
880: static inline uint32_t get_NZ_xcc(target_ulong dst)
881: {
882: uint32_t ret = 0;
883:
884: if (!dst)
885: ret |= PSR_ZERO;
886: if ((int64_t)dst < 0)
887: ret |= PSR_NEG;
888: return ret;
889: }
890: #endif
891:
892: static inline uint32_t get_V_div_icc(target_ulong src2)
893: {
894: uint32_t ret = 0;
895:
896: if (src2 != 0)
897: ret |= PSR_OVF;
898: return ret;
899: }
900:
901: static uint32_t compute_all_div(void)
902: {
903: uint32_t ret;
904:
905: ret = get_NZ_icc(CC_DST);
906: ret |= get_V_div_icc(CC_SRC2);
907: return ret;
908: }
909:
910: static uint32_t compute_C_div(void)
911: {
912: return 0;
913: }
914:
1.1.1.8 ! root 915: /* carry = (src1[31] & src2[31]) | ( ~dst[31] & (src1[31] | src2[31])) */
! 916: static inline uint32_t get_C_add_icc(target_ulong dst, target_ulong src1,
! 917: target_ulong src2)
1.1.1.7 root 918: {
919: uint32_t ret = 0;
920:
1.1.1.8 ! root 921: if (((src1 & (1ULL << 31)) & (src2 & (1ULL << 31)))
! 922: | ((~(dst & (1ULL << 31)))
! 923: & ((src1 & (1ULL << 31)) | (src2 & (1ULL << 31)))))
1.1.1.7 root 924: ret |= PSR_CARRY;
925: return ret;
926: }
927:
928: static inline uint32_t get_V_add_icc(target_ulong dst, target_ulong src1,
929: target_ulong src2)
930: {
931: uint32_t ret = 0;
932:
933: if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 31))
934: ret |= PSR_OVF;
935: return ret;
936: }
937:
938: #ifdef TARGET_SPARC64
939: static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
940: {
941: uint32_t ret = 0;
942:
943: if (dst < src1)
944: ret |= PSR_CARRY;
945: return ret;
946: }
947:
948: static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
949: target_ulong src2)
950: {
951: uint32_t ret = 0;
952:
953: if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63))
954: ret |= PSR_OVF;
955: return ret;
956: }
957:
958: static uint32_t compute_all_add_xcc(void)
959: {
960: uint32_t ret;
961:
962: ret = get_NZ_xcc(CC_DST);
963: ret |= get_C_add_xcc(CC_DST, CC_SRC);
964: ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
965: return ret;
966: }
967:
968: static uint32_t compute_C_add_xcc(void)
969: {
970: return get_C_add_xcc(CC_DST, CC_SRC);
971: }
972: #endif
973:
1.1.1.8 ! root 974: static uint32_t compute_all_add(void)
1.1.1.7 root 975: {
976: uint32_t ret;
977:
978: ret = get_NZ_icc(CC_DST);
1.1.1.8 ! root 979: ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1.1.1.7 root 980: ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
981: return ret;
982: }
983:
1.1.1.8 ! root 984: static uint32_t compute_C_add(void)
1.1.1.7 root 985: {
1.1.1.8 ! root 986: return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1.1.1.7 root 987: }
988:
989: #ifdef TARGET_SPARC64
990: static uint32_t compute_all_addx_xcc(void)
991: {
992: uint32_t ret;
993:
994: ret = get_NZ_xcc(CC_DST);
995: ret |= get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
996: ret |= get_C_add_xcc(CC_DST, CC_SRC);
997: ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
998: return ret;
999: }
1000:
1001: static uint32_t compute_C_addx_xcc(void)
1002: {
1003: uint32_t ret;
1004:
1005: ret = get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
1006: ret |= get_C_add_xcc(CC_DST, CC_SRC);
1007: return ret;
1008: }
1009: #endif
1010:
1011: static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
1012: {
1013: uint32_t ret = 0;
1014:
1015: if ((src1 | src2) & 0x3)
1016: ret |= PSR_OVF;
1017: return ret;
1018: }
1019:
1020: static uint32_t compute_all_tadd(void)
1021: {
1022: uint32_t ret;
1023:
1024: ret = get_NZ_icc(CC_DST);
1.1.1.8 ! root 1025: ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1.1.1.7 root 1026: ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
1027: ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1028: return ret;
1029: }
1030:
1031: static uint32_t compute_C_tadd(void)
1032: {
1.1.1.8 ! root 1033: return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1.1.1.7 root 1034: }
1035:
1036: static uint32_t compute_all_taddtv(void)
1037: {
1038: uint32_t ret;
1039:
1040: ret = get_NZ_icc(CC_DST);
1.1.1.8 ! root 1041: ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1.1.1.7 root 1042: return ret;
1043: }
1044:
1045: static uint32_t compute_C_taddtv(void)
1046: {
1.1.1.8 ! root 1047: return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1.1.1.7 root 1048: }
1049:
1.1.1.8 ! root 1050: /* carry = (~src1[31] & src2[31]) | ( dst[31] & (~src1[31] | src2[31])) */
! 1051: static inline uint32_t get_C_sub_icc(target_ulong dst, target_ulong src1,
! 1052: target_ulong src2)
1.1.1.7 root 1053: {
1054: uint32_t ret = 0;
1055:
1.1.1.8 ! root 1056: if (((~(src1 & (1ULL << 31))) & (src2 & (1ULL << 31)))
! 1057: | ((dst & (1ULL << 31)) & (( ~(src1 & (1ULL << 31)))
! 1058: | (src2 & (1ULL << 31)))))
1.1.1.7 root 1059: ret |= PSR_CARRY;
1060: return ret;
1061: }
1062:
1063: static inline uint32_t get_V_sub_icc(target_ulong dst, target_ulong src1,
1064: target_ulong src2)
1065: {
1066: uint32_t ret = 0;
1067:
1068: if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 31))
1069: ret |= PSR_OVF;
1070: return ret;
1071: }
1072:
1073:
1074: #ifdef TARGET_SPARC64
1075: static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
1076: {
1077: uint32_t ret = 0;
1078:
1079: if (src1 < src2)
1080: ret |= PSR_CARRY;
1081: return ret;
1082: }
1083:
1084: static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
1085: target_ulong src2)
1086: {
1087: uint32_t ret = 0;
1088:
1089: if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63))
1090: ret |= PSR_OVF;
1091: return ret;
1092: }
1093:
1094: static uint32_t compute_all_sub_xcc(void)
1095: {
1096: uint32_t ret;
1097:
1098: ret = get_NZ_xcc(CC_DST);
1099: ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
1100: ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1101: return ret;
1102: }
1103:
1104: static uint32_t compute_C_sub_xcc(void)
1105: {
1106: return get_C_sub_xcc(CC_SRC, CC_SRC2);
1107: }
1108: #endif
1109:
1.1.1.8 ! root 1110: static uint32_t compute_all_sub(void)
1.1.1.7 root 1111: {
1112: uint32_t ret;
1113:
1114: ret = get_NZ_icc(CC_DST);
1.1.1.8 ! root 1115: ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1.1.1.7 root 1116: ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1117: return ret;
1118: }
1119:
1.1.1.8 ! root 1120: static uint32_t compute_C_sub(void)
1.1.1.7 root 1121: {
1.1.1.8 ! root 1122: return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1.1.1.7 root 1123: }
1124:
1125: #ifdef TARGET_SPARC64
1126: static uint32_t compute_all_subx_xcc(void)
1127: {
1128: uint32_t ret;
1129:
1130: ret = get_NZ_xcc(CC_DST);
1131: ret |= get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1132: ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1133: ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1134: return ret;
1135: }
1136:
1137: static uint32_t compute_C_subx_xcc(void)
1138: {
1139: uint32_t ret;
1140:
1141: ret = get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1142: ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1143: return ret;
1144: }
1145: #endif
1146:
1147: static uint32_t compute_all_tsub(void)
1148: {
1149: uint32_t ret;
1150:
1151: ret = get_NZ_icc(CC_DST);
1.1.1.8 ! root 1152: ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1.1.1.7 root 1153: ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1154: ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1155: return ret;
1156: }
1157:
1158: static uint32_t compute_C_tsub(void)
1159: {
1.1.1.8 ! root 1160: return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1.1.1.7 root 1161: }
1162:
1163: static uint32_t compute_all_tsubtv(void)
1164: {
1165: uint32_t ret;
1166:
1167: ret = get_NZ_icc(CC_DST);
1.1.1.8 ! root 1168: ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1.1.1.7 root 1169: return ret;
1170: }
1171:
1172: static uint32_t compute_C_tsubtv(void)
1173: {
1.1.1.8 ! root 1174: return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1.1.1.7 root 1175: }
1176:
1177: static uint32_t compute_all_logic(void)
1178: {
1179: return get_NZ_icc(CC_DST);
1180: }
1181:
1182: static uint32_t compute_C_logic(void)
1183: {
1184: return 0;
1185: }
1186:
1187: #ifdef TARGET_SPARC64
1188: static uint32_t compute_all_logic_xcc(void)
1189: {
1190: return get_NZ_xcc(CC_DST);
1191: }
1192: #endif
1193:
1194: typedef struct CCTable {
1195: uint32_t (*compute_all)(void); /* return all the flags */
1196: uint32_t (*compute_c)(void); /* return the C flag */
1197: } CCTable;
1198:
1199: static const CCTable icc_table[CC_OP_NB] = {
1200: /* CC_OP_DYNAMIC should never happen */
1201: [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
1202: [CC_OP_DIV] = { compute_all_div, compute_C_div },
1203: [CC_OP_ADD] = { compute_all_add, compute_C_add },
1.1.1.8 ! root 1204: [CC_OP_ADDX] = { compute_all_add, compute_C_add },
1.1.1.7 root 1205: [CC_OP_TADD] = { compute_all_tadd, compute_C_tadd },
1206: [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_taddtv },
1207: [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
1.1.1.8 ! root 1208: [CC_OP_SUBX] = { compute_all_sub, compute_C_sub },
1.1.1.7 root 1209: [CC_OP_TSUB] = { compute_all_tsub, compute_C_tsub },
1210: [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_tsubtv },
1211: [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
1212: };
1213:
1214: #ifdef TARGET_SPARC64
1215: static const CCTable xcc_table[CC_OP_NB] = {
1216: /* CC_OP_DYNAMIC should never happen */
1217: [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
1218: [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
1219: [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
1220: [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
1221: [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
1222: [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
1223: [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
1224: [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
1225: [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
1226: [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
1227: [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
1228: };
1229: #endif
1230:
1231: void helper_compute_psr(void)
1232: {
1233: uint32_t new_psr;
1234:
1235: new_psr = icc_table[CC_OP].compute_all();
1236: env->psr = new_psr;
1237: #ifdef TARGET_SPARC64
1238: new_psr = xcc_table[CC_OP].compute_all();
1239: env->xcc = new_psr;
1240: #endif
1241: CC_OP = CC_OP_FLAGS;
1242: }
1243:
1244: uint32_t helper_compute_C_icc(void)
1245: {
1246: uint32_t ret;
1247:
1248: ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
1249: return ret;
1250: }
1251:
1.1 root 1252: #ifdef TARGET_SPARC64
1.1.1.6 root 1253: GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
1.1.1.5 root 1254: GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
1.1.1.6 root 1255: GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
1.1 root 1256:
1.1.1.6 root 1257: GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
1.1.1.5 root 1258: GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
1.1.1.6 root 1259: GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
1.1 root 1260:
1.1.1.6 root 1261: GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
1.1.1.5 root 1262: GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
1.1.1.6 root 1263: GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
1.1.1.5 root 1264:
1.1.1.6 root 1265: GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
1.1.1.5 root 1266: GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
1.1.1.6 root 1267: GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
1.1.1.5 root 1268:
1.1.1.6 root 1269: GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
1.1.1.5 root 1270: GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
1.1.1.6 root 1271: GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
1.1.1.5 root 1272:
1.1.1.6 root 1273: GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
1.1.1.5 root 1274: GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
1275: GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
1276: #endif
1.1.1.6 root 1277: #undef GEN_FCMPS
1.1.1.5 root 1278:
1.1.1.6 root 1279: #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
1280: defined(DEBUG_MXCC)
1.1.1.5 root 1281: static void dump_mxcc(CPUState *env)
1.1.1.2 root 1282: {
1.1.1.7 root 1283: printf("mxccdata: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1284: "\n",
1.1.1.6 root 1285: env->mxccdata[0], env->mxccdata[1],
1286: env->mxccdata[2], env->mxccdata[3]);
1.1.1.7 root 1287: printf("mxccregs: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1288: "\n"
1289: " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1290: "\n",
1.1.1.6 root 1291: env->mxccregs[0], env->mxccregs[1],
1292: env->mxccregs[2], env->mxccregs[3],
1293: env->mxccregs[4], env->mxccregs[5],
1294: env->mxccregs[6], env->mxccregs[7]);
1.1.1.2 root 1295: }
1.1.1.5 root 1296: #endif
1.1.1.2 root 1297:
1.1.1.6 root 1298: #if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
1299: && defined(DEBUG_ASI)
1300: static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
1301: uint64_t r1)
1.1.1.5 root 1302: {
1303: switch (size)
1304: {
1305: case 1:
1.1.1.6 root 1306: DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
1307: addr, asi, r1 & 0xff);
1.1.1.5 root 1308: break;
1309: case 2:
1.1.1.6 root 1310: DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
1311: addr, asi, r1 & 0xffff);
1.1.1.5 root 1312: break;
1313: case 4:
1.1.1.6 root 1314: DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
1315: addr, asi, r1 & 0xffffffff);
1.1.1.5 root 1316: break;
1317: case 8:
1.1.1.6 root 1318: DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
1319: addr, asi, r1);
1.1.1.5 root 1320: break;
1321: }
1.1.1.2 root 1322: }
1.1.1.5 root 1323: #endif
1324:
1.1.1.6 root 1325: #ifndef TARGET_SPARC64
1326: #ifndef CONFIG_USER_ONLY
1327: uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1.1 root 1328: {
1.1.1.6 root 1329: uint64_t ret = 0;
1.1.1.5 root 1330: #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
1.1.1.6 root 1331: uint32_t last_addr = addr;
1.1.1.5 root 1332: #endif
1.1 root 1333:
1.1.1.6 root 1334: helper_check_align(addr, size - 1);
1.1 root 1335: switch (asi) {
1.1.1.5 root 1336: case 2: /* SuperSparc MXCC registers */
1.1.1.6 root 1337: switch (addr) {
1.1.1.5 root 1338: case 0x01c00a00: /* MXCC control register */
1.1.1.6 root 1339: if (size == 8)
1340: ret = env->mxccregs[3];
1341: else
1342: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1343: size);
1.1.1.5 root 1344: break;
1345: case 0x01c00a04: /* MXCC control register */
1346: if (size == 4)
1347: ret = env->mxccregs[3];
1348: else
1.1.1.6 root 1349: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1350: size);
1.1.1.5 root 1351: break;
1352: case 0x01c00c00: /* Module reset register */
1353: if (size == 8) {
1.1.1.6 root 1354: ret = env->mxccregs[5];
1.1.1.5 root 1355: // should we do something here?
1356: } else
1.1.1.6 root 1357: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1358: size);
1.1.1.5 root 1359: break;
1360: case 0x01c00f00: /* MBus port address register */
1.1.1.6 root 1361: if (size == 8)
1362: ret = env->mxccregs[7];
1363: else
1364: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1365: size);
1.1.1.5 root 1366: break;
1367: default:
1.1.1.6 root 1368: DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1369: size);
1.1.1.5 root 1370: break;
1371: }
1.1.1.6 root 1372: DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
1373: "addr = %08x -> ret = %" PRIx64 ","
1374: "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
1.1.1.5 root 1375: #ifdef DEBUG_MXCC
1376: dump_mxcc(env);
1377: #endif
1378: break;
1.1 root 1379: case 3: /* MMU probe */
1.1.1.5 root 1380: {
1381: int mmulev;
1.1 root 1382:
1.1.1.6 root 1383: mmulev = (addr >> 8) & 15;
1.1.1.5 root 1384: if (mmulev > 4)
1385: ret = 0;
1.1.1.6 root 1386: else
1387: ret = mmu_probe(env, addr, mmulev);
1388: DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
1389: addr, mmulev, ret);
1.1.1.5 root 1390: }
1391: break;
1.1 root 1392: case 4: /* read MMU regs */
1.1.1.5 root 1393: {
1.1.1.6 root 1394: int reg = (addr >> 8) & 0x1f;
1.1.1.5 root 1395:
1396: ret = env->mmuregs[reg];
1397: if (reg == 3) /* Fault status cleared on read */
1398: env->mmuregs[3] = 0;
1399: else if (reg == 0x13) /* Fault status read */
1400: ret = env->mmuregs[3];
1401: else if (reg == 0x14) /* Fault address read */
1402: ret = env->mmuregs[4];
1.1.1.6 root 1403: DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
1.1.1.5 root 1404: }
1405: break;
1406: case 5: // Turbosparc ITLB Diagnostic
1407: case 6: // Turbosparc DTLB Diagnostic
1408: case 7: // Turbosparc IOTLB Diagnostic
1409: break;
1410: case 9: /* Supervisor code access */
1411: switch(size) {
1412: case 1:
1.1.1.6 root 1413: ret = ldub_code(addr);
1.1.1.5 root 1414: break;
1415: case 2:
1.1.1.6 root 1416: ret = lduw_code(addr);
1.1.1.5 root 1417: break;
1418: default:
1419: case 4:
1.1.1.6 root 1420: ret = ldl_code(addr);
1.1.1.5 root 1421: break;
1422: case 8:
1.1.1.6 root 1423: ret = ldq_code(addr);
1.1.1.5 root 1424: break;
1425: }
1426: break;
1427: case 0xa: /* User data access */
1428: switch(size) {
1429: case 1:
1.1.1.6 root 1430: ret = ldub_user(addr);
1.1.1.5 root 1431: break;
1432: case 2:
1.1.1.6 root 1433: ret = lduw_user(addr);
1.1.1.5 root 1434: break;
1435: default:
1436: case 4:
1.1.1.6 root 1437: ret = ldl_user(addr);
1.1.1.5 root 1438: break;
1439: case 8:
1.1.1.6 root 1440: ret = ldq_user(addr);
1.1.1.5 root 1441: break;
1442: }
1443: break;
1444: case 0xb: /* Supervisor data access */
1445: switch(size) {
1446: case 1:
1.1.1.6 root 1447: ret = ldub_kernel(addr);
1.1.1.5 root 1448: break;
1449: case 2:
1.1.1.6 root 1450: ret = lduw_kernel(addr);
1.1.1.5 root 1451: break;
1452: default:
1453: case 4:
1.1.1.6 root 1454: ret = ldl_kernel(addr);
1.1.1.5 root 1455: break;
1456: case 8:
1.1.1.6 root 1457: ret = ldq_kernel(addr);
1.1.1.5 root 1458: break;
1459: }
1460: break;
1461: case 0xc: /* I-cache tag */
1462: case 0xd: /* I-cache data */
1463: case 0xe: /* D-cache tag */
1464: case 0xf: /* D-cache data */
1465: break;
1466: case 0x20: /* MMU passthrough */
1.1.1.2 root 1467: switch(size) {
1468: case 1:
1.1.1.6 root 1469: ret = ldub_phys(addr);
1.1.1.2 root 1470: break;
1471: case 2:
1.1.1.6 root 1472: ret = lduw_phys(addr);
1.1.1.2 root 1473: break;
1474: default:
1475: case 4:
1.1.1.6 root 1476: ret = ldl_phys(addr);
1.1.1.2 root 1477: break;
1478: case 8:
1.1.1.6 root 1479: ret = ldq_phys(addr);
1.1.1.5 root 1480: break;
1.1.1.2 root 1481: }
1.1.1.5 root 1482: break;
1483: case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1484: switch(size) {
1485: case 1:
1.1.1.6 root 1486: ret = ldub_phys((target_phys_addr_t)addr
1.1.1.5 root 1487: | ((target_phys_addr_t)(asi & 0xf) << 32));
1488: break;
1489: case 2:
1.1.1.6 root 1490: ret = lduw_phys((target_phys_addr_t)addr
1.1.1.5 root 1491: | ((target_phys_addr_t)(asi & 0xf) << 32));
1492: break;
1493: default:
1494: case 4:
1.1.1.6 root 1495: ret = ldl_phys((target_phys_addr_t)addr
1.1.1.5 root 1496: | ((target_phys_addr_t)(asi & 0xf) << 32));
1497: break;
1498: case 8:
1.1.1.6 root 1499: ret = ldq_phys((target_phys_addr_t)addr
1.1.1.5 root 1500: | ((target_phys_addr_t)(asi & 0xf) << 32));
1501: break;
1502: }
1503: break;
1504: case 0x30: // Turbosparc secondary cache diagnostic
1505: case 0x31: // Turbosparc RAM snoop
1506: case 0x32: // Turbosparc page table descriptor diagnostic
1507: case 0x39: /* data cache diagnostic register */
1508: ret = 0;
1509: break;
1.1.1.6 root 1510: case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
1511: {
1512: int reg = (addr >> 8) & 3;
1513:
1514: switch(reg) {
1515: case 0: /* Breakpoint Value (Addr) */
1516: ret = env->mmubpregs[reg];
1517: break;
1518: case 1: /* Breakpoint Mask */
1519: ret = env->mmubpregs[reg];
1520: break;
1521: case 2: /* Breakpoint Control */
1522: ret = env->mmubpregs[reg];
1523: break;
1524: case 3: /* Breakpoint Status */
1525: ret = env->mmubpregs[reg];
1526: env->mmubpregs[reg] = 0ULL;
1527: break;
1528: }
1.1.1.7 root 1529: DPRINTF_MMU("read breakpoint reg[%d] 0x%016" PRIx64 "\n", reg,
1530: ret);
1.1.1.6 root 1531: }
1532: break;
1.1.1.5 root 1533: case 8: /* User code access, XXX */
1.1 root 1534: default:
1.1.1.6 root 1535: do_unassigned_access(addr, 0, 0, asi, size);
1.1.1.5 root 1536: ret = 0;
1537: break;
1.1 root 1538: }
1.1.1.5 root 1539: if (sign) {
1540: switch(size) {
1541: case 1:
1.1.1.6 root 1542: ret = (int8_t) ret;
1.1.1.5 root 1543: break;
1544: case 2:
1.1.1.6 root 1545: ret = (int16_t) ret;
1546: break;
1547: case 4:
1548: ret = (int32_t) ret;
1.1.1.5 root 1549: break;
1550: default:
1551: break;
1552: }
1553: }
1554: #ifdef DEBUG_ASI
1.1.1.6 root 1555: dump_asi("read ", last_addr, asi, size, ret);
1.1.1.5 root 1556: #endif
1.1.1.6 root 1557: return ret;
1.1 root 1558: }
1559:
1.1.1.6 root 1560: void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
1.1 root 1561: {
1.1.1.6 root 1562: helper_check_align(addr, size - 1);
1.1 root 1563: switch(asi) {
1.1.1.5 root 1564: case 2: /* SuperSparc MXCC registers */
1.1.1.6 root 1565: switch (addr) {
1.1.1.5 root 1566: case 0x01c00000: /* MXCC stream data register 0 */
1567: if (size == 8)
1.1.1.6 root 1568: env->mxccdata[0] = val;
1.1.1.5 root 1569: else
1.1.1.6 root 1570: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1571: size);
1.1.1.5 root 1572: break;
1573: case 0x01c00008: /* MXCC stream data register 1 */
1574: if (size == 8)
1.1.1.6 root 1575: env->mxccdata[1] = val;
1.1.1.5 root 1576: else
1.1.1.6 root 1577: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1578: size);
1.1.1.5 root 1579: break;
1580: case 0x01c00010: /* MXCC stream data register 2 */
1581: if (size == 8)
1.1.1.6 root 1582: env->mxccdata[2] = val;
1.1.1.5 root 1583: else
1.1.1.6 root 1584: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1585: size);
1.1.1.5 root 1586: break;
1587: case 0x01c00018: /* MXCC stream data register 3 */
1588: if (size == 8)
1.1.1.6 root 1589: env->mxccdata[3] = val;
1.1.1.5 root 1590: else
1.1.1.6 root 1591: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1592: size);
1.1.1.5 root 1593: break;
1594: case 0x01c00100: /* MXCC stream source */
1595: if (size == 8)
1.1.1.6 root 1596: env->mxccregs[0] = val;
1.1.1.5 root 1597: else
1.1.1.6 root 1598: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1599: size);
1600: env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1601: 0);
1602: env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1603: 8);
1604: env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1605: 16);
1606: env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1607: 24);
1.1.1.5 root 1608: break;
1609: case 0x01c00200: /* MXCC stream destination */
1610: if (size == 8)
1.1.1.6 root 1611: env->mxccregs[1] = val;
1.1.1.5 root 1612: else
1.1.1.6 root 1613: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1614: size);
1615: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0,
1616: env->mxccdata[0]);
1617: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8,
1618: env->mxccdata[1]);
1619: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
1620: env->mxccdata[2]);
1621: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
1622: env->mxccdata[3]);
1.1.1.5 root 1623: break;
1624: case 0x01c00a00: /* MXCC control register */
1625: if (size == 8)
1.1.1.6 root 1626: env->mxccregs[3] = val;
1.1.1.5 root 1627: else
1.1.1.6 root 1628: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1629: size);
1.1.1.5 root 1630: break;
1631: case 0x01c00a04: /* MXCC control register */
1632: if (size == 4)
1.1.1.6 root 1633: env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
1634: | val;
1.1.1.5 root 1635: else
1.1.1.6 root 1636: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1637: size);
1.1.1.5 root 1638: break;
1639: case 0x01c00e00: /* MXCC error register */
1640: // writing a 1 bit clears the error
1641: if (size == 8)
1.1.1.6 root 1642: env->mxccregs[6] &= ~val;
1.1.1.5 root 1643: else
1.1.1.6 root 1644: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1645: size);
1.1.1.5 root 1646: break;
1647: case 0x01c00f00: /* MBus port address register */
1648: if (size == 8)
1.1.1.6 root 1649: env->mxccregs[7] = val;
1.1.1.5 root 1650: else
1.1.1.6 root 1651: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1652: size);
1.1.1.5 root 1653: break;
1654: default:
1.1.1.6 root 1655: DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1656: size);
1.1.1.5 root 1657: break;
1658: }
1.1.1.6 root 1659: DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
1660: asi, size, addr, val);
1.1.1.5 root 1661: #ifdef DEBUG_MXCC
1662: dump_mxcc(env);
1663: #endif
1664: break;
1.1 root 1665: case 3: /* MMU flush */
1.1.1.5 root 1666: {
1667: int mmulev;
1.1 root 1668:
1.1.1.6 root 1669: mmulev = (addr >> 8) & 15;
1.1.1.5 root 1670: DPRINTF_MMU("mmu flush level %d\n", mmulev);
1671: switch (mmulev) {
1672: case 0: // flush page
1.1.1.6 root 1673: tlb_flush_page(env, addr & 0xfffff000);
1.1.1.5 root 1674: break;
1675: case 1: // flush segment (256k)
1676: case 2: // flush region (16M)
1677: case 3: // flush context (4G)
1678: case 4: // flush entire
1679: tlb_flush(env, 1);
1680: break;
1681: default:
1682: break;
1683: }
1.1 root 1684: #ifdef DEBUG_MMU
1.1.1.5 root 1685: dump_mmu(env);
1.1 root 1686: #endif
1.1.1.5 root 1687: }
1688: break;
1.1 root 1689: case 4: /* write MMU regs */
1.1.1.5 root 1690: {
1.1.1.6 root 1691: int reg = (addr >> 8) & 0x1f;
1.1.1.5 root 1692: uint32_t oldreg;
1693:
1694: oldreg = env->mmuregs[reg];
1.1 root 1695: switch(reg) {
1.1.1.6 root 1696: case 0: // Control Register
1.1.1.5 root 1697: env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
1.1.1.6 root 1698: (val & 0x00ffffff);
1.1.1.5 root 1699: // Mappings generated during no-fault mode or MMU
1700: // disabled mode are invalid in normal mode
1.1.1.6 root 1701: if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
1702: (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
1.1 root 1703: tlb_flush(env, 1);
1704: break;
1.1.1.6 root 1705: case 1: // Context Table Pointer Register
1706: env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
1707: break;
1708: case 2: // Context Register
1709: env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
1.1 root 1710: if (oldreg != env->mmuregs[reg]) {
1711: /* we flush when the MMU context changes because
1712: QEMU has no MMU context support */
1713: tlb_flush(env, 1);
1714: }
1715: break;
1.1.1.6 root 1716: case 3: // Synchronous Fault Status Register with Clear
1717: case 4: // Synchronous Fault Address Register
1.1 root 1718: break;
1.1.1.6 root 1719: case 0x10: // TLB Replacement Control Register
1720: env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
1.1.1.5 root 1721: break;
1.1.1.6 root 1722: case 0x13: // Synchronous Fault Status Register with Read and Clear
1723: env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
1724: break;
1725: case 0x14: // Synchronous Fault Address Register
1726: env->mmuregs[4] = val;
1.1.1.5 root 1727: break;
1.1 root 1728: default:
1.1.1.6 root 1729: env->mmuregs[reg] = val;
1.1 root 1730: break;
1731: }
1732: if (oldreg != env->mmuregs[reg]) {
1.1.1.6 root 1733: DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
1734: reg, oldreg, env->mmuregs[reg]);
1.1 root 1735: }
1.1.1.5 root 1736: #ifdef DEBUG_MMU
1737: dump_mmu(env);
1.1 root 1738: #endif
1.1.1.5 root 1739: }
1740: break;
1741: case 5: // Turbosparc ITLB Diagnostic
1742: case 6: // Turbosparc DTLB Diagnostic
1743: case 7: // Turbosparc IOTLB Diagnostic
1744: break;
1745: case 0xa: /* User data access */
1746: switch(size) {
1747: case 1:
1.1.1.6 root 1748: stb_user(addr, val);
1.1.1.5 root 1749: break;
1750: case 2:
1.1.1.6 root 1751: stw_user(addr, val);
1.1.1.5 root 1752: break;
1753: default:
1754: case 4:
1.1.1.6 root 1755: stl_user(addr, val);
1.1.1.5 root 1756: break;
1757: case 8:
1.1.1.6 root 1758: stq_user(addr, val);
1.1.1.5 root 1759: break;
1760: }
1761: break;
1762: case 0xb: /* Supervisor data access */
1763: switch(size) {
1764: case 1:
1.1.1.6 root 1765: stb_kernel(addr, val);
1.1.1.5 root 1766: break;
1767: case 2:
1.1.1.6 root 1768: stw_kernel(addr, val);
1.1.1.5 root 1769: break;
1770: default:
1771: case 4:
1.1.1.6 root 1772: stl_kernel(addr, val);
1.1.1.5 root 1773: break;
1774: case 8:
1.1.1.6 root 1775: stq_kernel(addr, val);
1.1.1.5 root 1776: break;
1777: }
1778: break;
1779: case 0xc: /* I-cache tag */
1780: case 0xd: /* I-cache data */
1781: case 0xe: /* D-cache tag */
1782: case 0xf: /* D-cache data */
1783: case 0x10: /* I/D-cache flush page */
1784: case 0x11: /* I/D-cache flush segment */
1785: case 0x12: /* I/D-cache flush region */
1786: case 0x13: /* I/D-cache flush context */
1787: case 0x14: /* I/D-cache flush user */
1788: break;
1.1 root 1789: case 0x17: /* Block copy, sta access */
1.1.1.5 root 1790: {
1.1.1.6 root 1791: // val = src
1792: // addr = dst
1.1.1.5 root 1793: // copy 32 bytes
1794: unsigned int i;
1.1.1.6 root 1795: uint32_t src = val & ~3, dst = addr & ~3, temp;
1.1.1.5 root 1796:
1797: for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1798: temp = ldl_kernel(src);
1799: stl_kernel(dst, temp);
1800: }
1801: }
1802: break;
1.1 root 1803: case 0x1f: /* Block fill, stda access */
1.1.1.5 root 1804: {
1.1.1.6 root 1805: // addr = dst
1806: // fill 32 bytes with val
1.1.1.5 root 1807: unsigned int i;
1.1.1.6 root 1808: uint32_t dst = addr & 7;
1.1.1.5 root 1809:
1810: for (i = 0; i < 32; i += 8, dst += 8)
1811: stq_kernel(dst, val);
1812: }
1813: break;
1814: case 0x20: /* MMU passthrough */
1815: {
1816: switch(size) {
1817: case 1:
1.1.1.6 root 1818: stb_phys(addr, val);
1.1.1.5 root 1819: break;
1820: case 2:
1.1.1.6 root 1821: stw_phys(addr, val);
1.1.1.5 root 1822: break;
1823: case 4:
1824: default:
1.1.1.6 root 1825: stl_phys(addr, val);
1.1.1.5 root 1826: break;
1827: case 8:
1.1.1.6 root 1828: stq_phys(addr, val);
1.1.1.5 root 1829: break;
1830: }
1831: }
1832: break;
1833: case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1834: {
1835: switch(size) {
1836: case 1:
1.1.1.6 root 1837: stb_phys((target_phys_addr_t)addr
1838: | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1.1.1.5 root 1839: break;
1840: case 2:
1.1.1.6 root 1841: stw_phys((target_phys_addr_t)addr
1842: | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1.1.1.5 root 1843: break;
1844: case 4:
1845: default:
1.1.1.6 root 1846: stl_phys((target_phys_addr_t)addr
1847: | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1.1.1.5 root 1848: break;
1849: case 8:
1.1.1.6 root 1850: stq_phys((target_phys_addr_t)addr
1851: | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1.1.1.5 root 1852: break;
1853: }
1854: }
1855: break;
1856: case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
1857: case 0x31: // store buffer data, Ross RT620 I-cache flush or
1858: // Turbosparc snoop RAM
1.1.1.6 root 1859: case 0x32: // store buffer control or Turbosparc page table
1860: // descriptor diagnostic
1.1.1.5 root 1861: case 0x36: /* I-cache flash clear */
1862: case 0x37: /* D-cache flash clear */
1863: case 0x4c: /* breakpoint action */
1864: break;
1.1.1.6 root 1865: case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
1866: {
1867: int reg = (addr >> 8) & 3;
1868:
1869: switch(reg) {
1870: case 0: /* Breakpoint Value (Addr) */
1871: env->mmubpregs[reg] = (val & 0xfffffffffULL);
1872: break;
1873: case 1: /* Breakpoint Mask */
1874: env->mmubpregs[reg] = (val & 0xfffffffffULL);
1875: break;
1876: case 2: /* Breakpoint Control */
1877: env->mmubpregs[reg] = (val & 0x7fULL);
1878: break;
1879: case 3: /* Breakpoint Status */
1880: env->mmubpregs[reg] = (val & 0xfULL);
1881: break;
1882: }
1.1.1.7 root 1883: DPRINTF_MMU("write breakpoint reg[%d] 0x%016x\n", reg,
1.1.1.6 root 1884: env->mmuregs[reg]);
1885: }
1886: break;
1.1.1.5 root 1887: case 8: /* User code access, XXX */
1888: case 9: /* Supervisor code access, XXX */
1889: default:
1.1.1.6 root 1890: do_unassigned_access(addr, 1, 0, asi, size);
1.1.1.5 root 1891: break;
1892: }
1893: #ifdef DEBUG_ASI
1.1.1.6 root 1894: dump_asi("write", addr, asi, size, val);
1.1.1.5 root 1895: #endif
1896: }
1897:
1898: #endif /* CONFIG_USER_ONLY */
1899: #else /* TARGET_SPARC64 */
1900:
1901: #ifdef CONFIG_USER_ONLY
1.1.1.6 root 1902: uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1.1.1.5 root 1903: {
1904: uint64_t ret = 0;
1.1.1.6 root 1905: #if defined(DEBUG_ASI)
1906: target_ulong last_addr = addr;
1907: #endif
1.1.1.5 root 1908:
1909: if (asi < 0x80)
1910: raise_exception(TT_PRIV_ACT);
1911:
1.1.1.6 root 1912: helper_check_align(addr, size - 1);
1913: address_mask(env, &addr);
1914:
1.1.1.5 root 1915: switch (asi) {
1916: case 0x82: // Primary no-fault
1917: case 0x8a: // Primary no-fault LE
1.1.1.6 root 1918: if (page_check_range(addr, size, PAGE_READ) == -1) {
1919: #ifdef DEBUG_ASI
1920: dump_asi("read ", last_addr, asi, size, ret);
1921: #endif
1922: return 0;
1923: }
1924: // Fall through
1925: case 0x80: // Primary
1926: case 0x88: // Primary LE
1.1.1.5 root 1927: {
1928: switch(size) {
1929: case 1:
1.1.1.6 root 1930: ret = ldub_raw(addr);
1.1.1.5 root 1931: break;
1932: case 2:
1.1.1.6 root 1933: ret = lduw_raw(addr);
1.1.1.5 root 1934: break;
1935: case 4:
1.1.1.6 root 1936: ret = ldl_raw(addr);
1.1.1.5 root 1937: break;
1938: default:
1939: case 8:
1.1.1.6 root 1940: ret = ldq_raw(addr);
1.1.1.5 root 1941: break;
1942: }
1943: }
1944: break;
1945: case 0x83: // Secondary no-fault
1946: case 0x8b: // Secondary no-fault LE
1.1.1.6 root 1947: if (page_check_range(addr, size, PAGE_READ) == -1) {
1948: #ifdef DEBUG_ASI
1949: dump_asi("read ", last_addr, asi, size, ret);
1950: #endif
1951: return 0;
1952: }
1953: // Fall through
1954: case 0x81: // Secondary
1955: case 0x89: // Secondary LE
1.1.1.5 root 1956: // XXX
1957: break;
1958: default:
1959: break;
1960: }
1961:
1962: /* Convert from little endian */
1963: switch (asi) {
1964: case 0x88: // Primary LE
1965: case 0x89: // Secondary LE
1966: case 0x8a: // Primary no-fault LE
1967: case 0x8b: // Secondary no-fault LE
1968: switch(size) {
1969: case 2:
1970: ret = bswap16(ret);
1971: break;
1972: case 4:
1973: ret = bswap32(ret);
1974: break;
1975: case 8:
1976: ret = bswap64(ret);
1977: break;
1978: default:
1979: break;
1980: }
1981: default:
1982: break;
1983: }
1984:
1985: /* Convert to signed number */
1986: if (sign) {
1987: switch(size) {
1988: case 1:
1989: ret = (int8_t) ret;
1990: break;
1991: case 2:
1992: ret = (int16_t) ret;
1993: break;
1994: case 4:
1995: ret = (int32_t) ret;
1996: break;
1997: default:
1998: break;
1999: }
2000: }
1.1.1.6 root 2001: #ifdef DEBUG_ASI
2002: dump_asi("read ", last_addr, asi, size, ret);
2003: #endif
2004: return ret;
1.1.1.5 root 2005: }
2006:
1.1.1.6 root 2007: void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1.1.1.5 root 2008: {
1.1.1.6 root 2009: #ifdef DEBUG_ASI
2010: dump_asi("write", addr, asi, size, val);
2011: #endif
1.1.1.5 root 2012: if (asi < 0x80)
2013: raise_exception(TT_PRIV_ACT);
2014:
1.1.1.6 root 2015: helper_check_align(addr, size - 1);
2016: address_mask(env, &addr);
2017:
1.1.1.5 root 2018: /* Convert to little endian */
2019: switch (asi) {
2020: case 0x88: // Primary LE
2021: case 0x89: // Secondary LE
2022: switch(size) {
2023: case 2:
1.1.1.7 root 2024: val = bswap16(val);
1.1.1.5 root 2025: break;
2026: case 4:
1.1.1.7 root 2027: val = bswap32(val);
1.1.1.5 root 2028: break;
2029: case 8:
1.1.1.7 root 2030: val = bswap64(val);
1.1.1.5 root 2031: break;
2032: default:
2033: break;
2034: }
2035: default:
2036: break;
2037: }
2038:
2039: switch(asi) {
2040: case 0x80: // Primary
2041: case 0x88: // Primary LE
2042: {
1.1.1.2 root 2043: switch(size) {
2044: case 1:
1.1.1.6 root 2045: stb_raw(addr, val);
1.1.1.2 root 2046: break;
2047: case 2:
1.1.1.6 root 2048: stw_raw(addr, val);
1.1.1.2 root 2049: break;
2050: case 4:
1.1.1.6 root 2051: stl_raw(addr, val);
1.1.1.2 root 2052: break;
2053: case 8:
1.1.1.5 root 2054: default:
1.1.1.6 root 2055: stq_raw(addr, val);
1.1.1.2 root 2056: break;
2057: }
1.1.1.5 root 2058: }
2059: break;
2060: case 0x81: // Secondary
2061: case 0x89: // Secondary LE
2062: // XXX
2063: return;
2064:
2065: case 0x82: // Primary no-fault, RO
2066: case 0x83: // Secondary no-fault, RO
2067: case 0x8a: // Primary no-fault LE, RO
2068: case 0x8b: // Secondary no-fault LE, RO
1.1 root 2069: default:
1.1.1.6 root 2070: do_unassigned_access(addr, 1, 0, 1, size);
1.1.1.5 root 2071: return;
1.1 root 2072: }
2073: }
2074:
1.1.1.5 root 2075: #else /* CONFIG_USER_ONLY */
1.1 root 2076:
1.1.1.6 root 2077: uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1.1 root 2078: {
2079: uint64_t ret = 0;
1.1.1.6 root 2080: #if defined(DEBUG_ASI)
2081: target_ulong last_addr = addr;
2082: #endif
1.1 root 2083:
1.1.1.8 ! root 2084: asi &= 0xff;
! 2085:
1.1.1.5 root 2086: if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1.1.1.6 root 2087: || ((env->def->features & CPU_FEATURE_HYPV)
2088: && asi >= 0x30 && asi < 0x80
2089: && !(env->hpstate & HS_PRIV)))
1.1.1.5 root 2090: raise_exception(TT_PRIV_ACT);
1.1 root 2091:
1.1.1.6 root 2092: helper_check_align(addr, size - 1);
1.1 root 2093: switch (asi) {
1.1.1.6 root 2094: case 0x82: // Primary no-fault
2095: case 0x8a: // Primary no-fault LE
2096: if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
2097: #ifdef DEBUG_ASI
2098: dump_asi("read ", last_addr, asi, size, ret);
2099: #endif
2100: return 0;
2101: }
2102: // Fall through
1.1.1.5 root 2103: case 0x10: // As if user primary
2104: case 0x18: // As if user primary LE
2105: case 0x80: // Primary
2106: case 0x88: // Primary LE
1.1.1.6 root 2107: case 0xe2: // UA2007 Primary block init
2108: case 0xe3: // UA2007 Secondary block init
1.1.1.5 root 2109: if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1.1.1.6 root 2110: if ((env->def->features & CPU_FEATURE_HYPV)
2111: && env->hpstate & HS_PRIV) {
1.1.1.5 root 2112: switch(size) {
2113: case 1:
1.1.1.6 root 2114: ret = ldub_hypv(addr);
1.1.1.5 root 2115: break;
2116: case 2:
1.1.1.6 root 2117: ret = lduw_hypv(addr);
1.1.1.5 root 2118: break;
2119: case 4:
1.1.1.6 root 2120: ret = ldl_hypv(addr);
1.1.1.5 root 2121: break;
2122: default:
2123: case 8:
1.1.1.6 root 2124: ret = ldq_hypv(addr);
1.1.1.5 root 2125: break;
2126: }
2127: } else {
2128: switch(size) {
2129: case 1:
1.1.1.6 root 2130: ret = ldub_kernel(addr);
1.1.1.5 root 2131: break;
2132: case 2:
1.1.1.6 root 2133: ret = lduw_kernel(addr);
1.1.1.5 root 2134: break;
2135: case 4:
1.1.1.6 root 2136: ret = ldl_kernel(addr);
1.1.1.5 root 2137: break;
2138: default:
2139: case 8:
1.1.1.6 root 2140: ret = ldq_kernel(addr);
1.1.1.5 root 2141: break;
2142: }
2143: }
2144: } else {
2145: switch(size) {
2146: case 1:
1.1.1.6 root 2147: ret = ldub_user(addr);
1.1.1.5 root 2148: break;
2149: case 2:
1.1.1.6 root 2150: ret = lduw_user(addr);
1.1.1.5 root 2151: break;
2152: case 4:
1.1.1.6 root 2153: ret = ldl_user(addr);
1.1.1.5 root 2154: break;
2155: default:
2156: case 8:
1.1.1.6 root 2157: ret = ldq_user(addr);
1.1.1.5 root 2158: break;
2159: }
2160: }
2161: break;
1.1 root 2162: case 0x14: // Bypass
2163: case 0x15: // Bypass, non-cacheable
1.1.1.5 root 2164: case 0x1c: // Bypass LE
2165: case 0x1d: // Bypass, non-cacheable LE
2166: {
1.1.1.2 root 2167: switch(size) {
2168: case 1:
1.1.1.6 root 2169: ret = ldub_phys(addr);
1.1.1.2 root 2170: break;
2171: case 2:
1.1.1.6 root 2172: ret = lduw_phys(addr);
1.1.1.2 root 2173: break;
2174: case 4:
1.1.1.6 root 2175: ret = ldl_phys(addr);
1.1.1.2 root 2176: break;
2177: default:
2178: case 8:
1.1.1.6 root 2179: ret = ldq_phys(addr);
1.1.1.2 root 2180: break;
2181: }
1.1.1.5 root 2182: break;
2183: }
1.1.1.6 root 2184: case 0x24: // Nucleus quad LDD 128 bit atomic
2185: case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2186: // Only ldda allowed
2187: raise_exception(TT_ILL_INSN);
2188: return 0;
2189: case 0x83: // Secondary no-fault
2190: case 0x8b: // Secondary no-fault LE
2191: if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
2192: #ifdef DEBUG_ASI
2193: dump_asi("read ", last_addr, asi, size, ret);
2194: #endif
2195: return 0;
2196: }
2197: // Fall through
1.1 root 2198: case 0x04: // Nucleus
2199: case 0x0c: // Nucleus Little Endian (LE)
2200: case 0x11: // As if user secondary
2201: case 0x19: // As if user secondary LE
2202: case 0x4a: // UPA config
1.1.1.5 root 2203: case 0x81: // Secondary
1.1 root 2204: case 0x89: // Secondary LE
1.1.1.5 root 2205: // XXX
2206: break;
1.1 root 2207: case 0x45: // LSU
1.1.1.5 root 2208: ret = env->lsu;
2209: break;
1.1 root 2210: case 0x50: // I-MMU regs
1.1.1.5 root 2211: {
1.1.1.6 root 2212: int reg = (addr >> 3) & 0xf;
1.1 root 2213:
1.1.1.7 root 2214: if (reg == 0) {
2215: // I-TSB Tag Target register
1.1.1.8 ! root 2216: ret = ultrasparc_tag_target(env->immu.tag_access);
1.1.1.7 root 2217: } else {
2218: ret = env->immuregs[reg];
2219: }
2220:
1.1.1.5 root 2221: break;
2222: }
1.1 root 2223: case 0x51: // I-MMU 8k TSB pointer
1.1.1.7 root 2224: {
2225: // env->immuregs[5] holds I-MMU TSB register value
2226: // env->immuregs[6] holds I-MMU Tag Access register value
1.1.1.8 ! root 2227: ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
1.1.1.7 root 2228: 8*1024);
2229: break;
2230: }
1.1 root 2231: case 0x52: // I-MMU 64k TSB pointer
1.1.1.7 root 2232: {
2233: // env->immuregs[5] holds I-MMU TSB register value
2234: // env->immuregs[6] holds I-MMU Tag Access register value
1.1.1.8 ! root 2235: ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
1.1.1.7 root 2236: 64*1024);
2237: break;
2238: }
1.1.1.6 root 2239: case 0x55: // I-MMU data access
2240: {
2241: int reg = (addr >> 3) & 0x3f;
2242:
1.1.1.8 ! root 2243: ret = env->itlb[reg].tte;
1.1.1.6 root 2244: break;
2245: }
1.1 root 2246: case 0x56: // I-MMU tag read
1.1.1.5 root 2247: {
1.1.1.6 root 2248: int reg = (addr >> 3) & 0x3f;
1.1.1.5 root 2249:
1.1.1.8 ! root 2250: ret = env->itlb[reg].tag;
1.1.1.5 root 2251: break;
2252: }
1.1 root 2253: case 0x58: // D-MMU regs
1.1.1.5 root 2254: {
1.1.1.6 root 2255: int reg = (addr >> 3) & 0xf;
1.1 root 2256:
1.1.1.7 root 2257: if (reg == 0) {
2258: // D-TSB Tag Target register
1.1.1.8 ! root 2259: ret = ultrasparc_tag_target(env->dmmu.tag_access);
1.1.1.7 root 2260: } else {
2261: ret = env->dmmuregs[reg];
2262: }
2263: break;
2264: }
2265: case 0x59: // D-MMU 8k TSB pointer
2266: {
2267: // env->dmmuregs[5] holds D-MMU TSB register value
2268: // env->dmmuregs[6] holds D-MMU Tag Access register value
1.1.1.8 ! root 2269: ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
1.1.1.7 root 2270: 8*1024);
2271: break;
2272: }
2273: case 0x5a: // D-MMU 64k TSB pointer
2274: {
2275: // env->dmmuregs[5] holds D-MMU TSB register value
2276: // env->dmmuregs[6] holds D-MMU Tag Access register value
1.1.1.8 ! root 2277: ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
1.1.1.7 root 2278: 64*1024);
1.1.1.5 root 2279: break;
2280: }
1.1.1.6 root 2281: case 0x5d: // D-MMU data access
2282: {
2283: int reg = (addr >> 3) & 0x3f;
2284:
1.1.1.8 ! root 2285: ret = env->dtlb[reg].tte;
1.1.1.6 root 2286: break;
2287: }
1.1 root 2288: case 0x5e: // D-MMU tag read
1.1.1.5 root 2289: {
1.1.1.6 root 2290: int reg = (addr >> 3) & 0x3f;
1.1.1.5 root 2291:
1.1.1.8 ! root 2292: ret = env->dtlb[reg].tag;
1.1.1.5 root 2293: break;
2294: }
1.1.1.6 root 2295: case 0x46: // D-cache data
2296: case 0x47: // D-cache tag access
2297: case 0x4b: // E-cache error enable
2298: case 0x4c: // E-cache asynchronous fault status
2299: case 0x4d: // E-cache asynchronous fault address
2300: case 0x4e: // E-cache tag data
2301: case 0x66: // I-cache instruction access
2302: case 0x67: // I-cache tag access
2303: case 0x6e: // I-cache predecode
2304: case 0x6f: // I-cache LRU etc.
2305: case 0x76: // E-cache tag
2306: case 0x7e: // E-cache tag
2307: break;
1.1 root 2308: case 0x5b: // D-MMU data pointer
2309: case 0x48: // Interrupt dispatch, RO
2310: case 0x49: // Interrupt data receive
2311: case 0x7f: // Incoming interrupt vector, RO
1.1.1.5 root 2312: // XXX
2313: break;
1.1 root 2314: case 0x54: // I-MMU data in, WO
2315: case 0x57: // I-MMU demap, WO
2316: case 0x5c: // D-MMU data in, WO
2317: case 0x5f: // D-MMU demap, WO
2318: case 0x77: // Interrupt vector, WO
2319: default:
1.1.1.6 root 2320: do_unassigned_access(addr, 0, 0, 1, size);
1.1.1.5 root 2321: ret = 0;
2322: break;
2323: }
2324:
2325: /* Convert from little endian */
2326: switch (asi) {
2327: case 0x0c: // Nucleus Little Endian (LE)
2328: case 0x18: // As if user primary LE
2329: case 0x19: // As if user secondary LE
2330: case 0x1c: // Bypass LE
2331: case 0x1d: // Bypass, non-cacheable LE
2332: case 0x88: // Primary LE
2333: case 0x89: // Secondary LE
2334: case 0x8a: // Primary no-fault LE
2335: case 0x8b: // Secondary no-fault LE
2336: switch(size) {
2337: case 2:
2338: ret = bswap16(ret);
2339: break;
2340: case 4:
2341: ret = bswap32(ret);
2342: break;
2343: case 8:
2344: ret = bswap64(ret);
2345: break;
2346: default:
2347: break;
2348: }
2349: default:
2350: break;
2351: }
2352:
2353: /* Convert to signed number */
2354: if (sign) {
2355: switch(size) {
2356: case 1:
2357: ret = (int8_t) ret;
2358: break;
2359: case 2:
2360: ret = (int16_t) ret;
2361: break;
2362: case 4:
2363: ret = (int32_t) ret;
2364: break;
2365: default:
2366: break;
2367: }
1.1 root 2368: }
1.1.1.6 root 2369: #ifdef DEBUG_ASI
2370: dump_asi("read ", last_addr, asi, size, ret);
2371: #endif
2372: return ret;
1.1 root 2373: }
2374:
1.1.1.6 root 2375: void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1.1 root 2376: {
1.1.1.6 root 2377: #ifdef DEBUG_ASI
2378: dump_asi("write", addr, asi, size, val);
2379: #endif
1.1.1.8 ! root 2380:
! 2381: asi &= 0xff;
! 2382:
1.1.1.5 root 2383: if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1.1.1.6 root 2384: || ((env->def->features & CPU_FEATURE_HYPV)
2385: && asi >= 0x30 && asi < 0x80
2386: && !(env->hpstate & HS_PRIV)))
1.1.1.5 root 2387: raise_exception(TT_PRIV_ACT);
2388:
1.1.1.6 root 2389: helper_check_align(addr, size - 1);
1.1.1.5 root 2390: /* Convert to little endian */
2391: switch (asi) {
2392: case 0x0c: // Nucleus Little Endian (LE)
2393: case 0x18: // As if user primary LE
2394: case 0x19: // As if user secondary LE
2395: case 0x1c: // Bypass LE
2396: case 0x1d: // Bypass, non-cacheable LE
2397: case 0x88: // Primary LE
2398: case 0x89: // Secondary LE
2399: switch(size) {
2400: case 2:
1.1.1.7 root 2401: val = bswap16(val);
1.1.1.5 root 2402: break;
2403: case 4:
1.1.1.7 root 2404: val = bswap32(val);
1.1.1.5 root 2405: break;
2406: case 8:
1.1.1.7 root 2407: val = bswap64(val);
1.1.1.5 root 2408: break;
2409: default:
2410: break;
2411: }
2412: default:
2413: break;
2414: }
1.1 root 2415:
2416: switch(asi) {
1.1.1.5 root 2417: case 0x10: // As if user primary
2418: case 0x18: // As if user primary LE
2419: case 0x80: // Primary
2420: case 0x88: // Primary LE
1.1.1.6 root 2421: case 0xe2: // UA2007 Primary block init
2422: case 0xe3: // UA2007 Secondary block init
1.1.1.5 root 2423: if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1.1.1.6 root 2424: if ((env->def->features & CPU_FEATURE_HYPV)
2425: && env->hpstate & HS_PRIV) {
1.1.1.5 root 2426: switch(size) {
2427: case 1:
1.1.1.6 root 2428: stb_hypv(addr, val);
1.1.1.5 root 2429: break;
2430: case 2:
1.1.1.6 root 2431: stw_hypv(addr, val);
1.1.1.5 root 2432: break;
2433: case 4:
1.1.1.6 root 2434: stl_hypv(addr, val);
1.1.1.5 root 2435: break;
2436: case 8:
2437: default:
1.1.1.6 root 2438: stq_hypv(addr, val);
1.1.1.5 root 2439: break;
2440: }
2441: } else {
2442: switch(size) {
2443: case 1:
1.1.1.6 root 2444: stb_kernel(addr, val);
1.1.1.5 root 2445: break;
2446: case 2:
1.1.1.6 root 2447: stw_kernel(addr, val);
1.1.1.5 root 2448: break;
2449: case 4:
1.1.1.6 root 2450: stl_kernel(addr, val);
1.1.1.5 root 2451: break;
2452: case 8:
2453: default:
1.1.1.6 root 2454: stq_kernel(addr, val);
1.1.1.5 root 2455: break;
2456: }
2457: }
2458: } else {
2459: switch(size) {
2460: case 1:
1.1.1.6 root 2461: stb_user(addr, val);
1.1.1.5 root 2462: break;
2463: case 2:
1.1.1.6 root 2464: stw_user(addr, val);
1.1.1.5 root 2465: break;
2466: case 4:
1.1.1.6 root 2467: stl_user(addr, val);
1.1.1.5 root 2468: break;
2469: case 8:
2470: default:
1.1.1.6 root 2471: stq_user(addr, val);
1.1.1.5 root 2472: break;
2473: }
2474: }
2475: break;
1.1 root 2476: case 0x14: // Bypass
2477: case 0x15: // Bypass, non-cacheable
1.1.1.5 root 2478: case 0x1c: // Bypass LE
2479: case 0x1d: // Bypass, non-cacheable LE
2480: {
1.1.1.2 root 2481: switch(size) {
2482: case 1:
1.1.1.6 root 2483: stb_phys(addr, val);
1.1.1.2 root 2484: break;
2485: case 2:
1.1.1.6 root 2486: stw_phys(addr, val);
1.1.1.2 root 2487: break;
2488: case 4:
1.1.1.6 root 2489: stl_phys(addr, val);
1.1.1.2 root 2490: break;
2491: case 8:
2492: default:
1.1.1.6 root 2493: stq_phys(addr, val);
1.1.1.2 root 2494: break;
2495: }
1.1.1.5 root 2496: }
2497: return;
1.1.1.6 root 2498: case 0x24: // Nucleus quad LDD 128 bit atomic
2499: case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2500: // Only ldda allowed
2501: raise_exception(TT_ILL_INSN);
2502: return;
1.1 root 2503: case 0x04: // Nucleus
2504: case 0x0c: // Nucleus Little Endian (LE)
2505: case 0x11: // As if user secondary
2506: case 0x19: // As if user secondary LE
2507: case 0x4a: // UPA config
1.1.1.5 root 2508: case 0x81: // Secondary
1.1 root 2509: case 0x89: // Secondary LE
1.1.1.5 root 2510: // XXX
2511: return;
1.1 root 2512: case 0x45: // LSU
1.1.1.5 root 2513: {
2514: uint64_t oldreg;
1.1 root 2515:
1.1.1.5 root 2516: oldreg = env->lsu;
1.1.1.6 root 2517: env->lsu = val & (DMMU_E | IMMU_E);
1.1.1.5 root 2518: // Mappings generated during D/I MMU disabled mode are
2519: // invalid in normal mode
2520: if (oldreg != env->lsu) {
1.1.1.6 root 2521: DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
2522: oldreg, env->lsu);
1.1 root 2523: #ifdef DEBUG_MMU
1.1.1.5 root 2524: dump_mmu(env);
1.1 root 2525: #endif
1.1.1.5 root 2526: tlb_flush(env, 1);
2527: }
2528: return;
2529: }
1.1 root 2530: case 0x50: // I-MMU regs
1.1.1.5 root 2531: {
1.1.1.6 root 2532: int reg = (addr >> 3) & 0xf;
1.1.1.5 root 2533: uint64_t oldreg;
2534:
2535: oldreg = env->immuregs[reg];
1.1 root 2536: switch(reg) {
2537: case 0: // RO
2538: return;
2539: case 1: // Not in I-MMU
2540: case 2:
2541: return;
2542: case 3: // SFSR
1.1.1.6 root 2543: if ((val & 1) == 0)
2544: val = 0; // Clear SFSR
1.1.1.8 ! root 2545: env->immu.sfsr = val;
1.1 root 2546: break;
1.1.1.8 ! root 2547: case 4: // RO
! 2548: return;
1.1 root 2549: case 5: // TSB access
1.1.1.8 ! root 2550: DPRINTF_MMU("immu TSB write: 0x%016" PRIx64 " -> 0x%016"
! 2551: PRIx64 "\n", env->immu.tsb, val);
! 2552: env->immu.tsb = val;
! 2553: break;
1.1 root 2554: case 6: // Tag access
1.1.1.8 ! root 2555: env->immu.tag_access = val;
! 2556: break;
! 2557: case 7:
! 2558: case 8:
! 2559: return;
1.1 root 2560: default:
2561: break;
2562: }
1.1.1.8 ! root 2563:
1.1 root 2564: if (oldreg != env->immuregs[reg]) {
1.1.1.8 ! root 2565: DPRINTF_MMU("immu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
1.1.1.6 root 2566: PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1.1 root 2567: }
1.1.1.5 root 2568: #ifdef DEBUG_MMU
2569: dump_mmu(env);
1.1 root 2570: #endif
1.1.1.5 root 2571: return;
2572: }
1.1 root 2573: case 0x54: // I-MMU data in
1.1.1.8 ! root 2574: replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", env);
! 2575: return;
1.1 root 2576: case 0x55: // I-MMU data access
1.1.1.5 root 2577: {
1.1.1.6 root 2578: // TODO: auto demap
2579:
2580: unsigned int i = (addr >> 3) & 0x3f;
1.1 root 2581:
1.1.1.8 ! root 2582: replace_tlb_entry(&env->itlb[i], env->immu.tag_access, val, env);
! 2583:
! 2584: #ifdef DEBUG_MMU
! 2585: DPRINTF_MMU("immu data access replaced entry [%i]\n", i);
! 2586: dump_mmu(env);
! 2587: #endif
1.1.1.5 root 2588: return;
2589: }
1.1 root 2590: case 0x57: // I-MMU demap
1.1.1.8 ! root 2591: demap_tlb(env->itlb, val, "immu", env);
1.1.1.5 root 2592: return;
1.1 root 2593: case 0x58: // D-MMU regs
1.1.1.5 root 2594: {
1.1.1.6 root 2595: int reg = (addr >> 3) & 0xf;
1.1.1.5 root 2596: uint64_t oldreg;
2597:
2598: oldreg = env->dmmuregs[reg];
1.1 root 2599: switch(reg) {
2600: case 0: // RO
2601: case 4:
2602: return;
2603: case 3: // SFSR
1.1.1.6 root 2604: if ((val & 1) == 0) {
2605: val = 0; // Clear SFSR, Fault address
1.1.1.8 ! root 2606: env->dmmu.sfar = 0;
1.1.1.5 root 2607: }
1.1.1.8 ! root 2608: env->dmmu.sfsr = val;
1.1 root 2609: break;
2610: case 1: // Primary context
1.1.1.8 ! root 2611: env->dmmu.mmu_primary_context = val;
! 2612: break;
1.1 root 2613: case 2: // Secondary context
1.1.1.8 ! root 2614: env->dmmu.mmu_secondary_context = val;
! 2615: break;
1.1 root 2616: case 5: // TSB access
1.1.1.8 ! root 2617: DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016"
! 2618: PRIx64 "\n", env->dmmu.tsb, val);
! 2619: env->dmmu.tsb = val;
! 2620: break;
1.1 root 2621: case 6: // Tag access
1.1.1.8 ! root 2622: env->dmmu.tag_access = val;
! 2623: break;
1.1 root 2624: case 7: // Virtual Watchpoint
2625: case 8: // Physical Watchpoint
2626: default:
1.1.1.8 ! root 2627: env->dmmuregs[reg] = val;
1.1 root 2628: break;
2629: }
1.1.1.8 ! root 2630:
1.1 root 2631: if (oldreg != env->dmmuregs[reg]) {
1.1.1.8 ! root 2632: DPRINTF_MMU("dmmu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
1.1.1.6 root 2633: PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
1.1 root 2634: }
1.1.1.5 root 2635: #ifdef DEBUG_MMU
2636: dump_mmu(env);
1.1 root 2637: #endif
1.1.1.5 root 2638: return;
2639: }
1.1 root 2640: case 0x5c: // D-MMU data in
1.1.1.8 ! root 2641: replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", env);
! 2642: return;
1.1 root 2643: case 0x5d: // D-MMU data access
1.1.1.5 root 2644: {
1.1.1.6 root 2645: unsigned int i = (addr >> 3) & 0x3f;
1.1 root 2646:
1.1.1.8 ! root 2647: replace_tlb_entry(&env->dtlb[i], env->dmmu.tag_access, val, env);
! 2648:
! 2649: #ifdef DEBUG_MMU
! 2650: DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i);
! 2651: dump_mmu(env);
! 2652: #endif
1.1.1.5 root 2653: return;
2654: }
1.1 root 2655: case 0x5f: // D-MMU demap
1.1.1.8 ! root 2656: demap_tlb(env->dtlb, val, "dmmu", env);
1.1.1.6 root 2657: return;
1.1 root 2658: case 0x49: // Interrupt data receive
1.1.1.5 root 2659: // XXX
2660: return;
1.1.1.6 root 2661: case 0x46: // D-cache data
2662: case 0x47: // D-cache tag access
2663: case 0x4b: // E-cache error enable
2664: case 0x4c: // E-cache asynchronous fault status
2665: case 0x4d: // E-cache asynchronous fault address
2666: case 0x4e: // E-cache tag data
2667: case 0x66: // I-cache instruction access
2668: case 0x67: // I-cache tag access
2669: case 0x6e: // I-cache predecode
2670: case 0x6f: // I-cache LRU etc.
2671: case 0x76: // E-cache tag
2672: case 0x7e: // E-cache tag
2673: return;
1.1 root 2674: case 0x51: // I-MMU 8k TSB pointer, RO
2675: case 0x52: // I-MMU 64k TSB pointer, RO
2676: case 0x56: // I-MMU tag read, RO
2677: case 0x59: // D-MMU 8k TSB pointer, RO
2678: case 0x5a: // D-MMU 64k TSB pointer, RO
2679: case 0x5b: // D-MMU data pointer, RO
2680: case 0x5e: // D-MMU tag read, RO
2681: case 0x48: // Interrupt dispatch, RO
2682: case 0x7f: // Incoming interrupt vector, RO
2683: case 0x82: // Primary no-fault, RO
2684: case 0x83: // Secondary no-fault, RO
2685: case 0x8a: // Primary no-fault LE, RO
2686: case 0x8b: // Secondary no-fault LE, RO
2687: default:
1.1.1.6 root 2688: do_unassigned_access(addr, 1, 0, 1, size);
1.1.1.5 root 2689: return;
2690: }
2691: }
2692: #endif /* CONFIG_USER_ONLY */
2693:
1.1.1.6 root 2694: void helper_ldda_asi(target_ulong addr, int asi, int rd)
2695: {
2696: if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2697: || ((env->def->features & CPU_FEATURE_HYPV)
2698: && asi >= 0x30 && asi < 0x80
2699: && !(env->hpstate & HS_PRIV)))
2700: raise_exception(TT_PRIV_ACT);
2701:
2702: switch (asi) {
2703: case 0x24: // Nucleus quad LDD 128 bit atomic
2704: case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2705: helper_check_align(addr, 0xf);
2706: if (rd == 0) {
2707: env->gregs[1] = ldq_kernel(addr + 8);
2708: if (asi == 0x2c)
2709: bswap64s(&env->gregs[1]);
2710: } else if (rd < 8) {
2711: env->gregs[rd] = ldq_kernel(addr);
2712: env->gregs[rd + 1] = ldq_kernel(addr + 8);
2713: if (asi == 0x2c) {
2714: bswap64s(&env->gregs[rd]);
2715: bswap64s(&env->gregs[rd + 1]);
2716: }
2717: } else {
2718: env->regwptr[rd] = ldq_kernel(addr);
2719: env->regwptr[rd + 1] = ldq_kernel(addr + 8);
2720: if (asi == 0x2c) {
2721: bswap64s(&env->regwptr[rd]);
2722: bswap64s(&env->regwptr[rd + 1]);
2723: }
2724: }
2725: break;
2726: default:
2727: helper_check_align(addr, 0x3);
2728: if (rd == 0)
2729: env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
2730: else if (rd < 8) {
2731: env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
2732: env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2733: } else {
2734: env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
2735: env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2736: }
2737: break;
2738: }
2739: }
2740:
2741: void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
1.1.1.5 root 2742: {
2743: unsigned int i;
1.1.1.6 root 2744: target_ulong val;
1.1.1.5 root 2745:
1.1.1.6 root 2746: helper_check_align(addr, 3);
1.1.1.5 root 2747: switch (asi) {
2748: case 0xf0: // Block load primary
2749: case 0xf1: // Block load secondary
2750: case 0xf8: // Block load primary LE
2751: case 0xf9: // Block load secondary LE
2752: if (rd & 7) {
2753: raise_exception(TT_ILL_INSN);
2754: return;
2755: }
1.1.1.6 root 2756: helper_check_align(addr, 0x3f);
1.1.1.5 root 2757: for (i = 0; i < 16; i++) {
1.1.1.6 root 2758: *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
2759: 0);
2760: addr += 4;
1.1.1.5 root 2761: }
2762:
2763: return;
2764: default:
2765: break;
2766: }
2767:
1.1.1.6 root 2768: val = helper_ld_asi(addr, asi, size, 0);
1.1.1.5 root 2769: switch(size) {
2770: default:
2771: case 4:
1.1.1.6 root 2772: *((uint32_t *)&env->fpr[rd]) = val;
1.1.1.5 root 2773: break;
2774: case 8:
1.1.1.6 root 2775: *((int64_t *)&DT0) = val;
1.1.1.5 root 2776: break;
2777: case 16:
2778: // XXX
2779: break;
1.1 root 2780: }
2781: }
1.1.1.5 root 2782:
1.1.1.6 root 2783: void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
1.1.1.5 root 2784: {
2785: unsigned int i;
1.1.1.6 root 2786: target_ulong val = 0;
1.1.1.5 root 2787:
1.1.1.6 root 2788: helper_check_align(addr, 3);
1.1.1.5 root 2789: switch (asi) {
1.1.1.6 root 2790: case 0xe0: // UA2007 Block commit store primary (cache flush)
2791: case 0xe1: // UA2007 Block commit store secondary (cache flush)
1.1.1.5 root 2792: case 0xf0: // Block store primary
2793: case 0xf1: // Block store secondary
2794: case 0xf8: // Block store primary LE
2795: case 0xf9: // Block store secondary LE
2796: if (rd & 7) {
2797: raise_exception(TT_ILL_INSN);
2798: return;
2799: }
1.1.1.6 root 2800: helper_check_align(addr, 0x3f);
1.1.1.5 root 2801: for (i = 0; i < 16; i++) {
1.1.1.6 root 2802: val = *(uint32_t *)&env->fpr[rd++];
2803: helper_st_asi(addr, val, asi & 0x8f, 4);
2804: addr += 4;
1.1.1.5 root 2805: }
2806:
2807: return;
2808: default:
2809: break;
2810: }
2811:
2812: switch(size) {
2813: default:
2814: case 4:
1.1.1.6 root 2815: val = *((uint32_t *)&env->fpr[rd]);
1.1.1.5 root 2816: break;
2817: case 8:
1.1.1.6 root 2818: val = *((int64_t *)&DT0);
1.1.1.5 root 2819: break;
2820: case 16:
2821: // XXX
2822: break;
2823: }
1.1.1.6 root 2824: helper_st_asi(addr, val, asi, size);
2825: }
2826:
2827: target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2828: target_ulong val2, uint32_t asi)
2829: {
2830: target_ulong ret;
2831:
2832: val2 &= 0xffffffffUL;
2833: ret = helper_ld_asi(addr, asi, 4, 0);
2834: ret &= 0xffffffffUL;
2835: if (val2 == ret)
2836: helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
2837: return ret;
1.1.1.5 root 2838: }
2839:
1.1.1.6 root 2840: target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2841: target_ulong val2, uint32_t asi)
2842: {
2843: target_ulong ret;
2844:
2845: ret = helper_ld_asi(addr, asi, 8, 0);
2846: if (val2 == ret)
2847: helper_st_asi(addr, val1, asi, 8);
2848: return ret;
2849: }
1.1.1.5 root 2850: #endif /* TARGET_SPARC64 */
1.1 root 2851:
2852: #ifndef TARGET_SPARC64
1.1.1.6 root 2853: void helper_rett(void)
1.1 root 2854: {
2855: unsigned int cwp;
2856:
1.1.1.5 root 2857: if (env->psret == 1)
2858: raise_exception(TT_ILL_INSN);
2859:
1.1 root 2860: env->psret = 1;
1.1.1.6 root 2861: cwp = cpu_cwp_inc(env, env->cwp + 1) ;
1.1 root 2862: if (env->wim & (1 << cwp)) {
2863: raise_exception(TT_WIN_UNF);
2864: }
2865: set_cwp(cwp);
2866: env->psrs = env->psrps;
2867: }
2868: #endif
2869:
1.1.1.6 root 2870: target_ulong helper_udiv(target_ulong a, target_ulong b)
2871: {
2872: uint64_t x0;
2873: uint32_t x1;
2874:
2875: x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2876: x1 = b;
2877:
2878: if (x1 == 0) {
2879: raise_exception(TT_DIV_ZERO);
2880: }
2881:
2882: x0 = x0 / x1;
2883: if (x0 > 0xffffffff) {
2884: env->cc_src2 = 1;
2885: return 0xffffffff;
2886: } else {
2887: env->cc_src2 = 0;
2888: return x0;
2889: }
2890: }
2891:
2892: target_ulong helper_sdiv(target_ulong a, target_ulong b)
2893: {
2894: int64_t x0;
2895: int32_t x1;
2896:
2897: x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2898: x1 = b;
2899:
2900: if (x1 == 0) {
2901: raise_exception(TT_DIV_ZERO);
2902: }
2903:
2904: x0 = x0 / x1;
2905: if ((int32_t) x0 != x0) {
2906: env->cc_src2 = 1;
2907: return x0 < 0? 0x80000000: 0x7fffffff;
2908: } else {
2909: env->cc_src2 = 0;
2910: return x0;
2911: }
2912: }
2913:
2914: void helper_stdf(target_ulong addr, int mem_idx)
2915: {
2916: helper_check_align(addr, 7);
2917: #if !defined(CONFIG_USER_ONLY)
2918: switch (mem_idx) {
2919: case 0:
2920: stfq_user(addr, DT0);
2921: break;
2922: case 1:
2923: stfq_kernel(addr, DT0);
2924: break;
2925: #ifdef TARGET_SPARC64
2926: case 2:
2927: stfq_hypv(addr, DT0);
2928: break;
2929: #endif
2930: default:
2931: break;
2932: }
2933: #else
2934: address_mask(env, &addr);
2935: stfq_raw(addr, DT0);
2936: #endif
2937: }
2938:
2939: void helper_lddf(target_ulong addr, int mem_idx)
2940: {
2941: helper_check_align(addr, 7);
2942: #if !defined(CONFIG_USER_ONLY)
2943: switch (mem_idx) {
2944: case 0:
2945: DT0 = ldfq_user(addr);
2946: break;
2947: case 1:
2948: DT0 = ldfq_kernel(addr);
2949: break;
2950: #ifdef TARGET_SPARC64
2951: case 2:
2952: DT0 = ldfq_hypv(addr);
2953: break;
2954: #endif
2955: default:
2956: break;
2957: }
2958: #else
2959: address_mask(env, &addr);
2960: DT0 = ldfq_raw(addr);
2961: #endif
2962: }
2963:
2964: void helper_ldqf(target_ulong addr, int mem_idx)
2965: {
2966: // XXX add 128 bit load
2967: CPU_QuadU u;
2968:
2969: helper_check_align(addr, 7);
2970: #if !defined(CONFIG_USER_ONLY)
2971: switch (mem_idx) {
2972: case 0:
2973: u.ll.upper = ldq_user(addr);
2974: u.ll.lower = ldq_user(addr + 8);
2975: QT0 = u.q;
2976: break;
2977: case 1:
2978: u.ll.upper = ldq_kernel(addr);
2979: u.ll.lower = ldq_kernel(addr + 8);
2980: QT0 = u.q;
2981: break;
2982: #ifdef TARGET_SPARC64
2983: case 2:
2984: u.ll.upper = ldq_hypv(addr);
2985: u.ll.lower = ldq_hypv(addr + 8);
2986: QT0 = u.q;
2987: break;
2988: #endif
2989: default:
2990: break;
2991: }
2992: #else
2993: address_mask(env, &addr);
2994: u.ll.upper = ldq_raw(addr);
2995: u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
2996: QT0 = u.q;
2997: #endif
2998: }
2999:
3000: void helper_stqf(target_ulong addr, int mem_idx)
3001: {
3002: // XXX add 128 bit store
3003: CPU_QuadU u;
3004:
3005: helper_check_align(addr, 7);
3006: #if !defined(CONFIG_USER_ONLY)
3007: switch (mem_idx) {
3008: case 0:
3009: u.q = QT0;
3010: stq_user(addr, u.ll.upper);
3011: stq_user(addr + 8, u.ll.lower);
3012: break;
3013: case 1:
3014: u.q = QT0;
3015: stq_kernel(addr, u.ll.upper);
3016: stq_kernel(addr + 8, u.ll.lower);
3017: break;
3018: #ifdef TARGET_SPARC64
3019: case 2:
3020: u.q = QT0;
3021: stq_hypv(addr, u.ll.upper);
3022: stq_hypv(addr + 8, u.ll.lower);
3023: break;
3024: #endif
3025: default:
3026: break;
3027: }
3028: #else
3029: u.q = QT0;
3030: address_mask(env, &addr);
3031: stq_raw(addr, u.ll.upper);
3032: stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
3033: #endif
3034: }
3035:
3036: static inline void set_fsr(void)
1.1 root 3037: {
3038: int rnd_mode;
1.1.1.6 root 3039:
1.1 root 3040: switch (env->fsr & FSR_RD_MASK) {
3041: case FSR_RD_NEAREST:
3042: rnd_mode = float_round_nearest_even;
1.1.1.5 root 3043: break;
1.1 root 3044: default:
3045: case FSR_RD_ZERO:
3046: rnd_mode = float_round_to_zero;
1.1.1.5 root 3047: break;
1.1 root 3048: case FSR_RD_POS:
3049: rnd_mode = float_round_up;
1.1.1.5 root 3050: break;
1.1 root 3051: case FSR_RD_NEG:
3052: rnd_mode = float_round_down;
1.1.1.5 root 3053: break;
1.1 root 3054: }
3055: set_float_rounding_mode(rnd_mode, &env->fp_status);
3056: }
3057:
1.1.1.6 root 3058: void helper_ldfsr(uint32_t new_fsr)
3059: {
3060: env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
3061: set_fsr();
3062: }
3063:
3064: #ifdef TARGET_SPARC64
3065: void helper_ldxfsr(uint64_t new_fsr)
3066: {
3067: env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
3068: set_fsr();
3069: }
3070: #endif
3071:
3072: void helper_debug(void)
1.1 root 3073: {
3074: env->exception_index = EXCP_DEBUG;
3075: cpu_loop_exit();
3076: }
3077:
3078: #ifndef TARGET_SPARC64
1.1.1.6 root 3079: /* XXX: use another pointer for %iN registers to avoid slow wrapping
3080: handling ? */
3081: void helper_save(void)
3082: {
3083: uint32_t cwp;
3084:
3085: cwp = cpu_cwp_dec(env, env->cwp - 1);
3086: if (env->wim & (1 << cwp)) {
3087: raise_exception(TT_WIN_OVF);
3088: }
3089: set_cwp(cwp);
3090: }
3091:
3092: void helper_restore(void)
3093: {
3094: uint32_t cwp;
3095:
3096: cwp = cpu_cwp_inc(env, env->cwp + 1);
3097: if (env->wim & (1 << cwp)) {
3098: raise_exception(TT_WIN_UNF);
3099: }
3100: set_cwp(cwp);
3101: }
3102:
3103: void helper_wrpsr(target_ulong new_psr)
1.1 root 3104: {
1.1.1.6 root 3105: if ((new_psr & PSR_CWP) >= env->nwindows)
1.1.1.5 root 3106: raise_exception(TT_ILL_INSN);
3107: else
1.1.1.6 root 3108: PUT_PSR(env, new_psr);
1.1 root 3109: }
3110:
1.1.1.6 root 3111: target_ulong helper_rdpsr(void)
1.1 root 3112: {
1.1.1.6 root 3113: return GET_PSR(env);
1.1 root 3114: }
3115:
3116: #else
1.1.1.6 root 3117: /* XXX: use another pointer for %iN registers to avoid slow wrapping
3118: handling ? */
3119: void helper_save(void)
3120: {
3121: uint32_t cwp;
3122:
3123: cwp = cpu_cwp_dec(env, env->cwp - 1);
3124: if (env->cansave == 0) {
3125: raise_exception(TT_SPILL | (env->otherwin != 0 ?
3126: (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3127: ((env->wstate & 0x7) << 2)));
3128: } else {
3129: if (env->cleanwin - env->canrestore == 0) {
3130: // XXX Clean windows without trap
3131: raise_exception(TT_CLRWIN);
3132: } else {
3133: env->cansave--;
3134: env->canrestore++;
3135: set_cwp(cwp);
3136: }
3137: }
3138: }
3139:
3140: void helper_restore(void)
3141: {
3142: uint32_t cwp;
3143:
3144: cwp = cpu_cwp_inc(env, env->cwp + 1);
3145: if (env->canrestore == 0) {
3146: raise_exception(TT_FILL | (env->otherwin != 0 ?
3147: (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3148: ((env->wstate & 0x7) << 2)));
3149: } else {
3150: env->cansave++;
3151: env->canrestore--;
3152: set_cwp(cwp);
3153: }
3154: }
3155:
3156: void helper_flushw(void)
3157: {
3158: if (env->cansave != env->nwindows - 2) {
3159: raise_exception(TT_SPILL | (env->otherwin != 0 ?
3160: (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3161: ((env->wstate & 0x7) << 2)));
3162: }
3163: }
3164:
3165: void helper_saved(void)
3166: {
3167: env->cansave++;
3168: if (env->otherwin == 0)
3169: env->canrestore--;
3170: else
3171: env->otherwin--;
3172: }
1.1 root 3173:
1.1.1.6 root 3174: void helper_restored(void)
1.1 root 3175: {
1.1.1.6 root 3176: env->canrestore++;
3177: if (env->cleanwin < env->nwindows - 1)
3178: env->cleanwin++;
3179: if (env->otherwin == 0)
3180: env->cansave--;
3181: else
3182: env->otherwin--;
3183: }
3184:
3185: target_ulong helper_rdccr(void)
3186: {
3187: return GET_CCR(env);
3188: }
3189:
3190: void helper_wrccr(target_ulong new_ccr)
3191: {
3192: PUT_CCR(env, new_ccr);
3193: }
3194:
3195: // CWP handling is reversed in V9, but we still use the V8 register
3196: // order.
3197: target_ulong helper_rdcwp(void)
3198: {
3199: return GET_CWP64(env);
3200: }
3201:
3202: void helper_wrcwp(target_ulong new_cwp)
3203: {
3204: PUT_CWP64(env, new_cwp);
3205: }
3206:
3207: // This function uses non-native bit order
3208: #define GET_FIELD(X, FROM, TO) \
3209: ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
3210:
3211: // This function uses the order in the manuals, i.e. bit 0 is 2^0
3212: #define GET_FIELD_SP(X, FROM, TO) \
3213: GET_FIELD(X, 63 - (TO), 63 - (FROM))
3214:
3215: target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
3216: {
3217: return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
3218: (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
3219: (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
3220: (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
3221: (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
3222: (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
3223: (((pixel_addr >> 55) & 1) << 4) |
3224: (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
3225: GET_FIELD_SP(pixel_addr, 11, 12);
3226: }
3227:
3228: target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
3229: {
3230: uint64_t tmp;
3231:
3232: tmp = addr + offset;
3233: env->gsr &= ~7ULL;
3234: env->gsr |= tmp & 7ULL;
3235: return tmp & ~7ULL;
3236: }
3237:
3238: target_ulong helper_popc(target_ulong val)
3239: {
3240: return ctpop64(val);
1.1 root 3241: }
3242:
3243: static inline uint64_t *get_gregset(uint64_t pstate)
3244: {
3245: switch (pstate) {
3246: default:
3247: case 0:
1.1.1.5 root 3248: return env->bgregs;
1.1 root 3249: case PS_AG:
1.1.1.5 root 3250: return env->agregs;
1.1 root 3251: case PS_MG:
1.1.1.5 root 3252: return env->mgregs;
1.1 root 3253: case PS_IG:
1.1.1.5 root 3254: return env->igregs;
1.1 root 3255: }
3256: }
3257:
1.1.1.5 root 3258: static inline void change_pstate(uint64_t new_pstate)
1.1 root 3259: {
1.1.1.5 root 3260: uint64_t pstate_regs, new_pstate_regs;
1.1 root 3261: uint64_t *src, *dst;
3262:
1.1.1.7 root 3263: if (env->def->features & CPU_FEATURE_GL) {
3264: // PS_AG is not implemented in this case
3265: new_pstate &= ~PS_AG;
3266: }
3267:
1.1 root 3268: pstate_regs = env->pstate & 0xc01;
3269: new_pstate_regs = new_pstate & 0xc01;
1.1.1.7 root 3270:
1.1 root 3271: if (new_pstate_regs != pstate_regs) {
1.1.1.5 root 3272: // Switch global register bank
3273: src = get_gregset(new_pstate_regs);
3274: dst = get_gregset(pstate_regs);
3275: memcpy32(dst, env->gregs);
3276: memcpy32(env->gregs, src);
1.1 root 3277: }
3278: env->pstate = new_pstate;
3279: }
3280:
1.1.1.6 root 3281: void helper_wrpstate(target_ulong new_state)
1.1.1.5 root 3282: {
1.1.1.7 root 3283: change_pstate(new_state & 0xf3f);
1.1.1.5 root 3284: }
3285:
1.1.1.6 root 3286: void helper_done(void)
1.1 root 3287: {
1.1.1.8 ! root 3288: trap_state* tsptr = cpu_tsptr(env);
! 3289:
! 3290: env->pc = tsptr->tnpc;
! 3291: env->npc = tsptr->tnpc + 4;
! 3292: PUT_CCR(env, tsptr->tstate >> 32);
! 3293: env->asi = (tsptr->tstate >> 24) & 0xff;
! 3294: change_pstate((tsptr->tstate >> 8) & 0xf3f);
! 3295: PUT_CWP64(env, tsptr->tstate & 0xff);
1.1 root 3296: env->tl--;
3297: }
3298:
1.1.1.6 root 3299: void helper_retry(void)
1.1 root 3300: {
1.1.1.8 ! root 3301: trap_state* tsptr = cpu_tsptr(env);
! 3302:
! 3303: env->pc = tsptr->tpc;
! 3304: env->npc = tsptr->tnpc;
! 3305: PUT_CCR(env, tsptr->tstate >> 32);
! 3306: env->asi = (tsptr->tstate >> 24) & 0xff;
! 3307: change_pstate((tsptr->tstate >> 8) & 0xf3f);
! 3308: PUT_CWP64(env, tsptr->tstate & 0xff);
1.1 root 3309: env->tl--;
3310: }
3311:
1.1.1.6 root 3312: void helper_set_softint(uint64_t value)
1.1 root 3313: {
1.1.1.6 root 3314: env->softint |= (uint32_t)value;
1.1 root 3315: }
3316:
1.1.1.6 root 3317: void helper_clear_softint(uint64_t value)
1.1 root 3318: {
1.1.1.6 root 3319: env->softint &= (uint32_t)~value;
3320: }
1.1 root 3321:
1.1.1.6 root 3322: void helper_write_softint(uint64_t value)
3323: {
3324: env->softint = (uint32_t)value;
3325: }
1.1 root 3326: #endif
1.1.1.6 root 3327:
3328: void helper_flush(target_ulong addr)
3329: {
3330: addr &= ~7;
3331: tb_invalidate_page_range(addr, addr + 8);
1.1 root 3332: }
3333:
3334: #ifdef TARGET_SPARC64
1.1.1.5 root 3335: #ifdef DEBUG_PCALL
1.1.1.6 root 3336: static const char * const excp_names[0x80] = {
1.1.1.5 root 3337: [TT_TFAULT] = "Instruction Access Fault",
3338: [TT_TMISS] = "Instruction Access MMU Miss",
3339: [TT_CODE_ACCESS] = "Instruction Access Error",
3340: [TT_ILL_INSN] = "Illegal Instruction",
3341: [TT_PRIV_INSN] = "Privileged Instruction",
3342: [TT_NFPU_INSN] = "FPU Disabled",
3343: [TT_FP_EXCP] = "FPU Exception",
3344: [TT_TOVF] = "Tag Overflow",
3345: [TT_CLRWIN] = "Clean Windows",
3346: [TT_DIV_ZERO] = "Division By Zero",
3347: [TT_DFAULT] = "Data Access Fault",
3348: [TT_DMISS] = "Data Access MMU Miss",
3349: [TT_DATA_ACCESS] = "Data Access Error",
3350: [TT_DPROT] = "Data Protection Error",
3351: [TT_UNALIGNED] = "Unaligned Memory Access",
3352: [TT_PRIV_ACT] = "Privileged Action",
3353: [TT_EXTINT | 0x1] = "External Interrupt 1",
3354: [TT_EXTINT | 0x2] = "External Interrupt 2",
3355: [TT_EXTINT | 0x3] = "External Interrupt 3",
3356: [TT_EXTINT | 0x4] = "External Interrupt 4",
3357: [TT_EXTINT | 0x5] = "External Interrupt 5",
3358: [TT_EXTINT | 0x6] = "External Interrupt 6",
3359: [TT_EXTINT | 0x7] = "External Interrupt 7",
3360: [TT_EXTINT | 0x8] = "External Interrupt 8",
3361: [TT_EXTINT | 0x9] = "External Interrupt 9",
3362: [TT_EXTINT | 0xa] = "External Interrupt 10",
3363: [TT_EXTINT | 0xb] = "External Interrupt 11",
3364: [TT_EXTINT | 0xc] = "External Interrupt 12",
3365: [TT_EXTINT | 0xd] = "External Interrupt 13",
3366: [TT_EXTINT | 0xe] = "External Interrupt 14",
3367: [TT_EXTINT | 0xf] = "External Interrupt 15",
3368: };
3369: #endif
3370:
1.1.1.8 ! root 3371: trap_state* cpu_tsptr(CPUState* env)
! 3372: {
! 3373: return &env->ts[env->tl & MAXTL_MASK];
! 3374: }
! 3375:
1.1.1.6 root 3376: void do_interrupt(CPUState *env)
1.1 root 3377: {
1.1.1.6 root 3378: int intno = env->exception_index;
1.1.1.8 ! root 3379: trap_state* tsptr;
1.1.1.6 root 3380:
1.1 root 3381: #ifdef DEBUG_PCALL
1.1.1.6 root 3382: if (qemu_loglevel_mask(CPU_LOG_INT)) {
1.1.1.5 root 3383: static int count;
3384: const char *name;
3385:
1.1.1.6 root 3386: if (intno < 0 || intno >= 0x180)
1.1.1.5 root 3387: name = "Unknown";
3388: else if (intno >= 0x100)
3389: name = "Trap Instruction";
3390: else if (intno >= 0xc0)
3391: name = "Window Fill";
3392: else if (intno >= 0x80)
3393: name = "Window Spill";
3394: else {
3395: name = excp_names[intno];
3396: if (!name)
3397: name = "Unknown";
3398: }
3399:
1.1.1.6 root 3400: qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
1.1.1.5 root 3401: " SP=%016" PRIx64 "\n",
3402: count, name, intno,
1.1 root 3403: env->pc,
3404: env->npc, env->regwptr[6]);
1.1.1.6 root 3405: log_cpu_state(env, 0);
1.1 root 3406: #if 0
1.1.1.5 root 3407: {
3408: int i;
3409: uint8_t *ptr;
3410:
1.1.1.6 root 3411: qemu_log(" code=");
1.1.1.5 root 3412: ptr = (uint8_t *)env->pc;
3413: for(i = 0; i < 16; i++) {
1.1.1.6 root 3414: qemu_log(" %02x", ldub(ptr + i));
1.1.1.5 root 3415: }
1.1.1.6 root 3416: qemu_log("\n");
1.1.1.5 root 3417: }
1.1 root 3418: #endif
1.1.1.5 root 3419: count++;
1.1 root 3420: }
3421: #endif
1.1.1.5 root 3422: #if !defined(CONFIG_USER_ONLY)
1.1.1.6 root 3423: if (env->tl >= env->maxtl) {
3424: cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
3425: " Error state", env->exception_index, env->tl, env->maxtl);
1.1.1.5 root 3426: return;
1.1 root 3427: }
3428: #endif
1.1.1.6 root 3429: if (env->tl < env->maxtl - 1) {
1.1.1.5 root 3430: env->tl++;
1.1 root 3431: } else {
1.1.1.5 root 3432: env->pstate |= PS_RED;
1.1.1.6 root 3433: if (env->tl < env->maxtl)
1.1.1.5 root 3434: env->tl++;
1.1 root 3435: }
1.1.1.8 ! root 3436: tsptr = cpu_tsptr(env);
! 3437:
! 3438: tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
1.1.1.6 root 3439: ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
3440: GET_CWP64(env);
1.1.1.8 ! root 3441: tsptr->tpc = env->pc;
! 3442: tsptr->tnpc = env->npc;
! 3443: tsptr->tt = intno;
1.1.1.7 root 3444:
3445: switch (intno) {
3446: case TT_IVEC:
3447: change_pstate(PS_PEF | PS_PRIV | PS_IG);
3448: break;
3449: case TT_TFAULT:
3450: case TT_TMISS:
3451: case TT_DFAULT:
3452: case TT_DMISS:
3453: case TT_DPROT:
3454: change_pstate(PS_PEF | PS_PRIV | PS_MG);
3455: break;
3456: default:
3457: change_pstate(PS_PEF | PS_PRIV | PS_AG);
3458: break;
1.1.1.6 root 3459: }
1.1.1.7 root 3460:
1.1.1.6 root 3461: if (intno == TT_CLRWIN)
3462: cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
3463: else if ((intno & 0x1c0) == TT_SPILL)
3464: cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
3465: else if ((intno & 0x1c0) == TT_FILL)
3466: cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
3467: env->tbr &= ~0x7fffULL;
3468: env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
1.1 root 3469: env->pc = env->tbr;
3470: env->npc = env->pc + 4;
3471: env->exception_index = 0;
3472: }
3473: #else
1.1.1.5 root 3474: #ifdef DEBUG_PCALL
3475: static const char * const excp_names[0x80] = {
3476: [TT_TFAULT] = "Instruction Access Fault",
3477: [TT_ILL_INSN] = "Illegal Instruction",
3478: [TT_PRIV_INSN] = "Privileged Instruction",
3479: [TT_NFPU_INSN] = "FPU Disabled",
3480: [TT_WIN_OVF] = "Window Overflow",
3481: [TT_WIN_UNF] = "Window Underflow",
3482: [TT_UNALIGNED] = "Unaligned Memory Access",
3483: [TT_FP_EXCP] = "FPU Exception",
3484: [TT_DFAULT] = "Data Access Fault",
3485: [TT_TOVF] = "Tag Overflow",
3486: [TT_EXTINT | 0x1] = "External Interrupt 1",
3487: [TT_EXTINT | 0x2] = "External Interrupt 2",
3488: [TT_EXTINT | 0x3] = "External Interrupt 3",
3489: [TT_EXTINT | 0x4] = "External Interrupt 4",
3490: [TT_EXTINT | 0x5] = "External Interrupt 5",
3491: [TT_EXTINT | 0x6] = "External Interrupt 6",
3492: [TT_EXTINT | 0x7] = "External Interrupt 7",
3493: [TT_EXTINT | 0x8] = "External Interrupt 8",
3494: [TT_EXTINT | 0x9] = "External Interrupt 9",
3495: [TT_EXTINT | 0xa] = "External Interrupt 10",
3496: [TT_EXTINT | 0xb] = "External Interrupt 11",
3497: [TT_EXTINT | 0xc] = "External Interrupt 12",
3498: [TT_EXTINT | 0xd] = "External Interrupt 13",
3499: [TT_EXTINT | 0xe] = "External Interrupt 14",
3500: [TT_EXTINT | 0xf] = "External Interrupt 15",
3501: [TT_TOVF] = "Tag Overflow",
3502: [TT_CODE_ACCESS] = "Instruction Access Error",
3503: [TT_DATA_ACCESS] = "Data Access Error",
3504: [TT_DIV_ZERO] = "Division By Zero",
3505: [TT_NCP_INSN] = "Coprocessor Disabled",
3506: };
3507: #endif
3508:
1.1.1.6 root 3509: void do_interrupt(CPUState *env)
1.1 root 3510: {
1.1.1.6 root 3511: int cwp, intno = env->exception_index;
1.1 root 3512:
3513: #ifdef DEBUG_PCALL
1.1.1.6 root 3514: if (qemu_loglevel_mask(CPU_LOG_INT)) {
1.1.1.5 root 3515: static int count;
3516: const char *name;
3517:
3518: if (intno < 0 || intno >= 0x100)
3519: name = "Unknown";
3520: else if (intno >= 0x80)
3521: name = "Trap Instruction";
3522: else {
3523: name = excp_names[intno];
3524: if (!name)
3525: name = "Unknown";
3526: }
3527:
1.1.1.6 root 3528: qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
1.1.1.5 root 3529: count, name, intno,
1.1 root 3530: env->pc,
3531: env->npc, env->regwptr[6]);
1.1.1.6 root 3532: log_cpu_state(env, 0);
1.1 root 3533: #if 0
1.1.1.5 root 3534: {
3535: int i;
3536: uint8_t *ptr;
3537:
1.1.1.6 root 3538: qemu_log(" code=");
1.1.1.5 root 3539: ptr = (uint8_t *)env->pc;
3540: for(i = 0; i < 16; i++) {
1.1.1.6 root 3541: qemu_log(" %02x", ldub(ptr + i));
1.1.1.5 root 3542: }
1.1.1.6 root 3543: qemu_log("\n");
1.1.1.5 root 3544: }
1.1 root 3545: #endif
1.1.1.5 root 3546: count++;
1.1 root 3547: }
3548: #endif
1.1.1.5 root 3549: #if !defined(CONFIG_USER_ONLY)
1.1 root 3550: if (env->psret == 0) {
1.1.1.6 root 3551: cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
3552: env->exception_index);
1.1.1.5 root 3553: return;
1.1 root 3554: }
3555: #endif
3556: env->psret = 0;
1.1.1.6 root 3557: cwp = cpu_cwp_dec(env, env->cwp - 1);
3558: cpu_set_cwp(env, cwp);
1.1 root 3559: env->regwptr[9] = env->pc;
3560: env->regwptr[10] = env->npc;
3561: env->psrps = env->psrs;
3562: env->psrs = 1;
3563: env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
3564: env->pc = env->tbr;
3565: env->npc = env->pc + 4;
3566: env->exception_index = 0;
3567: }
3568: #endif
3569:
1.1.1.5 root 3570: #if !defined(CONFIG_USER_ONLY)
3571:
3572: static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3573: void *retaddr);
1.1 root 3574:
3575: #define MMUSUFFIX _mmu
1.1.1.5 root 3576: #define ALIGNED_ONLY
1.1 root 3577:
3578: #define SHIFT 0
3579: #include "softmmu_template.h"
3580:
3581: #define SHIFT 1
3582: #include "softmmu_template.h"
3583:
3584: #define SHIFT 2
3585: #include "softmmu_template.h"
3586:
3587: #define SHIFT 3
3588: #include "softmmu_template.h"
3589:
1.1.1.6 root 3590: /* XXX: make it generic ? */
3591: static void cpu_restore_state2(void *retaddr)
3592: {
3593: TranslationBlock *tb;
3594: unsigned long pc;
3595:
3596: if (retaddr) {
3597: /* now we have a real cpu fault */
3598: pc = (unsigned long)retaddr;
3599: tb = tb_find_pc(pc);
3600: if (tb) {
3601: /* the PC is inside the translated code. It means that we have
3602: a virtual CPU fault */
3603: cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
3604: }
3605: }
3606: }
3607:
1.1.1.5 root 3608: static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3609: void *retaddr)
3610: {
3611: #ifdef DEBUG_UNALIGNED
1.1.1.6 root 3612: printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
3613: "\n", addr, env->pc);
1.1.1.5 root 3614: #endif
1.1.1.6 root 3615: cpu_restore_state2(retaddr);
1.1.1.5 root 3616: raise_exception(TT_UNALIGNED);
3617: }
1.1 root 3618:
3619: /* try to fill the TLB and return an exception if error. If retaddr is
3620: NULL, it means that the function was called in C code (i.e. not
3621: from generated code or from helper.c) */
3622: /* XXX: fix it to restore all registers */
1.1.1.5 root 3623: void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1.1 root 3624: {
3625: int ret;
3626: CPUState *saved_env;
3627:
3628: /* XXX: hack to restore env in all cases, even if not called from
3629: generated code */
3630: saved_env = env;
3631: env = cpu_single_env;
3632:
1.1.1.5 root 3633: ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1.1 root 3634: if (ret) {
1.1.1.6 root 3635: cpu_restore_state2(retaddr);
1.1 root 3636: cpu_loop_exit();
3637: }
3638: env = saved_env;
3639: }
3640:
3641: #endif
1.1.1.5 root 3642:
3643: #ifndef TARGET_SPARC64
3644: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1.1.1.6 root 3645: int is_asi, int size)
1.1.1.5 root 3646: {
3647: CPUState *saved_env;
3648:
3649: /* XXX: hack to restore env in all cases, even if not called from
3650: generated code */
3651: saved_env = env;
3652: env = cpu_single_env;
3653: #ifdef DEBUG_UNASSIGNED
3654: if (is_asi)
1.1.1.6 root 3655: printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3656: " asi 0x%02x from " TARGET_FMT_lx "\n",
3657: is_exec ? "exec" : is_write ? "write" : "read", size,
3658: size == 1 ? "" : "s", addr, is_asi, env->pc);
1.1.1.5 root 3659: else
1.1.1.6 root 3660: printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3661: " from " TARGET_FMT_lx "\n",
3662: is_exec ? "exec" : is_write ? "write" : "read", size,
3663: size == 1 ? "" : "s", addr, env->pc);
1.1.1.5 root 3664: #endif
3665: if (env->mmuregs[3]) /* Fault status register */
3666: env->mmuregs[3] = 1; /* overflow (not read before another fault) */
3667: if (is_asi)
3668: env->mmuregs[3] |= 1 << 16;
3669: if (env->psrs)
3670: env->mmuregs[3] |= 1 << 5;
3671: if (is_exec)
3672: env->mmuregs[3] |= 1 << 6;
3673: if (is_write)
3674: env->mmuregs[3] |= 1 << 7;
3675: env->mmuregs[3] |= (5 << 2) | 2;
3676: env->mmuregs[4] = addr; /* Fault address register */
3677: if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
3678: if (is_exec)
3679: raise_exception(TT_CODE_ACCESS);
3680: else
3681: raise_exception(TT_DATA_ACCESS);
3682: }
3683: env = saved_env;
3684: }
3685: #else
3686: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1.1.1.6 root 3687: int is_asi, int size)
1.1.1.5 root 3688: {
3689: #ifdef DEBUG_UNASSIGNED
3690: CPUState *saved_env;
3691:
3692: /* XXX: hack to restore env in all cases, even if not called from
3693: generated code */
3694: saved_env = env;
3695: env = cpu_single_env;
1.1.1.6 root 3696: printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
3697: "\n", addr, env->pc);
1.1.1.5 root 3698: env = saved_env;
3699: #endif
3700: if (is_exec)
3701: raise_exception(TT_CODE_ACCESS);
3702: else
3703: raise_exception(TT_DATA_ACCESS);
3704: }
3705: #endif
3706:
1.1.1.6 root 3707: #ifdef TARGET_SPARC64
3708: void helper_tick_set_count(void *opaque, uint64_t count)
3709: {
3710: #if !defined(CONFIG_USER_ONLY)
3711: cpu_tick_set_count(opaque, count);
3712: #endif
3713: }
3714:
3715: uint64_t helper_tick_get_count(void *opaque)
3716: {
3717: #if !defined(CONFIG_USER_ONLY)
3718: return cpu_tick_get_count(opaque);
3719: #else
3720: return 0;
3721: #endif
3722: }
3723:
3724: void helper_tick_set_limit(void *opaque, uint64_t limit)
3725: {
3726: #if !defined(CONFIG_USER_ONLY)
3727: cpu_tick_set_limit(opaque, limit);
3728: #endif
3729: }
3730: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.