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