Report normalised CWP values to userland and GDB, not internal representation
[qemu] / target-sparc / op_helper.c
1 #include "exec.h"
2
3 //#define DEBUG_PCALL
4 //#define DEBUG_MMU
5 //#define DEBUG_UNALIGNED
6 //#define DEBUG_UNASSIGNED
7
8 void raise_exception(int tt)
9 {
10     env->exception_index = tt;
11     cpu_loop_exit();
12 }   
13
14 void check_ieee_exceptions()
15 {
16      T0 = get_float_exception_flags(&env->fp_status);
17      if (T0)
18      {
19         /* Copy IEEE 754 flags into FSR */
20         if (T0 & float_flag_invalid)
21             env->fsr |= FSR_NVC;
22         if (T0 & float_flag_overflow)
23             env->fsr |= FSR_OFC;
24         if (T0 & float_flag_underflow)
25             env->fsr |= FSR_UFC;
26         if (T0 & float_flag_divbyzero)
27             env->fsr |= FSR_DZC;
28         if (T0 & float_flag_inexact)
29             env->fsr |= FSR_NXC;
30
31         if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23))
32         {
33             /* Unmasked exception, generate a trap */
34             env->fsr |= FSR_FTT_IEEE_EXCP;
35             raise_exception(TT_FP_EXCP);
36         }
37         else
38         {
39             /* Accumulate exceptions */
40             env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
41         }
42      }
43 }
44
45 #ifdef USE_INT_TO_FLOAT_HELPERS
46 void do_fitos(void)
47 {
48     set_float_exception_flags(0, &env->fp_status);
49     FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
50     check_ieee_exceptions();
51 }
52
53 void do_fitod(void)
54 {
55     DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
56 }
57 #endif
58
59 void do_fabss(void)
60 {
61     FT0 = float32_abs(FT1);
62 }
63
64 #ifdef TARGET_SPARC64
65 void do_fabsd(void)
66 {
67     DT0 = float64_abs(DT1);
68 }
69 #endif
70
71 void do_fsqrts(void)
72 {
73     set_float_exception_flags(0, &env->fp_status);
74     FT0 = float32_sqrt(FT1, &env->fp_status);
75     check_ieee_exceptions();
76 }
77
78 void do_fsqrtd(void)
79 {
80     set_float_exception_flags(0, &env->fp_status);
81     DT0 = float64_sqrt(DT1, &env->fp_status);
82     check_ieee_exceptions();
83 }
84
85 #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
86     void glue(do_, name) (void)                                         \
87     {                                                                   \
88         env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
89         switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
90         case float_relation_unordered:                                  \
91             T0 = (FSR_FCC1 | FSR_FCC0) << FS;                           \
92             if ((env->fsr & FSR_NVM) || TRAP) {                         \
93                 env->fsr |= T0;                                         \
94                 env->fsr |= FSR_NVC;                                    \
95                 env->fsr |= FSR_FTT_IEEE_EXCP;                          \
96                 raise_exception(TT_FP_EXCP);                            \
97             } else {                                                    \
98                 env->fsr |= FSR_NVA;                                    \
99             }                                                           \
100             break;                                                      \
101         case float_relation_less:                                       \
102             T0 = FSR_FCC0 << FS;                                        \
103             break;                                                      \
104         case float_relation_greater:                                    \
105             T0 = FSR_FCC1 << FS;                                        \
106             break;                                                      \
107         default:                                                        \
108             T0 = 0;                                                     \
109             break;                                                      \
110         }                                                               \
111         env->fsr |= T0;                                                 \
112     }
113
114 GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
115 GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
116
117 GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
118 GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
119
120 #ifdef TARGET_SPARC64
121 GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
122 GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
123
124 GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
125 GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
126
127 GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
128 GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
129
130 GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
131 GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
132
133 GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
134 GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
135
136 GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
137 GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
138 #endif
139
140 #if defined(CONFIG_USER_ONLY) 
141 void helper_ld_asi(int asi, int size, int sign)
142 {
143 }
144
145 void helper_st_asi(int asi, int size, int sign)
146 {
147 }
148 #else
149 #ifndef TARGET_SPARC64
150 void helper_ld_asi(int asi, int size, int sign)
151 {
152     uint32_t ret = 0;
153
154     switch (asi) {
155     case 2: /* SuperSparc MXCC registers */
156         break;
157     case 3: /* MMU probe */
158         {
159             int mmulev;
160
161             mmulev = (T0 >> 8) & 15;
162             if (mmulev > 4)
163                 ret = 0;
164             else {
165                 ret = mmu_probe(env, T0, mmulev);
166                 //bswap32s(&ret);
167             }
168 #ifdef DEBUG_MMU
169             printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
170 #endif
171         }
172         break;
173     case 4: /* read MMU regs */
174         {
175             int reg = (T0 >> 8) & 0xf;
176             
177             ret = env->mmuregs[reg];
178             if (reg == 3) /* Fault status cleared on read */
179                 env->mmuregs[reg] = 0;
180 #ifdef DEBUG_MMU
181             printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
182 #endif
183         }
184         break;
185     case 9: /* Supervisor code access */
186         switch(size) {
187         case 1:
188             ret = ldub_code(T0);
189             break;
190         case 2:
191             ret = lduw_code(T0 & ~1);
192             break;
193         default:
194         case 4:
195             ret = ldl_code(T0 & ~3);
196             break;
197         case 8:
198             ret = ldl_code(T0 & ~3);
199             T0 = ldl_code((T0 + 4) & ~3);
200             break;
201         }
202         break;
203     case 0xc: /* I-cache tag */
204     case 0xd: /* I-cache data */
205     case 0xe: /* D-cache tag */
206     case 0xf: /* D-cache data */
207         break;
208     case 0x20: /* MMU passthrough */
209         switch(size) {
210         case 1:
211             ret = ldub_phys(T0);
212             break;
213         case 2:
214             ret = lduw_phys(T0 & ~1);
215             break;
216         default:
217         case 4:
218             ret = ldl_phys(T0 & ~3);
219             break;
220         case 8:
221             ret = ldl_phys(T0 & ~3);
222             T0 = ldl_phys((T0 + 4) & ~3);
223             break;
224         }
225         break;
226     case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
227     case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
228         switch(size) {
229         case 1:
230             ret = ldub_phys((target_phys_addr_t)T0
231                             | ((target_phys_addr_t)(asi & 0xf) << 32));
232             break;
233         case 2:
234             ret = lduw_phys((target_phys_addr_t)(T0 & ~1)
235                             | ((target_phys_addr_t)(asi & 0xf) << 32));
236             break;
237         default:
238         case 4:
239             ret = ldl_phys((target_phys_addr_t)(T0 & ~3)
240                            | ((target_phys_addr_t)(asi & 0xf) << 32));
241             break;
242         case 8:
243             ret = ldl_phys((target_phys_addr_t)(T0 & ~3)
244                            | ((target_phys_addr_t)(asi & 0xf) << 32));
245             T0 = ldl_phys((target_phys_addr_t)((T0 + 4) & ~3)
246                            | ((target_phys_addr_t)(asi & 0xf) << 32));
247             break;
248         }
249         break;
250     case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
251     default:
252         do_unassigned_access(T0, 0, 0, 1);
253         ret = 0;
254         break;
255     }
256     T1 = ret;
257 }
258
259 void helper_st_asi(int asi, int size, int sign)
260 {
261     switch(asi) {
262     case 2: /* SuperSparc MXCC registers */
263         break;
264     case 3: /* MMU flush */
265         {
266             int mmulev;
267
268             mmulev = (T0 >> 8) & 15;
269 #ifdef DEBUG_MMU
270             printf("mmu flush level %d\n", mmulev);
271 #endif
272             switch (mmulev) {
273             case 0: // flush page
274                 tlb_flush_page(env, T0 & 0xfffff000);
275                 break;
276             case 1: // flush segment (256k)
277             case 2: // flush region (16M)
278             case 3: // flush context (4G)
279             case 4: // flush entire
280                 tlb_flush(env, 1);
281                 break;
282             default:
283                 break;
284             }
285 #ifdef DEBUG_MMU
286             dump_mmu(env);
287 #endif
288             return;
289         }
290     case 4: /* write MMU regs */
291         {
292             int reg = (T0 >> 8) & 0xf;
293             uint32_t oldreg;
294             
295             oldreg = env->mmuregs[reg];
296             switch(reg) {
297             case 0:
298                 env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
299                 env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
300                 // Mappings generated during no-fault mode or MMU
301                 // disabled mode are invalid in normal mode
302                 if (oldreg != env->mmuregs[reg])
303                     tlb_flush(env, 1);
304                 break;
305             case 2:
306                 env->mmuregs[reg] = T1;
307                 if (oldreg != env->mmuregs[reg]) {
308                     /* we flush when the MMU context changes because
309                        QEMU has no MMU context support */
310                     tlb_flush(env, 1);
311                 }
312                 break;
313             case 3:
314             case 4:
315                 break;
316             default:
317                 env->mmuregs[reg] = T1;
318                 break;
319             }
320 #ifdef DEBUG_MMU
321             if (oldreg != env->mmuregs[reg]) {
322                 printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
323             }
324             dump_mmu(env);
325 #endif
326             return;
327         }
328     case 0xc: /* I-cache tag */
329     case 0xd: /* I-cache data */
330     case 0xe: /* D-cache tag */
331     case 0xf: /* D-cache data */
332     case 0x10: /* I/D-cache flush page */
333     case 0x11: /* I/D-cache flush segment */
334     case 0x12: /* I/D-cache flush region */
335     case 0x13: /* I/D-cache flush context */
336     case 0x14: /* I/D-cache flush user */
337         break;
338     case 0x17: /* Block copy, sta access */
339         {
340             // value (T1) = src
341             // address (T0) = dst
342             // copy 32 bytes
343             unsigned int i;
344             uint32_t src = T1 & ~3, dst = T0 & ~3, temp;
345             
346             for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
347                 temp = ldl_kernel(src);
348                 stl_kernel(dst, temp);
349             }
350         }
351         return;
352     case 0x1f: /* Block fill, stda access */
353         {
354             // value (T1, T2)
355             // address (T0) = dst
356             // fill 32 bytes
357             unsigned int i;
358             uint32_t dst = T0 & 7;
359             uint64_t val;
360
361             val = (((uint64_t)T1) << 32) | T2;
362
363             for (i = 0; i < 32; i += 8, dst += 8)
364                 stq_kernel(dst, val);
365         }
366         return;
367     case 0x20: /* MMU passthrough */
368         {
369             switch(size) {
370             case 1:
371                 stb_phys(T0, T1);
372                 break;
373             case 2:
374                 stw_phys(T0 & ~1, T1);
375                 break;
376             case 4:
377             default:
378                 stl_phys(T0 & ~3, T1);
379                 break;
380             case 8:
381                 stl_phys(T0 & ~3, T1);
382                 stl_phys((T0 + 4) & ~3, T2);
383                 break;
384             }
385         }
386         return;
387     case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
388     case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
389         {
390             switch(size) {
391             case 1:
392                 stb_phys((target_phys_addr_t)T0
393                          | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
394                 break;
395             case 2:
396                 stw_phys((target_phys_addr_t)(T0 & ~1)
397                             | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
398                 break;
399             case 4:
400             default:
401                 stl_phys((target_phys_addr_t)(T0 & ~3)
402                            | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
403                 break;
404             case 8:
405                 stl_phys((target_phys_addr_t)(T0 & ~3)
406                            | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
407                 stl_phys((target_phys_addr_t)((T0 + 4) & ~3)
408                            | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
409                 break;
410             }
411         }
412         return;
413     case 0x31: /* Ross RT620 I-cache flush */
414     case 0x36: /* I-cache flash clear */
415     case 0x37: /* D-cache flash clear */
416         break;
417     case 9: /* Supervisor code access, XXX */
418     case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
419     default:
420         do_unassigned_access(T0, 1, 0, 1);
421         return;
422     }
423 }
424
425 #else
426
427 void helper_ld_asi(int asi, int size, int sign)
428 {
429     uint64_t ret = 0;
430
431     if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
432         raise_exception(TT_PRIV_ACT);
433
434     switch (asi) {
435     case 0x14: // Bypass
436     case 0x15: // Bypass, non-cacheable
437         {
438             switch(size) {
439             case 1:
440                 ret = ldub_phys(T0);
441                 break;
442             case 2:
443                 ret = lduw_phys(T0 & ~1);
444                 break;
445             case 4:
446                 ret = ldl_phys(T0 & ~3);
447                 break;
448             default:
449             case 8:
450                 ret = ldq_phys(T0 & ~7);
451                 break;
452             }
453             break;
454         }
455     case 0x04: // Nucleus
456     case 0x0c: // Nucleus Little Endian (LE)
457     case 0x10: // As if user primary
458     case 0x11: // As if user secondary
459     case 0x18: // As if user primary LE
460     case 0x19: // As if user secondary LE
461     case 0x1c: // Bypass LE
462     case 0x1d: // Bypass, non-cacheable LE
463     case 0x24: // Nucleus quad LDD 128 bit atomic
464     case 0x2c: // Nucleus quad LDD 128 bit atomic
465     case 0x4a: // UPA config
466     case 0x82: // Primary no-fault
467     case 0x83: // Secondary no-fault
468     case 0x88: // Primary LE
469     case 0x89: // Secondary LE
470     case 0x8a: // Primary no-fault LE
471     case 0x8b: // Secondary no-fault LE
472         // XXX
473         break;
474     case 0x45: // LSU
475         ret = env->lsu;
476         break;
477     case 0x50: // I-MMU regs
478         {
479             int reg = (T0 >> 3) & 0xf;
480
481             ret = env->immuregs[reg];
482             break;
483         }
484     case 0x51: // I-MMU 8k TSB pointer
485     case 0x52: // I-MMU 64k TSB pointer
486     case 0x55: // I-MMU data access
487         // XXX
488         break;
489     case 0x56: // I-MMU tag read
490         {
491             unsigned int i;
492             
493             for (i = 0; i < 64; i++) {
494                 // Valid, ctx match, vaddr match
495                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
496                     env->itlb_tag[i] == T0) {
497                     ret = env->itlb_tag[i];
498                     break;
499                 }
500             }
501             break;
502         }
503     case 0x58: // D-MMU regs
504         {
505             int reg = (T0 >> 3) & 0xf;
506
507             ret = env->dmmuregs[reg];
508             break;
509         }
510     case 0x5e: // D-MMU tag read
511         {
512             unsigned int i;
513             
514             for (i = 0; i < 64; i++) {
515                 // Valid, ctx match, vaddr match
516                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
517                     env->dtlb_tag[i] == T0) {
518                     ret = env->dtlb_tag[i];
519                     break;
520                 }
521             }
522             break;
523         }
524     case 0x59: // D-MMU 8k TSB pointer
525     case 0x5a: // D-MMU 64k TSB pointer
526     case 0x5b: // D-MMU data pointer
527     case 0x5d: // D-MMU data access
528     case 0x48: // Interrupt dispatch, RO
529     case 0x49: // Interrupt data receive
530     case 0x7f: // Incoming interrupt vector, RO
531         // XXX
532         break;
533     case 0x54: // I-MMU data in, WO
534     case 0x57: // I-MMU demap, WO
535     case 0x5c: // D-MMU data in, WO
536     case 0x5f: // D-MMU demap, WO
537     case 0x77: // Interrupt vector, WO
538     default:
539         do_unassigned_access(T0, 0, 0, 1);
540         ret = 0;
541         break;
542     }
543     T1 = ret;
544 }
545
546 void helper_st_asi(int asi, int size, int sign)
547 {
548     if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
549         raise_exception(TT_PRIV_ACT);
550
551     switch(asi) {
552     case 0x14: // Bypass
553     case 0x15: // Bypass, non-cacheable
554         {
555             switch(size) {
556             case 1:
557                 stb_phys(T0, T1);
558                 break;
559             case 2:
560                 stw_phys(T0 & ~1, T1);
561                 break;
562             case 4:
563                 stl_phys(T0 & ~3, T1);
564                 break;
565             case 8:
566             default:
567                 stq_phys(T0 & ~7, T1);
568                 break;
569             }
570         }
571         return;
572     case 0x04: // Nucleus
573     case 0x0c: // Nucleus Little Endian (LE)
574     case 0x10: // As if user primary
575     case 0x11: // As if user secondary
576     case 0x18: // As if user primary LE
577     case 0x19: // As if user secondary LE
578     case 0x1c: // Bypass LE
579     case 0x1d: // Bypass, non-cacheable LE
580     case 0x24: // Nucleus quad LDD 128 bit atomic
581     case 0x2c: // Nucleus quad LDD 128 bit atomic
582     case 0x4a: // UPA config
583     case 0x88: // Primary LE
584     case 0x89: // Secondary LE
585         // XXX
586         return;
587     case 0x45: // LSU
588         {
589             uint64_t oldreg;
590
591             oldreg = env->lsu;
592             env->lsu = T1 & (DMMU_E | IMMU_E);
593             // Mappings generated during D/I MMU disabled mode are
594             // invalid in normal mode
595             if (oldreg != env->lsu) {
596 #ifdef DEBUG_MMU
597                 printf("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
598                 dump_mmu(env);
599 #endif
600                 tlb_flush(env, 1);
601             }
602             return;
603         }
604     case 0x50: // I-MMU regs
605         {
606             int reg = (T0 >> 3) & 0xf;
607             uint64_t oldreg;
608             
609             oldreg = env->immuregs[reg];
610             switch(reg) {
611             case 0: // RO
612             case 4:
613                 return;
614             case 1: // Not in I-MMU
615             case 2:
616             case 7:
617             case 8:
618                 return;
619             case 3: // SFSR
620                 if ((T1 & 1) == 0)
621                     T1 = 0; // Clear SFSR
622                 break;
623             case 5: // TSB access
624             case 6: // Tag access
625             default:
626                 break;
627             }
628             env->immuregs[reg] = T1;
629 #ifdef DEBUG_MMU
630             if (oldreg != env->immuregs[reg]) {
631                 printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
632             }
633             dump_mmu(env);
634 #endif
635             return;
636         }
637     case 0x54: // I-MMU data in
638         {
639             unsigned int i;
640
641             // Try finding an invalid entry
642             for (i = 0; i < 64; i++) {
643                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
644                     env->itlb_tag[i] = env->immuregs[6];
645                     env->itlb_tte[i] = T1;
646                     return;
647                 }
648             }
649             // Try finding an unlocked entry
650             for (i = 0; i < 64; i++) {
651                 if ((env->itlb_tte[i] & 0x40) == 0) {
652                     env->itlb_tag[i] = env->immuregs[6];
653                     env->itlb_tte[i] = T1;
654                     return;
655                 }
656             }
657             // error state?
658             return;
659         }
660     case 0x55: // I-MMU data access
661         {
662             unsigned int i = (T0 >> 3) & 0x3f;
663
664             env->itlb_tag[i] = env->immuregs[6];
665             env->itlb_tte[i] = T1;
666             return;
667         }
668     case 0x57: // I-MMU demap
669         // XXX
670         return;
671     case 0x58: // D-MMU regs
672         {
673             int reg = (T0 >> 3) & 0xf;
674             uint64_t oldreg;
675             
676             oldreg = env->dmmuregs[reg];
677             switch(reg) {
678             case 0: // RO
679             case 4:
680                 return;
681             case 3: // SFSR
682                 if ((T1 & 1) == 0) {
683                     T1 = 0; // Clear SFSR, Fault address
684                     env->dmmuregs[4] = 0;
685                 }
686                 env->dmmuregs[reg] = T1;
687                 break;
688             case 1: // Primary context
689             case 2: // Secondary context
690             case 5: // TSB access
691             case 6: // Tag access
692             case 7: // Virtual Watchpoint
693             case 8: // Physical Watchpoint
694             default:
695                 break;
696             }
697             env->dmmuregs[reg] = T1;
698 #ifdef DEBUG_MMU
699             if (oldreg != env->dmmuregs[reg]) {
700                 printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
701             }
702             dump_mmu(env);
703 #endif
704             return;
705         }
706     case 0x5c: // D-MMU data in
707         {
708             unsigned int i;
709
710             // Try finding an invalid entry
711             for (i = 0; i < 64; i++) {
712                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
713                     env->dtlb_tag[i] = env->dmmuregs[6];
714                     env->dtlb_tte[i] = T1;
715                     return;
716                 }
717             }
718             // Try finding an unlocked entry
719             for (i = 0; i < 64; i++) {
720                 if ((env->dtlb_tte[i] & 0x40) == 0) {
721                     env->dtlb_tag[i] = env->dmmuregs[6];
722                     env->dtlb_tte[i] = T1;
723                     return;
724                 }
725             }
726             // error state?
727             return;
728         }
729     case 0x5d: // D-MMU data access
730         {
731             unsigned int i = (T0 >> 3) & 0x3f;
732
733             env->dtlb_tag[i] = env->dmmuregs[6];
734             env->dtlb_tte[i] = T1;
735             return;
736         }
737     case 0x5f: // D-MMU demap
738     case 0x49: // Interrupt data receive
739         // XXX
740         return;
741     case 0x51: // I-MMU 8k TSB pointer, RO
742     case 0x52: // I-MMU 64k TSB pointer, RO
743     case 0x56: // I-MMU tag read, RO
744     case 0x59: // D-MMU 8k TSB pointer, RO
745     case 0x5a: // D-MMU 64k TSB pointer, RO
746     case 0x5b: // D-MMU data pointer, RO
747     case 0x5e: // D-MMU tag read, RO
748     case 0x48: // Interrupt dispatch, RO
749     case 0x7f: // Incoming interrupt vector, RO
750     case 0x82: // Primary no-fault, RO
751     case 0x83: // Secondary no-fault, RO
752     case 0x8a: // Primary no-fault LE, RO
753     case 0x8b: // Secondary no-fault LE, RO
754     default:
755         do_unassigned_access(T0, 1, 0, 1);
756         return;
757     }
758 }
759 #endif
760 #endif /* !CONFIG_USER_ONLY */
761
762 #ifndef TARGET_SPARC64
763 void helper_rett()
764 {
765     unsigned int cwp;
766
767     if (env->psret == 1)
768         raise_exception(TT_ILL_INSN);
769
770     env->psret = 1;
771     cwp = (env->cwp + 1) & (NWINDOWS - 1); 
772     if (env->wim & (1 << cwp)) {
773         raise_exception(TT_WIN_UNF);
774     }
775     set_cwp(cwp);
776     env->psrs = env->psrps;
777 }
778 #endif
779
780 void helper_ldfsr(void)
781 {
782     int rnd_mode;
783     switch (env->fsr & FSR_RD_MASK) {
784     case FSR_RD_NEAREST:
785         rnd_mode = float_round_nearest_even;
786         break;
787     default:
788     case FSR_RD_ZERO:
789         rnd_mode = float_round_to_zero;
790         break;
791     case FSR_RD_POS:
792         rnd_mode = float_round_up;
793         break;
794     case FSR_RD_NEG:
795         rnd_mode = float_round_down;
796         break;
797     }
798     set_float_rounding_mode(rnd_mode, &env->fp_status);
799 }
800
801 void helper_debug()
802 {
803     env->exception_index = EXCP_DEBUG;
804     cpu_loop_exit();
805 }
806
807 #ifndef TARGET_SPARC64
808 void do_wrpsr()
809 {
810     if ((T0 & PSR_CWP) >= NWINDOWS)
811         raise_exception(TT_ILL_INSN);
812     else
813         PUT_PSR(env, T0);
814 }
815
816 void do_rdpsr()
817 {
818     T0 = GET_PSR(env);
819 }
820
821 #else
822
823 void do_popc()
824 {
825     T0 = (T1 & 0x5555555555555555ULL) + ((T1 >> 1) & 0x5555555555555555ULL);
826     T0 = (T0 & 0x3333333333333333ULL) + ((T0 >> 2) & 0x3333333333333333ULL);
827     T0 = (T0 & 0x0f0f0f0f0f0f0f0fULL) + ((T0 >> 4) & 0x0f0f0f0f0f0f0f0fULL);
828     T0 = (T0 & 0x00ff00ff00ff00ffULL) + ((T0 >> 8) & 0x00ff00ff00ff00ffULL);
829     T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
830     T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
831 }
832
833 static inline uint64_t *get_gregset(uint64_t pstate)
834 {
835     switch (pstate) {
836     default:
837     case 0:
838         return env->bgregs;
839     case PS_AG:
840         return env->agregs;
841     case PS_MG:
842         return env->mgregs;
843     case PS_IG:
844         return env->igregs;
845     }
846 }
847
848 void do_wrpstate()
849 {
850     uint64_t new_pstate, pstate_regs, new_pstate_regs;
851     uint64_t *src, *dst;
852
853     new_pstate = T0 & 0xf3f;
854     pstate_regs = env->pstate & 0xc01;
855     new_pstate_regs = new_pstate & 0xc01;
856     if (new_pstate_regs != pstate_regs) {
857         // Switch global register bank
858         src = get_gregset(new_pstate_regs);
859         dst = get_gregset(pstate_regs);
860         memcpy32(dst, env->gregs);
861         memcpy32(env->gregs, src);
862     }
863     env->pstate = new_pstate;
864 }
865
866 void do_done(void)
867 {
868     env->tl--;
869     env->pc = env->tnpc[env->tl];
870     env->npc = env->tnpc[env->tl] + 4;
871     PUT_CCR(env, env->tstate[env->tl] >> 32);
872     env->asi = (env->tstate[env->tl] >> 24) & 0xff;
873     env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
874     PUT_CWP64(env, env->tstate[env->tl] & 0xff);
875 }
876
877 void do_retry(void)
878 {
879     env->tl--;
880     env->pc = env->tpc[env->tl];
881     env->npc = env->tnpc[env->tl];
882     PUT_CCR(env, env->tstate[env->tl] >> 32);
883     env->asi = (env->tstate[env->tl] >> 24) & 0xff;
884     env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
885     PUT_CWP64(env, env->tstate[env->tl] & 0xff);
886 }
887 #endif
888
889 void set_cwp(int new_cwp)
890 {
891     /* put the modified wrap registers at their proper location */
892     if (env->cwp == (NWINDOWS - 1))
893         memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
894     env->cwp = new_cwp;
895     /* put the wrap registers at their temporary location */
896     if (new_cwp == (NWINDOWS - 1))
897         memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
898     env->regwptr = env->regbase + (new_cwp * 16);
899     REGWPTR = env->regwptr;
900 }
901
902 void cpu_set_cwp(CPUState *env1, int new_cwp)
903 {
904     CPUState *saved_env;
905 #ifdef reg_REGWPTR
906     target_ulong *saved_regwptr;
907 #endif
908
909     saved_env = env;
910 #ifdef reg_REGWPTR
911     saved_regwptr = REGWPTR;
912 #endif
913     env = env1;
914     set_cwp(new_cwp);
915     env = saved_env;
916 #ifdef reg_REGWPTR
917     REGWPTR = saved_regwptr;
918 #endif
919 }
920
921 #ifdef TARGET_SPARC64
922 void do_interrupt(int intno)
923 {
924 #ifdef DEBUG_PCALL
925     if (loglevel & CPU_LOG_INT) {
926         static int count;
927         fprintf(logfile, "%6d: v=%04x pc=%016" PRIx64 " npc=%016" PRIx64 " SP=%016" PRIx64 "\n",
928                 count, intno,
929                 env->pc,
930                 env->npc, env->regwptr[6]);
931         cpu_dump_state(env, logfile, fprintf, 0);
932 #if 0
933         {
934             int i;
935             uint8_t *ptr;
936
937             fprintf(logfile, "       code=");
938             ptr = (uint8_t *)env->pc;
939             for(i = 0; i < 16; i++) {
940                 fprintf(logfile, " %02x", ldub(ptr + i));
941             }
942             fprintf(logfile, "\n");
943         }
944 #endif
945         count++;
946     }
947 #endif
948 #if !defined(CONFIG_USER_ONLY) 
949     if (env->tl == MAXTL) {
950         cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
951         return;
952     }
953 #endif
954     env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
955         ((env->pstate & 0xfff) << 8) | GET_CWP64(env);
956     env->tpc[env->tl] = env->pc;
957     env->tnpc[env->tl] = env->npc;
958     env->tt[env->tl] = intno;
959     env->pstate = PS_PEF | PS_PRIV | PS_AG;
960     env->tbr &= ~0x7fffULL;
961     env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
962     if (env->tl < MAXTL - 1) {
963         env->tl++;
964     } else {
965         env->pstate |= PS_RED;
966         if (env->tl != MAXTL)
967             env->tl++;
968     }
969     env->pc = env->tbr;
970     env->npc = env->pc + 4;
971     env->exception_index = 0;
972 }
973 #else
974 void do_interrupt(int intno)
975 {
976     int cwp;
977
978 #ifdef DEBUG_PCALL
979     if (loglevel & CPU_LOG_INT) {
980         static int count;
981         fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
982                 count, intno,
983                 env->pc,
984                 env->npc, env->regwptr[6]);
985         cpu_dump_state(env, logfile, fprintf, 0);
986 #if 0
987         {
988             int i;
989             uint8_t *ptr;
990
991             fprintf(logfile, "       code=");
992             ptr = (uint8_t *)env->pc;
993             for(i = 0; i < 16; i++) {
994                 fprintf(logfile, " %02x", ldub(ptr + i));
995             }
996             fprintf(logfile, "\n");
997         }
998 #endif
999         count++;
1000     }
1001 #endif
1002 #if !defined(CONFIG_USER_ONLY) 
1003     if (env->psret == 0) {
1004         cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
1005         return;
1006     }
1007 #endif
1008     env->psret = 0;
1009     cwp = (env->cwp - 1) & (NWINDOWS - 1); 
1010     set_cwp(cwp);
1011     env->regwptr[9] = env->pc;
1012     env->regwptr[10] = env->npc;
1013     env->psrps = env->psrs;
1014     env->psrs = 1;
1015     env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
1016     env->pc = env->tbr;
1017     env->npc = env->pc + 4;
1018     env->exception_index = 0;
1019 }
1020 #endif
1021
1022 #if !defined(CONFIG_USER_ONLY) 
1023
1024 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1025                                 void *retaddr);
1026
1027 #define MMUSUFFIX _mmu
1028 #define ALIGNED_ONLY
1029 #define GETPC() (__builtin_return_address(0))
1030
1031 #define SHIFT 0
1032 #include "softmmu_template.h"
1033
1034 #define SHIFT 1
1035 #include "softmmu_template.h"
1036
1037 #define SHIFT 2
1038 #include "softmmu_template.h"
1039
1040 #define SHIFT 3
1041 #include "softmmu_template.h"
1042
1043 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1044                                 void *retaddr)
1045 {
1046 #ifdef DEBUG_UNALIGNED
1047     printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
1048 #endif
1049     raise_exception(TT_UNALIGNED);
1050 }
1051
1052 /* try to fill the TLB and return an exception if error. If retaddr is
1053    NULL, it means that the function was called in C code (i.e. not
1054    from generated code or from helper.c) */
1055 /* XXX: fix it to restore all registers */
1056 void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
1057 {
1058     TranslationBlock *tb;
1059     int ret;
1060     unsigned long pc;
1061     CPUState *saved_env;
1062
1063     /* XXX: hack to restore env in all cases, even if not called from
1064        generated code */
1065     saved_env = env;
1066     env = cpu_single_env;
1067
1068     ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
1069     if (ret) {
1070         if (retaddr) {
1071             /* now we have a real cpu fault */
1072             pc = (unsigned long)retaddr;
1073             tb = tb_find_pc(pc);
1074             if (tb) {
1075                 /* the PC is inside the translated code. It means that we have
1076                    a virtual CPU fault */
1077                 cpu_restore_state(tb, env, pc, (void *)T2);
1078             }
1079         }
1080         cpu_loop_exit();
1081     }
1082     env = saved_env;
1083 }
1084
1085 #endif
1086
1087 #ifndef TARGET_SPARC64
1088 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1089                           int is_asi)
1090 {
1091     CPUState *saved_env;
1092
1093     /* XXX: hack to restore env in all cases, even if not called from
1094        generated code */
1095     saved_env = env;
1096     env = cpu_single_env;
1097     if (env->mmuregs[3]) /* Fault status register */
1098         env->mmuregs[3] = 1; /* overflow (not read before another fault) */
1099     if (is_asi)
1100         env->mmuregs[3] |= 1 << 16;
1101     if (env->psrs)
1102         env->mmuregs[3] |= 1 << 5;
1103     if (is_exec)
1104         env->mmuregs[3] |= 1 << 6;
1105     if (is_write)
1106         env->mmuregs[3] |= 1 << 7;
1107     env->mmuregs[3] |= (5 << 2) | 2;
1108     env->mmuregs[4] = addr; /* Fault address register */
1109     if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
1110 #ifdef DEBUG_UNASSIGNED
1111         printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
1112                "\n", addr, env->pc);
1113 #endif
1114         if (is_exec)
1115             raise_exception(TT_CODE_ACCESS);
1116         else
1117             raise_exception(TT_DATA_ACCESS);
1118     }
1119     env = saved_env;
1120 }
1121 #else
1122 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1123                           int is_asi)
1124 {
1125 #ifdef DEBUG_UNASSIGNED
1126     CPUState *saved_env;
1127
1128     /* XXX: hack to restore env in all cases, even if not called from
1129        generated code */
1130     saved_env = env;
1131     env = cpu_single_env;
1132     printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
1133            addr, env->pc);
1134     env = saved_env;
1135 #endif
1136     if (is_exec)
1137         raise_exception(TT_CODE_ACCESS);
1138     else
1139         raise_exception(TT_DATA_ACCESS);
1140 }
1141 #endif
1142
1143 #ifdef TARGET_SPARC64
1144 void do_tick_set_count(void *opaque, uint64_t count)
1145 {
1146 #if !defined(CONFIG_USER_ONLY)
1147     ptimer_set_count(opaque, -count);
1148 #endif
1149 }
1150
1151 uint64_t do_tick_get_count(void *opaque)
1152 {
1153 #if !defined(CONFIG_USER_ONLY)
1154     return -ptimer_get_count(opaque);
1155 #else
1156     return 0;
1157 #endif
1158 }
1159
1160 void do_tick_set_limit(void *opaque, uint64_t limit)
1161 {
1162 #if !defined(CONFIG_USER_ONLY)
1163     ptimer_set_limit(opaque, -limit, 0);
1164 #endif
1165 }
1166 #endif