|
|
1.1 root 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:
1.1.1.2 ! root 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
1.1 root 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 */
1.1.1.2 ! root 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: }
1.1 root 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: {
1.1.1.2 ! root 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: }
1.1 root 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: {
1.1.1.2 ! root 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: }
1.1 root 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: {
1.1.1.2 ! root 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: }
1.1 root 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
1.1.1.2 ! root 748: #endif /* !CONFIG_USER_ONLY */
1.1 root 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) {
1.1.1.2 ! root 945: cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
1.1 root 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) {
1.1.1.2 ! root 999: cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
1.1 root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.