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