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