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