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