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