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