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