|
|
1.1 root 1: #include "exec.h" 1.1.1.5 root 2: #include "host-utils.h" 1.1.1.6 ! root 3: #include "helper.h" ! 4: #if !defined(CONFIG_USER_ONLY) ! 5: #include "softmmu_exec.h" ! 6: #endif /* !defined(CONFIG_USER_ONLY) */ 1.1 root 7: 8: //#define DEBUG_MMU 1.1.1.5 root 9: //#define DEBUG_MXCC 10: //#define DEBUG_UNALIGNED 11: //#define DEBUG_UNASSIGNED 12: //#define DEBUG_ASI 1.1.1.6 ! root 13: //#define DEBUG_PCALL 1.1.1.5 root 14: 15: #ifdef DEBUG_MMU 16: #define DPRINTF_MMU(fmt, args...) \ 17: do { printf("MMU: " fmt , ##args); } while (0) 18: #else 1.1.1.6 ! root 19: #define DPRINTF_MMU(fmt, args...) do {} while (0) 1.1.1.5 root 20: #endif 21: 22: #ifdef DEBUG_MXCC 23: #define DPRINTF_MXCC(fmt, args...) \ 24: do { printf("MXCC: " fmt , ##args); } while (0) 25: #else 1.1.1.6 ! root 26: #define DPRINTF_MXCC(fmt, args...) do {} while (0) 1.1.1.5 root 27: #endif 28: 29: #ifdef DEBUG_ASI 30: #define DPRINTF_ASI(fmt, args...) \ 31: do { printf("ASI: " fmt , ##args); } while (0) 32: #else 1.1.1.6 ! root 33: #define DPRINTF_ASI(fmt, args...) do {} while (0) ! 34: #endif ! 35: ! 36: #ifdef TARGET_SPARC64 ! 37: #ifndef TARGET_ABI32 ! 38: #define AM_CHECK(env1) ((env1)->pstate & PS_AM) ! 39: #else ! 40: #define AM_CHECK(env1) (1) ! 41: #endif 1.1.1.5 root 42: #endif 1.1 root 43: 1.1.1.6 ! root 44: static inline void address_mask(CPUState *env1, target_ulong *addr) ! 45: { ! 46: #ifdef TARGET_SPARC64 ! 47: if (AM_CHECK(env1)) ! 48: *addr &= 0xffffffffULL; ! 49: #endif ! 50: } ! 51: ! 52: static void raise_exception(int tt) 1.1 root 53: { 54: env->exception_index = tt; 55: cpu_loop_exit(); 1.1.1.5 root 56: } 57: 1.1.1.6 ! root 58: void HELPER(raise_exception)(int tt) 1.1.1.5 root 59: { 1.1.1.6 ! root 60: raise_exception(tt); ! 61: } 1.1.1.5 root 62: 1.1.1.6 ! root 63: static inline void set_cwp(int new_cwp) ! 64: { ! 65: cpu_set_cwp(env, new_cwp); 1.1.1.5 root 66: } 1.1 root 67: 1.1.1.6 ! root 68: void helper_check_align(target_ulong addr, uint32_t align) 1.1 root 69: { 1.1.1.6 ! root 70: if (addr & align) { ! 71: #ifdef DEBUG_UNALIGNED ! 72: printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx ! 73: "\n", addr, env->pc); ! 74: #endif ! 75: raise_exception(TT_UNALIGNED); ! 76: } ! 77: } ! 78: ! 79: #define F_HELPER(name, p) void helper_f##name##p(void) ! 80: ! 81: #define F_BINOP(name) \ ! 82: float32 helper_f ## name ## s (float32 src1, float32 src2) \ ! 83: { \ ! 84: return float32_ ## name (src1, src2, &env->fp_status); \ ! 85: } \ ! 86: F_HELPER(name, d) \ ! 87: { \ ! 88: DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \ ! 89: } \ ! 90: F_HELPER(name, q) \ ! 91: { \ ! 92: QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \ ! 93: } ! 94: ! 95: F_BINOP(add); ! 96: F_BINOP(sub); ! 97: F_BINOP(mul); ! 98: F_BINOP(div); ! 99: #undef F_BINOP ! 100: ! 101: void helper_fsmuld(float32 src1, float32 src2) ! 102: { ! 103: DT0 = float64_mul(float32_to_float64(src1, &env->fp_status), ! 104: float32_to_float64(src2, &env->fp_status), ! 105: &env->fp_status); ! 106: } ! 107: ! 108: void helper_fdmulq(void) ! 109: { ! 110: QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status), ! 111: float64_to_float128(DT1, &env->fp_status), ! 112: &env->fp_status); ! 113: } ! 114: ! 115: float32 helper_fnegs(float32 src) ! 116: { ! 117: return float32_chs(src); 1.1 root 118: } 119: 1.1.1.6 ! root 120: #ifdef TARGET_SPARC64 ! 121: F_HELPER(neg, d) 1.1 root 122: { 1.1.1.6 ! root 123: DT0 = float64_chs(DT1); 1.1 root 124: } 1.1.1.5 root 125: 1.1.1.6 ! root 126: F_HELPER(neg, q) 1.1.1.5 root 127: { 1.1.1.6 ! root 128: QT0 = float128_chs(QT1); 1.1.1.5 root 129: } 130: #endif 131: 1.1.1.6 ! root 132: /* Integer to float conversion. */ ! 133: float32 helper_fitos(int32_t src) ! 134: { ! 135: return int32_to_float32(src, &env->fp_status); ! 136: } ! 137: ! 138: void helper_fitod(int32_t src) ! 139: { ! 140: DT0 = int32_to_float64(src, &env->fp_status); ! 141: } ! 142: ! 143: void helper_fitoq(int32_t src) ! 144: { ! 145: QT0 = int32_to_float128(src, &env->fp_status); ! 146: } ! 147: 1.1.1.5 root 148: #ifdef TARGET_SPARC64 1.1.1.6 ! root 149: float32 helper_fxtos(void) 1.1.1.5 root 150: { 1.1.1.6 ! root 151: return int64_to_float32(*((int64_t *)&DT1), &env->fp_status); 1.1.1.5 root 152: } 153: 1.1.1.6 ! root 154: F_HELPER(xto, d) 1.1.1.5 root 155: { 156: DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status); 157: } 158: 1.1.1.6 ! root 159: F_HELPER(xto, q) 1.1.1.5 root 160: { 1.1.1.6 ! root 161: QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status); 1.1.1.5 root 162: } 163: #endif 1.1.1.6 ! root 164: #undef F_HELPER ! 165: ! 166: /* floating point conversion */ ! 167: float32 helper_fdtos(void) ! 168: { ! 169: return float64_to_float32(DT1, &env->fp_status); ! 170: } ! 171: ! 172: void helper_fstod(float32 src) ! 173: { ! 174: DT0 = float32_to_float64(src, &env->fp_status); ! 175: } ! 176: ! 177: float32 helper_fqtos(void) ! 178: { ! 179: return float128_to_float32(QT1, &env->fp_status); ! 180: } ! 181: ! 182: void helper_fstoq(float32 src) ! 183: { ! 184: QT0 = float32_to_float128(src, &env->fp_status); ! 185: } ! 186: ! 187: void helper_fqtod(void) ! 188: { ! 189: DT0 = float128_to_float64(QT1, &env->fp_status); ! 190: } ! 191: ! 192: void helper_fdtoq(void) ! 193: { ! 194: QT0 = float64_to_float128(DT1, &env->fp_status); ! 195: } ! 196: ! 197: /* Float to integer conversion. */ ! 198: int32_t helper_fstoi(float32 src) ! 199: { ! 200: return float32_to_int32_round_to_zero(src, &env->fp_status); ! 201: } ! 202: ! 203: int32_t helper_fdtoi(void) ! 204: { ! 205: return float64_to_int32_round_to_zero(DT1, &env->fp_status); ! 206: } ! 207: ! 208: int32_t helper_fqtoi(void) ! 209: { ! 210: return float128_to_int32_round_to_zero(QT1, &env->fp_status); ! 211: } ! 212: ! 213: #ifdef TARGET_SPARC64 ! 214: void helper_fstox(float32 src) ! 215: { ! 216: *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status); ! 217: } ! 218: ! 219: void helper_fdtox(void) ! 220: { ! 221: *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status); ! 222: } ! 223: ! 224: void helper_fqtox(void) ! 225: { ! 226: *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status); ! 227: } ! 228: ! 229: void helper_faligndata(void) ! 230: { ! 231: uint64_t tmp; ! 232: ! 233: tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8); ! 234: /* on many architectures a shift of 64 does nothing */ ! 235: if ((env->gsr & 7) != 0) { ! 236: tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8); ! 237: } ! 238: *((uint64_t *)&DT0) = tmp; ! 239: } ! 240: ! 241: #ifdef WORDS_BIGENDIAN ! 242: #define VIS_B64(n) b[7 - (n)] ! 243: #define VIS_W64(n) w[3 - (n)] ! 244: #define VIS_SW64(n) sw[3 - (n)] ! 245: #define VIS_L64(n) l[1 - (n)] ! 246: #define VIS_B32(n) b[3 - (n)] ! 247: #define VIS_W32(n) w[1 - (n)] ! 248: #else ! 249: #define VIS_B64(n) b[n] ! 250: #define VIS_W64(n) w[n] ! 251: #define VIS_SW64(n) sw[n] ! 252: #define VIS_L64(n) l[n] ! 253: #define VIS_B32(n) b[n] ! 254: #define VIS_W32(n) w[n] ! 255: #endif ! 256: ! 257: typedef union { ! 258: uint8_t b[8]; ! 259: uint16_t w[4]; ! 260: int16_t sw[4]; ! 261: uint32_t l[2]; ! 262: float64 d; ! 263: } vis64; ! 264: ! 265: typedef union { ! 266: uint8_t b[4]; ! 267: uint16_t w[2]; ! 268: uint32_t l; ! 269: float32 f; ! 270: } vis32; ! 271: ! 272: void helper_fpmerge(void) ! 273: { ! 274: vis64 s, d; ! 275: ! 276: s.d = DT0; ! 277: d.d = DT1; ! 278: ! 279: // Reverse calculation order to handle overlap ! 280: d.VIS_B64(7) = s.VIS_B64(3); ! 281: d.VIS_B64(6) = d.VIS_B64(3); ! 282: d.VIS_B64(5) = s.VIS_B64(2); ! 283: d.VIS_B64(4) = d.VIS_B64(2); ! 284: d.VIS_B64(3) = s.VIS_B64(1); ! 285: d.VIS_B64(2) = d.VIS_B64(1); ! 286: d.VIS_B64(1) = s.VIS_B64(0); ! 287: //d.VIS_B64(0) = d.VIS_B64(0); ! 288: ! 289: DT0 = d.d; ! 290: } ! 291: ! 292: void helper_fmul8x16(void) ! 293: { ! 294: vis64 s, d; ! 295: uint32_t tmp; ! 296: ! 297: s.d = DT0; ! 298: d.d = DT1; ! 299: ! 300: #define PMUL(r) \ ! 301: tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r); \ ! 302: if ((tmp & 0xff) > 0x7f) \ ! 303: tmp += 0x100; \ ! 304: d.VIS_W64(r) = tmp >> 8; ! 305: ! 306: PMUL(0); ! 307: PMUL(1); ! 308: PMUL(2); ! 309: PMUL(3); ! 310: #undef PMUL ! 311: ! 312: DT0 = d.d; ! 313: } ! 314: ! 315: void helper_fmul8x16al(void) ! 316: { ! 317: vis64 s, d; ! 318: uint32_t tmp; ! 319: ! 320: s.d = DT0; ! 321: d.d = DT1; ! 322: ! 323: #define PMUL(r) \ ! 324: tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r); \ ! 325: if ((tmp & 0xff) > 0x7f) \ ! 326: tmp += 0x100; \ ! 327: d.VIS_W64(r) = tmp >> 8; ! 328: ! 329: PMUL(0); ! 330: PMUL(1); ! 331: PMUL(2); ! 332: PMUL(3); ! 333: #undef PMUL ! 334: ! 335: DT0 = d.d; ! 336: } ! 337: ! 338: void helper_fmul8x16au(void) ! 339: { ! 340: vis64 s, d; ! 341: uint32_t tmp; ! 342: ! 343: s.d = DT0; ! 344: d.d = DT1; ! 345: ! 346: #define PMUL(r) \ ! 347: tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r); \ ! 348: if ((tmp & 0xff) > 0x7f) \ ! 349: tmp += 0x100; \ ! 350: d.VIS_W64(r) = tmp >> 8; ! 351: ! 352: PMUL(0); ! 353: PMUL(1); ! 354: PMUL(2); ! 355: PMUL(3); ! 356: #undef PMUL ! 357: ! 358: DT0 = d.d; ! 359: } ! 360: ! 361: void helper_fmul8sux16(void) ! 362: { ! 363: vis64 s, d; ! 364: uint32_t tmp; ! 365: ! 366: s.d = DT0; ! 367: d.d = DT1; ! 368: ! 369: #define PMUL(r) \ ! 370: tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \ ! 371: if ((tmp & 0xff) > 0x7f) \ ! 372: tmp += 0x100; \ ! 373: d.VIS_W64(r) = tmp >> 8; ! 374: ! 375: PMUL(0); ! 376: PMUL(1); ! 377: PMUL(2); ! 378: PMUL(3); ! 379: #undef PMUL ! 380: ! 381: DT0 = d.d; ! 382: } ! 383: ! 384: void helper_fmul8ulx16(void) ! 385: { ! 386: vis64 s, d; ! 387: uint32_t tmp; ! 388: ! 389: s.d = DT0; ! 390: d.d = DT1; ! 391: ! 392: #define PMUL(r) \ ! 393: tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \ ! 394: if ((tmp & 0xff) > 0x7f) \ ! 395: tmp += 0x100; \ ! 396: d.VIS_W64(r) = tmp >> 8; ! 397: ! 398: PMUL(0); ! 399: PMUL(1); ! 400: PMUL(2); ! 401: PMUL(3); ! 402: #undef PMUL ! 403: ! 404: DT0 = d.d; ! 405: } ! 406: ! 407: void helper_fmuld8sux16(void) ! 408: { ! 409: vis64 s, d; ! 410: uint32_t tmp; ! 411: ! 412: s.d = DT0; ! 413: d.d = DT1; ! 414: ! 415: #define PMUL(r) \ ! 416: tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \ ! 417: if ((tmp & 0xff) > 0x7f) \ ! 418: tmp += 0x100; \ ! 419: d.VIS_L64(r) = tmp; ! 420: ! 421: // Reverse calculation order to handle overlap ! 422: PMUL(1); ! 423: PMUL(0); ! 424: #undef PMUL ! 425: ! 426: DT0 = d.d; ! 427: } ! 428: ! 429: void helper_fmuld8ulx16(void) ! 430: { ! 431: vis64 s, d; ! 432: uint32_t tmp; ! 433: ! 434: s.d = DT0; ! 435: d.d = DT1; ! 436: ! 437: #define PMUL(r) \ ! 438: tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \ ! 439: if ((tmp & 0xff) > 0x7f) \ ! 440: tmp += 0x100; \ ! 441: d.VIS_L64(r) = tmp; ! 442: ! 443: // Reverse calculation order to handle overlap ! 444: PMUL(1); ! 445: PMUL(0); ! 446: #undef PMUL ! 447: ! 448: DT0 = d.d; ! 449: } ! 450: ! 451: void helper_fexpand(void) ! 452: { ! 453: vis32 s; ! 454: vis64 d; ! 455: ! 456: s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff); ! 457: d.d = DT1; ! 458: d.VIS_W64(0) = s.VIS_B32(0) << 4; ! 459: d.VIS_W64(1) = s.VIS_B32(1) << 4; ! 460: d.VIS_W64(2) = s.VIS_B32(2) << 4; ! 461: d.VIS_W64(3) = s.VIS_B32(3) << 4; ! 462: ! 463: DT0 = d.d; ! 464: } ! 465: ! 466: #define VIS_HELPER(name, F) \ ! 467: void name##16(void) \ ! 468: { \ ! 469: vis64 s, d; \ ! 470: \ ! 471: s.d = DT0; \ ! 472: d.d = DT1; \ ! 473: \ ! 474: d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0)); \ ! 475: d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1)); \ ! 476: d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2)); \ ! 477: d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3)); \ ! 478: \ ! 479: DT0 = d.d; \ ! 480: } \ ! 481: \ ! 482: uint32_t name##16s(uint32_t src1, uint32_t src2) \ ! 483: { \ ! 484: vis32 s, d; \ ! 485: \ ! 486: s.l = src1; \ ! 487: d.l = src2; \ ! 488: \ ! 489: d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0)); \ ! 490: d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1)); \ ! 491: \ ! 492: return d.l; \ ! 493: } \ ! 494: \ ! 495: void name##32(void) \ ! 496: { \ ! 497: vis64 s, d; \ ! 498: \ ! 499: s.d = DT0; \ ! 500: d.d = DT1; \ ! 501: \ ! 502: d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0)); \ ! 503: d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1)); \ ! 504: \ ! 505: DT0 = d.d; \ ! 506: } \ ! 507: \ ! 508: uint32_t name##32s(uint32_t src1, uint32_t src2) \ ! 509: { \ ! 510: vis32 s, d; \ ! 511: \ ! 512: s.l = src1; \ ! 513: d.l = src2; \ ! 514: \ ! 515: d.l = F(d.l, s.l); \ ! 516: \ ! 517: return d.l; \ ! 518: } ! 519: ! 520: #define FADD(a, b) ((a) + (b)) ! 521: #define FSUB(a, b) ((a) - (b)) ! 522: VIS_HELPER(helper_fpadd, FADD) ! 523: VIS_HELPER(helper_fpsub, FSUB) ! 524: ! 525: #define VIS_CMPHELPER(name, F) \ ! 526: void name##16(void) \ ! 527: { \ ! 528: vis64 s, d; \ ! 529: \ ! 530: s.d = DT0; \ ! 531: d.d = DT1; \ ! 532: \ ! 533: d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0; \ ! 534: d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0; \ ! 535: d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0; \ ! 536: d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0; \ ! 537: \ ! 538: DT0 = d.d; \ ! 539: } \ ! 540: \ ! 541: void name##32(void) \ ! 542: { \ ! 543: vis64 s, d; \ ! 544: \ ! 545: s.d = DT0; \ ! 546: d.d = DT1; \ ! 547: \ ! 548: d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0; \ ! 549: d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0; \ ! 550: \ ! 551: DT0 = d.d; \ ! 552: } ! 553: ! 554: #define FCMPGT(a, b) ((a) > (b)) ! 555: #define FCMPEQ(a, b) ((a) == (b)) ! 556: #define FCMPLE(a, b) ((a) <= (b)) ! 557: #define FCMPNE(a, b) ((a) != (b)) ! 558: ! 559: VIS_CMPHELPER(helper_fcmpgt, FCMPGT) ! 560: VIS_CMPHELPER(helper_fcmpeq, FCMPEQ) ! 561: VIS_CMPHELPER(helper_fcmple, FCMPLE) ! 562: VIS_CMPHELPER(helper_fcmpne, FCMPNE) 1.1.1.5 root 563: #endif 1.1 root 564: 1.1.1.6 ! root 565: void helper_check_ieee_exceptions(void) ! 566: { ! 567: target_ulong status; ! 568: ! 569: status = get_float_exception_flags(&env->fp_status); ! 570: if (status) { ! 571: /* Copy IEEE 754 flags into FSR */ ! 572: if (status & float_flag_invalid) ! 573: env->fsr |= FSR_NVC; ! 574: if (status & float_flag_overflow) ! 575: env->fsr |= FSR_OFC; ! 576: if (status & float_flag_underflow) ! 577: env->fsr |= FSR_UFC; ! 578: if (status & float_flag_divbyzero) ! 579: env->fsr |= FSR_DZC; ! 580: if (status & float_flag_inexact) ! 581: env->fsr |= FSR_NXC; ! 582: ! 583: if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) { ! 584: /* Unmasked exception, generate a trap */ ! 585: env->fsr |= FSR_FTT_IEEE_EXCP; ! 586: raise_exception(TT_FP_EXCP); ! 587: } else { ! 588: /* Accumulate exceptions */ ! 589: env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5; ! 590: } ! 591: } ! 592: } ! 593: ! 594: void helper_clear_float_exceptions(void) ! 595: { ! 596: set_float_exception_flags(0, &env->fp_status); ! 597: } ! 598: ! 599: float32 helper_fabss(float32 src) 1.1 root 600: { 1.1.1.6 ! root 601: return float32_abs(src); 1.1 root 602: } 603: 604: #ifdef TARGET_SPARC64 1.1.1.6 ! root 605: void helper_fabsd(void) 1.1 root 606: { 607: DT0 = float64_abs(DT1); 608: } 1.1.1.5 root 609: 1.1.1.6 ! root 610: void helper_fabsq(void) 1.1.1.5 root 611: { 612: QT0 = float128_abs(QT1); 613: } 614: #endif 1.1 root 615: 1.1.1.6 ! root 616: float32 helper_fsqrts(float32 src) 1.1 root 617: { 1.1.1.6 ! root 618: return float32_sqrt(src, &env->fp_status); 1.1 root 619: } 620: 1.1.1.6 ! root 621: void helper_fsqrtd(void) 1.1 root 622: { 623: DT0 = float64_sqrt(DT1, &env->fp_status); 624: } 625: 1.1.1.6 ! root 626: void helper_fsqrtq(void) 1.1.1.5 root 627: { 628: QT0 = float128_sqrt(QT1, &env->fp_status); 629: } 630: 631: #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \ 1.1.1.6 ! root 632: void glue(helper_, name) (void) \ 1.1.1.3 root 633: { \ 1.1.1.6 ! root 634: target_ulong new_fsr; \ ! 635: \ 1.1.1.3 root 636: env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ 637: switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \ 638: case float_relation_unordered: \ 1.1.1.6 ! root 639: new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \ ! 640: if ((env->fsr & FSR_NVM) || TRAP) { \ ! 641: env->fsr |= new_fsr; \ ! 642: env->fsr |= FSR_NVC; \ ! 643: env->fsr |= FSR_FTT_IEEE_EXCP; \ ! 644: raise_exception(TT_FP_EXCP); \ ! 645: } else { \ ! 646: env->fsr |= FSR_NVA; \ ! 647: } \ ! 648: break; \ ! 649: case float_relation_less: \ ! 650: new_fsr = FSR_FCC0 << FS; \ ! 651: break; \ ! 652: case float_relation_greater: \ ! 653: new_fsr = FSR_FCC1 << FS; \ ! 654: break; \ ! 655: default: \ ! 656: new_fsr = 0; \ ! 657: break; \ ! 658: } \ ! 659: env->fsr |= new_fsr; \ ! 660: } ! 661: #define GEN_FCMPS(name, size, FS, TRAP) \ ! 662: void glue(helper_, name)(float32 src1, float32 src2) \ ! 663: { \ ! 664: target_ulong new_fsr; \ ! 665: \ ! 666: env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ ! 667: switch (glue(size, _compare) (src1, src2, &env->fp_status)) { \ ! 668: case float_relation_unordered: \ ! 669: new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \ 1.1.1.5 root 670: if ((env->fsr & FSR_NVM) || TRAP) { \ 1.1.1.6 ! root 671: env->fsr |= new_fsr; \ 1.1.1.5 root 672: env->fsr |= FSR_NVC; \ 673: env->fsr |= FSR_FTT_IEEE_EXCP; \ 1.1.1.3 root 674: raise_exception(TT_FP_EXCP); \ 675: } else { \ 676: env->fsr |= FSR_NVA; \ 677: } \ 678: break; \ 679: case float_relation_less: \ 1.1.1.6 ! root 680: new_fsr = FSR_FCC0 << FS; \ 1.1.1.3 root 681: break; \ 682: case float_relation_greater: \ 1.1.1.6 ! root 683: new_fsr = FSR_FCC1 << FS; \ 1.1.1.3 root 684: break; \ 685: default: \ 1.1.1.6 ! root 686: new_fsr = 0; \ 1.1.1.3 root 687: break; \ 688: } \ 1.1.1.6 ! root 689: env->fsr |= new_fsr; \ 1.1 root 690: } 691: 1.1.1.6 ! root 692: GEN_FCMPS(fcmps, float32, 0, 0); 1.1.1.5 root 693: GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0); 694: 1.1.1.6 ! root 695: GEN_FCMPS(fcmpes, float32, 0, 1); 1.1.1.5 root 696: GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1); 697: 698: GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0); 699: GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1); 1.1 root 700: 701: #ifdef TARGET_SPARC64 1.1.1.6 ! root 702: GEN_FCMPS(fcmps_fcc1, float32, 22, 0); 1.1.1.5 root 703: GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0); 1.1.1.6 ! root 704: GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0); 1.1 root 705: 1.1.1.6 ! root 706: GEN_FCMPS(fcmps_fcc2, float32, 24, 0); 1.1.1.5 root 707: GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0); 1.1.1.6 ! root 708: GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0); 1.1 root 709: 1.1.1.6 ! root 710: GEN_FCMPS(fcmps_fcc3, float32, 26, 0); 1.1.1.5 root 711: GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0); 1.1.1.6 ! root 712: GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0); 1.1.1.5 root 713: 1.1.1.6 ! root 714: GEN_FCMPS(fcmpes_fcc1, float32, 22, 1); 1.1.1.5 root 715: GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1); 1.1.1.6 ! root 716: GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1); 1.1.1.5 root 717: 1.1.1.6 ! root 718: GEN_FCMPS(fcmpes_fcc2, float32, 24, 1); 1.1.1.5 root 719: GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1); 1.1.1.6 ! root 720: GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1); 1.1.1.5 root 721: 1.1.1.6 ! root 722: GEN_FCMPS(fcmpes_fcc3, float32, 26, 1); 1.1.1.5 root 723: GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1); 724: GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1); 725: #endif 1.1.1.6 ! root 726: #undef GEN_FCMPS 1.1.1.5 root 727: 1.1.1.6 ! root 728: #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \ ! 729: defined(DEBUG_MXCC) 1.1.1.5 root 730: static void dump_mxcc(CPUState *env) 1.1.1.2 root 731: { 1.1.1.5 root 732: printf("mxccdata: %016llx %016llx %016llx %016llx\n", 1.1.1.6 ! root 733: env->mxccdata[0], env->mxccdata[1], ! 734: env->mxccdata[2], env->mxccdata[3]); 1.1.1.5 root 735: printf("mxccregs: %016llx %016llx %016llx %016llx\n" 736: " %016llx %016llx %016llx %016llx\n", 1.1.1.6 ! root 737: env->mxccregs[0], env->mxccregs[1], ! 738: env->mxccregs[2], env->mxccregs[3], ! 739: env->mxccregs[4], env->mxccregs[5], ! 740: env->mxccregs[6], env->mxccregs[7]); 1.1.1.2 root 741: } 1.1.1.5 root 742: #endif 1.1.1.2 root 743: 1.1.1.6 ! root 744: #if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \ ! 745: && defined(DEBUG_ASI) ! 746: static void dump_asi(const char *txt, target_ulong addr, int asi, int size, ! 747: uint64_t r1) 1.1.1.5 root 748: { 749: switch (size) 750: { 751: case 1: 1.1.1.6 ! root 752: DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt, ! 753: addr, asi, r1 & 0xff); 1.1.1.5 root 754: break; 755: case 2: 1.1.1.6 ! root 756: DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt, ! 757: addr, asi, r1 & 0xffff); 1.1.1.5 root 758: break; 759: case 4: 1.1.1.6 ! root 760: DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt, ! 761: addr, asi, r1 & 0xffffffff); 1.1.1.5 root 762: break; 763: case 8: 1.1.1.6 ! root 764: DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt, ! 765: addr, asi, r1); 1.1.1.5 root 766: break; 767: } 1.1.1.2 root 768: } 1.1.1.5 root 769: #endif 770: 1.1.1.6 ! root 771: #ifndef TARGET_SPARC64 ! 772: #ifndef CONFIG_USER_ONLY ! 773: uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) 1.1 root 774: { 1.1.1.6 ! root 775: uint64_t ret = 0; 1.1.1.5 root 776: #if defined(DEBUG_MXCC) || defined(DEBUG_ASI) 1.1.1.6 ! root 777: uint32_t last_addr = addr; 1.1.1.5 root 778: #endif 1.1 root 779: 1.1.1.6 ! root 780: helper_check_align(addr, size - 1); 1.1 root 781: switch (asi) { 1.1.1.5 root 782: case 2: /* SuperSparc MXCC registers */ 1.1.1.6 ! root 783: switch (addr) { 1.1.1.5 root 784: case 0x01c00a00: /* MXCC control register */ 1.1.1.6 ! root 785: if (size == 8) ! 786: ret = env->mxccregs[3]; ! 787: else ! 788: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, ! 789: size); 1.1.1.5 root 790: break; 791: case 0x01c00a04: /* MXCC control register */ 792: if (size == 4) 793: ret = env->mxccregs[3]; 794: else 1.1.1.6 ! root 795: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, ! 796: size); 1.1.1.5 root 797: break; 798: case 0x01c00c00: /* Module reset register */ 799: if (size == 8) { 1.1.1.6 ! root 800: ret = env->mxccregs[5]; 1.1.1.5 root 801: // should we do something here? 802: } else 1.1.1.6 ! root 803: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, ! 804: size); 1.1.1.5 root 805: break; 806: case 0x01c00f00: /* MBus port address register */ 1.1.1.6 ! root 807: if (size == 8) ! 808: ret = env->mxccregs[7]; ! 809: else ! 810: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, ! 811: size); 1.1.1.5 root 812: break; 813: default: 1.1.1.6 ! root 814: DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, ! 815: size); 1.1.1.5 root 816: break; 817: } 1.1.1.6 ! root 818: DPRINTF_MXCC("asi = %d, size = %d, sign = %d, " ! 819: "addr = %08x -> ret = %" PRIx64 "," ! 820: "addr = %08x\n", asi, size, sign, last_addr, ret, addr); 1.1.1.5 root 821: #ifdef DEBUG_MXCC 822: dump_mxcc(env); 823: #endif 824: break; 1.1 root 825: case 3: /* MMU probe */ 1.1.1.5 root 826: { 827: int mmulev; 1.1 root 828: 1.1.1.6 ! root 829: mmulev = (addr >> 8) & 15; 1.1.1.5 root 830: if (mmulev > 4) 831: ret = 0; 1.1.1.6 ! root 832: else ! 833: ret = mmu_probe(env, addr, mmulev); ! 834: DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n", ! 835: addr, mmulev, ret); 1.1.1.5 root 836: } 837: break; 1.1 root 838: case 4: /* read MMU regs */ 1.1.1.5 root 839: { 1.1.1.6 ! root 840: int reg = (addr >> 8) & 0x1f; 1.1.1.5 root 841: 842: ret = env->mmuregs[reg]; 843: if (reg == 3) /* Fault status cleared on read */ 844: env->mmuregs[3] = 0; 845: else if (reg == 0x13) /* Fault status read */ 846: ret = env->mmuregs[3]; 847: else if (reg == 0x14) /* Fault address read */ 848: ret = env->mmuregs[4]; 1.1.1.6 ! root 849: DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret); 1.1.1.5 root 850: } 851: break; 852: case 5: // Turbosparc ITLB Diagnostic 853: case 6: // Turbosparc DTLB Diagnostic 854: case 7: // Turbosparc IOTLB Diagnostic 855: break; 856: case 9: /* Supervisor code access */ 857: switch(size) { 858: case 1: 1.1.1.6 ! root 859: ret = ldub_code(addr); 1.1.1.5 root 860: break; 861: case 2: 1.1.1.6 ! root 862: ret = lduw_code(addr); 1.1.1.5 root 863: break; 864: default: 865: case 4: 1.1.1.6 ! root 866: ret = ldl_code(addr); 1.1.1.5 root 867: break; 868: case 8: 1.1.1.6 ! root 869: ret = ldq_code(addr); 1.1.1.5 root 870: break; 871: } 872: break; 873: case 0xa: /* User data access */ 874: switch(size) { 875: case 1: 1.1.1.6 ! root 876: ret = ldub_user(addr); 1.1.1.5 root 877: break; 878: case 2: 1.1.1.6 ! root 879: ret = lduw_user(addr); 1.1.1.5 root 880: break; 881: default: 882: case 4: 1.1.1.6 ! root 883: ret = ldl_user(addr); 1.1.1.5 root 884: break; 885: case 8: 1.1.1.6 ! root 886: ret = ldq_user(addr); 1.1.1.5 root 887: break; 888: } 889: break; 890: case 0xb: /* Supervisor data access */ 891: switch(size) { 892: case 1: 1.1.1.6 ! root 893: ret = ldub_kernel(addr); 1.1.1.5 root 894: break; 895: case 2: 1.1.1.6 ! root 896: ret = lduw_kernel(addr); 1.1.1.5 root 897: break; 898: default: 899: case 4: 1.1.1.6 ! root 900: ret = ldl_kernel(addr); 1.1.1.5 root 901: break; 902: case 8: 1.1.1.6 ! root 903: ret = ldq_kernel(addr); 1.1.1.5 root 904: break; 905: } 906: break; 907: case 0xc: /* I-cache tag */ 908: case 0xd: /* I-cache data */ 909: case 0xe: /* D-cache tag */ 910: case 0xf: /* D-cache data */ 911: break; 912: case 0x20: /* MMU passthrough */ 1.1.1.2 root 913: switch(size) { 914: case 1: 1.1.1.6 ! root 915: ret = ldub_phys(addr); 1.1.1.2 root 916: break; 917: case 2: 1.1.1.6 ! root 918: ret = lduw_phys(addr); 1.1.1.2 root 919: break; 920: default: 921: case 4: 1.1.1.6 ! root 922: ret = ldl_phys(addr); 1.1.1.2 root 923: break; 924: case 8: 1.1.1.6 ! root 925: ret = ldq_phys(addr); 1.1.1.5 root 926: break; 1.1.1.2 root 927: } 1.1.1.5 root 928: break; 929: case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */ 930: switch(size) { 931: case 1: 1.1.1.6 ! root 932: ret = ldub_phys((target_phys_addr_t)addr 1.1.1.5 root 933: | ((target_phys_addr_t)(asi & 0xf) << 32)); 934: break; 935: case 2: 1.1.1.6 ! root 936: ret = lduw_phys((target_phys_addr_t)addr 1.1.1.5 root 937: | ((target_phys_addr_t)(asi & 0xf) << 32)); 938: break; 939: default: 940: case 4: 1.1.1.6 ! root 941: ret = ldl_phys((target_phys_addr_t)addr 1.1.1.5 root 942: | ((target_phys_addr_t)(asi & 0xf) << 32)); 943: break; 944: case 8: 1.1.1.6 ! root 945: ret = ldq_phys((target_phys_addr_t)addr 1.1.1.5 root 946: | ((target_phys_addr_t)(asi & 0xf) << 32)); 947: break; 948: } 949: break; 950: case 0x30: // Turbosparc secondary cache diagnostic 951: case 0x31: // Turbosparc RAM snoop 952: case 0x32: // Turbosparc page table descriptor diagnostic 953: case 0x39: /* data cache diagnostic register */ 954: ret = 0; 955: break; 1.1.1.6 ! root 956: case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */ ! 957: { ! 958: int reg = (addr >> 8) & 3; ! 959: ! 960: switch(reg) { ! 961: case 0: /* Breakpoint Value (Addr) */ ! 962: ret = env->mmubpregs[reg]; ! 963: break; ! 964: case 1: /* Breakpoint Mask */ ! 965: ret = env->mmubpregs[reg]; ! 966: break; ! 967: case 2: /* Breakpoint Control */ ! 968: ret = env->mmubpregs[reg]; ! 969: break; ! 970: case 3: /* Breakpoint Status */ ! 971: ret = env->mmubpregs[reg]; ! 972: env->mmubpregs[reg] = 0ULL; ! 973: break; ! 974: } ! 975: DPRINTF_MMU("read breakpoint reg[%d] 0x%016llx\n", reg, ret); ! 976: } ! 977: break; 1.1.1.5 root 978: case 8: /* User code access, XXX */ 1.1 root 979: default: 1.1.1.6 ! root 980: do_unassigned_access(addr, 0, 0, asi, size); 1.1.1.5 root 981: ret = 0; 982: break; 1.1 root 983: } 1.1.1.5 root 984: if (sign) { 985: switch(size) { 986: case 1: 1.1.1.6 ! root 987: ret = (int8_t) ret; 1.1.1.5 root 988: break; 989: case 2: 1.1.1.6 ! root 990: ret = (int16_t) ret; ! 991: break; ! 992: case 4: ! 993: ret = (int32_t) ret; 1.1.1.5 root 994: break; 995: default: 996: break; 997: } 998: } 999: #ifdef DEBUG_ASI 1.1.1.6 ! root 1000: dump_asi("read ", last_addr, asi, size, ret); 1.1.1.5 root 1001: #endif 1.1.1.6 ! root 1002: return ret; 1.1 root 1003: } 1004: 1.1.1.6 ! root 1005: void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size) 1.1 root 1006: { 1.1.1.6 ! root 1007: helper_check_align(addr, size - 1); 1.1 root 1008: switch(asi) { 1.1.1.5 root 1009: case 2: /* SuperSparc MXCC registers */ 1.1.1.6 ! root 1010: switch (addr) { 1.1.1.5 root 1011: case 0x01c00000: /* MXCC stream data register 0 */ 1012: if (size == 8) 1.1.1.6 ! root 1013: env->mxccdata[0] = val; 1.1.1.5 root 1014: else 1.1.1.6 ! root 1015: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, ! 1016: size); 1.1.1.5 root 1017: break; 1018: case 0x01c00008: /* MXCC stream data register 1 */ 1019: if (size == 8) 1.1.1.6 ! root 1020: env->mxccdata[1] = val; 1.1.1.5 root 1021: else 1.1.1.6 ! root 1022: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, ! 1023: size); 1.1.1.5 root 1024: break; 1025: case 0x01c00010: /* MXCC stream data register 2 */ 1026: if (size == 8) 1.1.1.6 ! root 1027: env->mxccdata[2] = val; 1.1.1.5 root 1028: else 1.1.1.6 ! root 1029: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, ! 1030: size); 1.1.1.5 root 1031: break; 1032: case 0x01c00018: /* MXCC stream data register 3 */ 1033: if (size == 8) 1.1.1.6 ! root 1034: env->mxccdata[3] = val; 1.1.1.5 root 1035: else 1.1.1.6 ! root 1036: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, ! 1037: size); 1.1.1.5 root 1038: break; 1039: case 0x01c00100: /* MXCC stream source */ 1040: if (size == 8) 1.1.1.6 ! root 1041: env->mxccregs[0] = val; 1.1.1.5 root 1042: else 1.1.1.6 ! root 1043: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, ! 1044: size); ! 1045: env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + ! 1046: 0); ! 1047: env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + ! 1048: 8); ! 1049: env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + ! 1050: 16); ! 1051: env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + ! 1052: 24); 1.1.1.5 root 1053: break; 1054: case 0x01c00200: /* MXCC stream destination */ 1055: if (size == 8) 1.1.1.6 ! root 1056: env->mxccregs[1] = val; 1.1.1.5 root 1057: else 1.1.1.6 ! root 1058: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, ! 1059: size); ! 1060: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0, ! 1061: env->mxccdata[0]); ! 1062: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8, ! 1063: env->mxccdata[1]); ! 1064: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, ! 1065: env->mxccdata[2]); ! 1066: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, ! 1067: env->mxccdata[3]); 1.1.1.5 root 1068: break; 1069: case 0x01c00a00: /* MXCC control register */ 1070: if (size == 8) 1.1.1.6 ! root 1071: env->mxccregs[3] = val; 1.1.1.5 root 1072: else 1.1.1.6 ! root 1073: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, ! 1074: size); 1.1.1.5 root 1075: break; 1076: case 0x01c00a04: /* MXCC control register */ 1077: if (size == 4) 1.1.1.6 ! root 1078: env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL) ! 1079: | val; 1.1.1.5 root 1080: else 1.1.1.6 ! root 1081: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, ! 1082: size); 1.1.1.5 root 1083: break; 1084: case 0x01c00e00: /* MXCC error register */ 1085: // writing a 1 bit clears the error 1086: if (size == 8) 1.1.1.6 ! root 1087: env->mxccregs[6] &= ~val; 1.1.1.5 root 1088: else 1.1.1.6 ! root 1089: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, ! 1090: size); 1.1.1.5 root 1091: break; 1092: case 0x01c00f00: /* MBus port address register */ 1093: if (size == 8) 1.1.1.6 ! root 1094: env->mxccregs[7] = val; 1.1.1.5 root 1095: else 1.1.1.6 ! root 1096: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, ! 1097: size); 1.1.1.5 root 1098: break; 1099: default: 1.1.1.6 ! root 1100: DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, ! 1101: size); 1.1.1.5 root 1102: break; 1103: } 1.1.1.6 ! root 1104: DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n", ! 1105: asi, size, addr, val); 1.1.1.5 root 1106: #ifdef DEBUG_MXCC 1107: dump_mxcc(env); 1108: #endif 1109: break; 1.1 root 1110: case 3: /* MMU flush */ 1.1.1.5 root 1111: { 1112: int mmulev; 1.1 root 1113: 1.1.1.6 ! root 1114: mmulev = (addr >> 8) & 15; 1.1.1.5 root 1115: DPRINTF_MMU("mmu flush level %d\n", mmulev); 1116: switch (mmulev) { 1117: case 0: // flush page 1.1.1.6 ! root 1118: tlb_flush_page(env, addr & 0xfffff000); 1.1.1.5 root 1119: break; 1120: case 1: // flush segment (256k) 1121: case 2: // flush region (16M) 1122: case 3: // flush context (4G) 1123: case 4: // flush entire 1124: tlb_flush(env, 1); 1125: break; 1126: default: 1127: break; 1128: } 1.1 root 1129: #ifdef DEBUG_MMU 1.1.1.5 root 1130: dump_mmu(env); 1.1 root 1131: #endif 1.1.1.5 root 1132: } 1133: break; 1.1 root 1134: case 4: /* write MMU regs */ 1.1.1.5 root 1135: { 1.1.1.6 ! root 1136: int reg = (addr >> 8) & 0x1f; 1.1.1.5 root 1137: uint32_t oldreg; 1138: 1139: oldreg = env->mmuregs[reg]; 1.1 root 1140: switch(reg) { 1.1.1.6 ! root 1141: case 0: // Control Register 1.1.1.5 root 1142: env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) | 1.1.1.6 ! root 1143: (val & 0x00ffffff); 1.1.1.5 root 1144: // Mappings generated during no-fault mode or MMU 1145: // disabled mode are invalid in normal mode 1.1.1.6 ! root 1146: if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) != ! 1147: (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm))) 1.1 root 1148: tlb_flush(env, 1); 1149: break; 1.1.1.6 ! root 1150: case 1: // Context Table Pointer Register ! 1151: env->mmuregs[reg] = val & env->def->mmu_ctpr_mask; ! 1152: break; ! 1153: case 2: // Context Register ! 1154: env->mmuregs[reg] = val & env->def->mmu_cxr_mask; 1.1 root 1155: if (oldreg != env->mmuregs[reg]) { 1156: /* we flush when the MMU context changes because 1157: QEMU has no MMU context support */ 1158: tlb_flush(env, 1); 1159: } 1160: break; 1.1.1.6 ! root 1161: case 3: // Synchronous Fault Status Register with Clear ! 1162: case 4: // Synchronous Fault Address Register 1.1 root 1163: break; 1.1.1.6 ! root 1164: case 0x10: // TLB Replacement Control Register ! 1165: env->mmuregs[reg] = val & env->def->mmu_trcr_mask; 1.1.1.5 root 1166: break; 1.1.1.6 ! root 1167: case 0x13: // Synchronous Fault Status Register with Read and Clear ! 1168: env->mmuregs[3] = val & env->def->mmu_sfsr_mask; ! 1169: break; ! 1170: case 0x14: // Synchronous Fault Address Register ! 1171: env->mmuregs[4] = val; 1.1.1.5 root 1172: break; 1.1 root 1173: default: 1.1.1.6 ! root 1174: env->mmuregs[reg] = val; 1.1 root 1175: break; 1176: } 1177: if (oldreg != env->mmuregs[reg]) { 1.1.1.6 ! root 1178: DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", ! 1179: reg, oldreg, env->mmuregs[reg]); 1.1 root 1180: } 1.1.1.5 root 1181: #ifdef DEBUG_MMU 1182: dump_mmu(env); 1.1 root 1183: #endif 1.1.1.5 root 1184: } 1185: break; 1186: case 5: // Turbosparc ITLB Diagnostic 1187: case 6: // Turbosparc DTLB Diagnostic 1188: case 7: // Turbosparc IOTLB Diagnostic 1189: break; 1190: case 0xa: /* User data access */ 1191: switch(size) { 1192: case 1: 1.1.1.6 ! root 1193: stb_user(addr, val); 1.1.1.5 root 1194: break; 1195: case 2: 1.1.1.6 ! root 1196: stw_user(addr, val); 1.1.1.5 root 1197: break; 1198: default: 1199: case 4: 1.1.1.6 ! root 1200: stl_user(addr, val); 1.1.1.5 root 1201: break; 1202: case 8: 1.1.1.6 ! root 1203: stq_user(addr, val); 1.1.1.5 root 1204: break; 1205: } 1206: break; 1207: case 0xb: /* Supervisor data access */ 1208: switch(size) { 1209: case 1: 1.1.1.6 ! root 1210: stb_kernel(addr, val); 1.1.1.5 root 1211: break; 1212: case 2: 1.1.1.6 ! root 1213: stw_kernel(addr, val); 1.1.1.5 root 1214: break; 1215: default: 1216: case 4: 1.1.1.6 ! root 1217: stl_kernel(addr, val); 1.1.1.5 root 1218: break; 1219: case 8: 1.1.1.6 ! root 1220: stq_kernel(addr, val); 1.1.1.5 root 1221: break; 1222: } 1223: break; 1224: case 0xc: /* I-cache tag */ 1225: case 0xd: /* I-cache data */ 1226: case 0xe: /* D-cache tag */ 1227: case 0xf: /* D-cache data */ 1228: case 0x10: /* I/D-cache flush page */ 1229: case 0x11: /* I/D-cache flush segment */ 1230: case 0x12: /* I/D-cache flush region */ 1231: case 0x13: /* I/D-cache flush context */ 1232: case 0x14: /* I/D-cache flush user */ 1233: break; 1.1 root 1234: case 0x17: /* Block copy, sta access */ 1.1.1.5 root 1235: { 1.1.1.6 ! root 1236: // val = src ! 1237: // addr = dst 1.1.1.5 root 1238: // copy 32 bytes 1239: unsigned int i; 1.1.1.6 ! root 1240: uint32_t src = val & ~3, dst = addr & ~3, temp; 1.1.1.5 root 1241: 1242: for (i = 0; i < 32; i += 4, src += 4, dst += 4) { 1243: temp = ldl_kernel(src); 1244: stl_kernel(dst, temp); 1245: } 1246: } 1247: break; 1.1 root 1248: case 0x1f: /* Block fill, stda access */ 1.1.1.5 root 1249: { 1.1.1.6 ! root 1250: // addr = dst ! 1251: // fill 32 bytes with val 1.1.1.5 root 1252: unsigned int i; 1.1.1.6 ! root 1253: uint32_t dst = addr & 7; 1.1.1.5 root 1254: 1255: for (i = 0; i < 32; i += 8, dst += 8) 1256: stq_kernel(dst, val); 1257: } 1258: break; 1259: case 0x20: /* MMU passthrough */ 1260: { 1261: switch(size) { 1262: case 1: 1.1.1.6 ! root 1263: stb_phys(addr, val); 1.1.1.5 root 1264: break; 1265: case 2: 1.1.1.6 ! root 1266: stw_phys(addr, val); 1.1.1.5 root 1267: break; 1268: case 4: 1269: default: 1.1.1.6 ! root 1270: stl_phys(addr, val); 1.1.1.5 root 1271: break; 1272: case 8: 1.1.1.6 ! root 1273: stq_phys(addr, val); 1.1.1.5 root 1274: break; 1275: } 1276: } 1277: break; 1278: case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */ 1279: { 1280: switch(size) { 1281: case 1: 1.1.1.6 ! root 1282: stb_phys((target_phys_addr_t)addr ! 1283: | ((target_phys_addr_t)(asi & 0xf) << 32), val); 1.1.1.5 root 1284: break; 1285: case 2: 1.1.1.6 ! root 1286: stw_phys((target_phys_addr_t)addr ! 1287: | ((target_phys_addr_t)(asi & 0xf) << 32), val); 1.1.1.5 root 1288: break; 1289: case 4: 1290: default: 1.1.1.6 ! root 1291: stl_phys((target_phys_addr_t)addr ! 1292: | ((target_phys_addr_t)(asi & 0xf) << 32), val); 1.1.1.5 root 1293: break; 1294: case 8: 1.1.1.6 ! root 1295: stq_phys((target_phys_addr_t)addr ! 1296: | ((target_phys_addr_t)(asi & 0xf) << 32), val); 1.1.1.5 root 1297: break; 1298: } 1299: } 1300: break; 1301: case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic 1302: case 0x31: // store buffer data, Ross RT620 I-cache flush or 1303: // Turbosparc snoop RAM 1.1.1.6 ! root 1304: case 0x32: // store buffer control or Turbosparc page table ! 1305: // descriptor diagnostic 1.1.1.5 root 1306: case 0x36: /* I-cache flash clear */ 1307: case 0x37: /* D-cache flash clear */ 1308: case 0x4c: /* breakpoint action */ 1309: break; 1.1.1.6 ! root 1310: case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/ ! 1311: { ! 1312: int reg = (addr >> 8) & 3; ! 1313: ! 1314: switch(reg) { ! 1315: case 0: /* Breakpoint Value (Addr) */ ! 1316: env->mmubpregs[reg] = (val & 0xfffffffffULL); ! 1317: break; ! 1318: case 1: /* Breakpoint Mask */ ! 1319: env->mmubpregs[reg] = (val & 0xfffffffffULL); ! 1320: break; ! 1321: case 2: /* Breakpoint Control */ ! 1322: env->mmubpregs[reg] = (val & 0x7fULL); ! 1323: break; ! 1324: case 3: /* Breakpoint Status */ ! 1325: env->mmubpregs[reg] = (val & 0xfULL); ! 1326: break; ! 1327: } ! 1328: DPRINTF_MMU("write breakpoint reg[%d] 0x%016llx\n", reg, ! 1329: env->mmuregs[reg]); ! 1330: } ! 1331: break; 1.1.1.5 root 1332: case 8: /* User code access, XXX */ 1333: case 9: /* Supervisor code access, XXX */ 1334: default: 1.1.1.6 ! root 1335: do_unassigned_access(addr, 1, 0, asi, size); 1.1.1.5 root 1336: break; 1337: } 1338: #ifdef DEBUG_ASI 1.1.1.6 ! root 1339: dump_asi("write", addr, asi, size, val); 1.1.1.5 root 1340: #endif 1341: } 1342: 1343: #endif /* CONFIG_USER_ONLY */ 1344: #else /* TARGET_SPARC64 */ 1345: 1346: #ifdef CONFIG_USER_ONLY 1.1.1.6 ! root 1347: uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) 1.1.1.5 root 1348: { 1349: uint64_t ret = 0; 1.1.1.6 ! root 1350: #if defined(DEBUG_ASI) ! 1351: target_ulong last_addr = addr; ! 1352: #endif 1.1.1.5 root 1353: 1354: if (asi < 0x80) 1355: raise_exception(TT_PRIV_ACT); 1356: 1.1.1.6 ! root 1357: helper_check_align(addr, size - 1); ! 1358: address_mask(env, &addr); ! 1359: 1.1.1.5 root 1360: switch (asi) { 1361: case 0x82: // Primary no-fault 1362: case 0x8a: // Primary no-fault LE 1.1.1.6 ! root 1363: if (page_check_range(addr, size, PAGE_READ) == -1) { ! 1364: #ifdef DEBUG_ASI ! 1365: dump_asi("read ", last_addr, asi, size, ret); ! 1366: #endif ! 1367: return 0; ! 1368: } ! 1369: // Fall through ! 1370: case 0x80: // Primary ! 1371: case 0x88: // Primary LE 1.1.1.5 root 1372: { 1373: switch(size) { 1374: case 1: 1.1.1.6 ! root 1375: ret = ldub_raw(addr); 1.1.1.5 root 1376: break; 1377: case 2: 1.1.1.6 ! root 1378: ret = lduw_raw(addr); 1.1.1.5 root 1379: break; 1380: case 4: 1.1.1.6 ! root 1381: ret = ldl_raw(addr); 1.1.1.5 root 1382: break; 1383: default: 1384: case 8: 1.1.1.6 ! root 1385: ret = ldq_raw(addr); 1.1.1.5 root 1386: break; 1387: } 1388: } 1389: break; 1390: case 0x83: // Secondary no-fault 1391: case 0x8b: // Secondary no-fault LE 1.1.1.6 ! root 1392: if (page_check_range(addr, size, PAGE_READ) == -1) { ! 1393: #ifdef DEBUG_ASI ! 1394: dump_asi("read ", last_addr, asi, size, ret); ! 1395: #endif ! 1396: return 0; ! 1397: } ! 1398: // Fall through ! 1399: case 0x81: // Secondary ! 1400: case 0x89: // Secondary LE 1.1.1.5 root 1401: // XXX 1402: break; 1403: default: 1404: break; 1405: } 1406: 1407: /* Convert from little endian */ 1408: switch (asi) { 1409: case 0x88: // Primary LE 1410: case 0x89: // Secondary LE 1411: case 0x8a: // Primary no-fault LE 1412: case 0x8b: // Secondary no-fault LE 1413: switch(size) { 1414: case 2: 1415: ret = bswap16(ret); 1416: break; 1417: case 4: 1418: ret = bswap32(ret); 1419: break; 1420: case 8: 1421: ret = bswap64(ret); 1422: break; 1423: default: 1424: break; 1425: } 1426: default: 1427: break; 1428: } 1429: 1430: /* Convert to signed number */ 1431: if (sign) { 1432: switch(size) { 1433: case 1: 1434: ret = (int8_t) ret; 1435: break; 1436: case 2: 1437: ret = (int16_t) ret; 1438: break; 1439: case 4: 1440: ret = (int32_t) ret; 1441: break; 1442: default: 1443: break; 1444: } 1445: } 1.1.1.6 ! root 1446: #ifdef DEBUG_ASI ! 1447: dump_asi("read ", last_addr, asi, size, ret); ! 1448: #endif ! 1449: return ret; 1.1.1.5 root 1450: } 1451: 1.1.1.6 ! root 1452: void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) 1.1.1.5 root 1453: { 1.1.1.6 ! root 1454: #ifdef DEBUG_ASI ! 1455: dump_asi("write", addr, asi, size, val); ! 1456: #endif 1.1.1.5 root 1457: if (asi < 0x80) 1458: raise_exception(TT_PRIV_ACT); 1459: 1.1.1.6 ! root 1460: helper_check_align(addr, size - 1); ! 1461: address_mask(env, &addr); ! 1462: 1.1.1.5 root 1463: /* Convert to little endian */ 1464: switch (asi) { 1465: case 0x88: // Primary LE 1466: case 0x89: // Secondary LE 1467: switch(size) { 1468: case 2: 1.1.1.6 ! root 1469: addr = bswap16(addr); 1.1.1.5 root 1470: break; 1471: case 4: 1.1.1.6 ! root 1472: addr = bswap32(addr); 1.1.1.5 root 1473: break; 1474: case 8: 1.1.1.6 ! root 1475: addr = bswap64(addr); 1.1.1.5 root 1476: break; 1477: default: 1478: break; 1479: } 1480: default: 1481: break; 1482: } 1483: 1484: switch(asi) { 1485: case 0x80: // Primary 1486: case 0x88: // Primary LE 1487: { 1.1.1.2 root 1488: switch(size) { 1489: case 1: 1.1.1.6 ! root 1490: stb_raw(addr, val); 1.1.1.2 root 1491: break; 1492: case 2: 1.1.1.6 ! root 1493: stw_raw(addr, val); 1.1.1.2 root 1494: break; 1495: case 4: 1.1.1.6 ! root 1496: stl_raw(addr, val); 1.1.1.2 root 1497: break; 1498: case 8: 1.1.1.5 root 1499: default: 1.1.1.6 ! root 1500: stq_raw(addr, val); 1.1.1.2 root 1501: break; 1502: } 1.1.1.5 root 1503: } 1504: break; 1505: case 0x81: // Secondary 1506: case 0x89: // Secondary LE 1507: // XXX 1508: return; 1509: 1510: case 0x82: // Primary no-fault, RO 1511: case 0x83: // Secondary no-fault, RO 1512: case 0x8a: // Primary no-fault LE, RO 1513: case 0x8b: // Secondary no-fault LE, RO 1.1 root 1514: default: 1.1.1.6 ! root 1515: do_unassigned_access(addr, 1, 0, 1, size); 1.1.1.5 root 1516: return; 1.1 root 1517: } 1518: } 1519: 1.1.1.5 root 1520: #else /* CONFIG_USER_ONLY */ 1.1 root 1521: 1.1.1.6 ! root 1522: uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) 1.1 root 1523: { 1524: uint64_t ret = 0; 1.1.1.6 ! root 1525: #if defined(DEBUG_ASI) ! 1526: target_ulong last_addr = addr; ! 1527: #endif 1.1 root 1528: 1.1.1.5 root 1529: if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) 1.1.1.6 ! root 1530: || ((env->def->features & CPU_FEATURE_HYPV) ! 1531: && asi >= 0x30 && asi < 0x80 ! 1532: && !(env->hpstate & HS_PRIV))) 1.1.1.5 root 1533: raise_exception(TT_PRIV_ACT); 1.1 root 1534: 1.1.1.6 ! root 1535: helper_check_align(addr, size - 1); 1.1 root 1536: switch (asi) { 1.1.1.6 ! root 1537: case 0x82: // Primary no-fault ! 1538: case 0x8a: // Primary no-fault LE ! 1539: if (cpu_get_phys_page_debug(env, addr) == -1ULL) { ! 1540: #ifdef DEBUG_ASI ! 1541: dump_asi("read ", last_addr, asi, size, ret); ! 1542: #endif ! 1543: return 0; ! 1544: } ! 1545: // Fall through 1.1.1.5 root 1546: case 0x10: // As if user primary 1547: case 0x18: // As if user primary LE 1548: case 0x80: // Primary 1549: case 0x88: // Primary LE 1.1.1.6 ! root 1550: case 0xe2: // UA2007 Primary block init ! 1551: case 0xe3: // UA2007 Secondary block init 1.1.1.5 root 1552: if ((asi & 0x80) && (env->pstate & PS_PRIV)) { 1.1.1.6 ! root 1553: if ((env->def->features & CPU_FEATURE_HYPV) ! 1554: && env->hpstate & HS_PRIV) { 1.1.1.5 root 1555: switch(size) { 1556: case 1: 1.1.1.6 ! root 1557: ret = ldub_hypv(addr); 1.1.1.5 root 1558: break; 1559: case 2: 1.1.1.6 ! root 1560: ret = lduw_hypv(addr); 1.1.1.5 root 1561: break; 1562: case 4: 1.1.1.6 ! root 1563: ret = ldl_hypv(addr); 1.1.1.5 root 1564: break; 1565: default: 1566: case 8: 1.1.1.6 ! root 1567: ret = ldq_hypv(addr); 1.1.1.5 root 1568: break; 1569: } 1570: } else { 1571: switch(size) { 1572: case 1: 1.1.1.6 ! root 1573: ret = ldub_kernel(addr); 1.1.1.5 root 1574: break; 1575: case 2: 1.1.1.6 ! root 1576: ret = lduw_kernel(addr); 1.1.1.5 root 1577: break; 1578: case 4: 1.1.1.6 ! root 1579: ret = ldl_kernel(addr); 1.1.1.5 root 1580: break; 1581: default: 1582: case 8: 1.1.1.6 ! root 1583: ret = ldq_kernel(addr); 1.1.1.5 root 1584: break; 1585: } 1586: } 1587: } else { 1588: switch(size) { 1589: case 1: 1.1.1.6 ! root 1590: ret = ldub_user(addr); 1.1.1.5 root 1591: break; 1592: case 2: 1.1.1.6 ! root 1593: ret = lduw_user(addr); 1.1.1.5 root 1594: break; 1595: case 4: 1.1.1.6 ! root 1596: ret = ldl_user(addr); 1.1.1.5 root 1597: break; 1598: default: 1599: case 8: 1.1.1.6 ! root 1600: ret = ldq_user(addr); 1.1.1.5 root 1601: break; 1602: } 1603: } 1604: break; 1.1 root 1605: case 0x14: // Bypass 1606: case 0x15: // Bypass, non-cacheable 1.1.1.5 root 1607: case 0x1c: // Bypass LE 1608: case 0x1d: // Bypass, non-cacheable LE 1609: { 1.1.1.2 root 1610: switch(size) { 1611: case 1: 1.1.1.6 ! root 1612: ret = ldub_phys(addr); 1.1.1.2 root 1613: break; 1614: case 2: 1.1.1.6 ! root 1615: ret = lduw_phys(addr); 1.1.1.2 root 1616: break; 1617: case 4: 1.1.1.6 ! root 1618: ret = ldl_phys(addr); 1.1.1.2 root 1619: break; 1620: default: 1621: case 8: 1.1.1.6 ! root 1622: ret = ldq_phys(addr); 1.1.1.2 root 1623: break; 1624: } 1.1.1.5 root 1625: break; 1626: } 1.1.1.6 ! root 1627: case 0x24: // Nucleus quad LDD 128 bit atomic ! 1628: case 0x2c: // Nucleus quad LDD 128 bit atomic LE ! 1629: // Only ldda allowed ! 1630: raise_exception(TT_ILL_INSN); ! 1631: return 0; ! 1632: case 0x83: // Secondary no-fault ! 1633: case 0x8b: // Secondary no-fault LE ! 1634: if (cpu_get_phys_page_debug(env, addr) == -1ULL) { ! 1635: #ifdef DEBUG_ASI ! 1636: dump_asi("read ", last_addr, asi, size, ret); ! 1637: #endif ! 1638: return 0; ! 1639: } ! 1640: // Fall through 1.1 root 1641: case 0x04: // Nucleus 1642: case 0x0c: // Nucleus Little Endian (LE) 1643: case 0x11: // As if user secondary 1644: case 0x19: // As if user secondary LE 1645: case 0x4a: // UPA config 1.1.1.5 root 1646: case 0x81: // Secondary 1.1 root 1647: case 0x89: // Secondary LE 1.1.1.5 root 1648: // XXX 1649: break; 1.1 root 1650: case 0x45: // LSU 1.1.1.5 root 1651: ret = env->lsu; 1652: break; 1.1 root 1653: case 0x50: // I-MMU regs 1.1.1.5 root 1654: { 1.1.1.6 ! root 1655: int reg = (addr >> 3) & 0xf; 1.1 root 1656: 1.1.1.5 root 1657: ret = env->immuregs[reg]; 1658: break; 1659: } 1.1 root 1660: case 0x51: // I-MMU 8k TSB pointer 1661: case 0x52: // I-MMU 64k TSB pointer 1.1.1.5 root 1662: // XXX 1663: break; 1.1.1.6 ! root 1664: case 0x55: // I-MMU data access ! 1665: { ! 1666: int reg = (addr >> 3) & 0x3f; ! 1667: ! 1668: ret = env->itlb_tte[reg]; ! 1669: break; ! 1670: } 1.1 root 1671: case 0x56: // I-MMU tag read 1.1.1.5 root 1672: { 1.1.1.6 ! root 1673: int reg = (addr >> 3) & 0x3f; 1.1.1.5 root 1674: 1.1.1.6 ! root 1675: ret = env->itlb_tag[reg]; 1.1.1.5 root 1676: break; 1677: } 1.1 root 1678: case 0x58: // D-MMU regs 1.1.1.5 root 1679: { 1.1.1.6 ! root 1680: int reg = (addr >> 3) & 0xf; 1.1 root 1681: 1.1.1.5 root 1682: ret = env->dmmuregs[reg]; 1683: break; 1684: } 1.1.1.6 ! root 1685: case 0x5d: // D-MMU data access ! 1686: { ! 1687: int reg = (addr >> 3) & 0x3f; ! 1688: ! 1689: ret = env->dtlb_tte[reg]; ! 1690: break; ! 1691: } 1.1 root 1692: case 0x5e: // D-MMU tag read 1.1.1.5 root 1693: { 1.1.1.6 ! root 1694: int reg = (addr >> 3) & 0x3f; 1.1.1.5 root 1695: 1.1.1.6 ! root 1696: ret = env->dtlb_tag[reg]; 1.1.1.5 root 1697: break; 1698: } 1.1.1.6 ! root 1699: case 0x46: // D-cache data ! 1700: case 0x47: // D-cache tag access ! 1701: case 0x4b: // E-cache error enable ! 1702: case 0x4c: // E-cache asynchronous fault status ! 1703: case 0x4d: // E-cache asynchronous fault address ! 1704: case 0x4e: // E-cache tag data ! 1705: case 0x66: // I-cache instruction access ! 1706: case 0x67: // I-cache tag access ! 1707: case 0x6e: // I-cache predecode ! 1708: case 0x6f: // I-cache LRU etc. ! 1709: case 0x76: // E-cache tag ! 1710: case 0x7e: // E-cache tag ! 1711: break; 1.1 root 1712: case 0x59: // D-MMU 8k TSB pointer 1713: case 0x5a: // D-MMU 64k TSB pointer 1714: case 0x5b: // D-MMU data pointer 1715: case 0x48: // Interrupt dispatch, RO 1716: case 0x49: // Interrupt data receive 1717: case 0x7f: // Incoming interrupt vector, RO 1.1.1.5 root 1718: // XXX 1719: break; 1.1 root 1720: case 0x54: // I-MMU data in, WO 1721: case 0x57: // I-MMU demap, WO 1722: case 0x5c: // D-MMU data in, WO 1723: case 0x5f: // D-MMU demap, WO 1724: case 0x77: // Interrupt vector, WO 1725: default: 1.1.1.6 ! root 1726: do_unassigned_access(addr, 0, 0, 1, size); 1.1.1.5 root 1727: ret = 0; 1728: break; 1729: } 1730: 1731: /* Convert from little endian */ 1732: switch (asi) { 1733: case 0x0c: // Nucleus Little Endian (LE) 1734: case 0x18: // As if user primary LE 1735: case 0x19: // As if user secondary LE 1736: case 0x1c: // Bypass LE 1737: case 0x1d: // Bypass, non-cacheable LE 1738: case 0x88: // Primary LE 1739: case 0x89: // Secondary LE 1740: case 0x8a: // Primary no-fault LE 1741: case 0x8b: // Secondary no-fault LE 1742: switch(size) { 1743: case 2: 1744: ret = bswap16(ret); 1745: break; 1746: case 4: 1747: ret = bswap32(ret); 1748: break; 1749: case 8: 1750: ret = bswap64(ret); 1751: break; 1752: default: 1753: break; 1754: } 1755: default: 1756: break; 1757: } 1758: 1759: /* Convert to signed number */ 1760: if (sign) { 1761: switch(size) { 1762: case 1: 1763: ret = (int8_t) ret; 1764: break; 1765: case 2: 1766: ret = (int16_t) ret; 1767: break; 1768: case 4: 1769: ret = (int32_t) ret; 1770: break; 1771: default: 1772: break; 1773: } 1.1 root 1774: } 1.1.1.6 ! root 1775: #ifdef DEBUG_ASI ! 1776: dump_asi("read ", last_addr, asi, size, ret); ! 1777: #endif ! 1778: return ret; 1.1 root 1779: } 1780: 1.1.1.6 ! root 1781: void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) 1.1 root 1782: { 1.1.1.6 ! root 1783: #ifdef DEBUG_ASI ! 1784: dump_asi("write", addr, asi, size, val); ! 1785: #endif 1.1.1.5 root 1786: if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) 1.1.1.6 ! root 1787: || ((env->def->features & CPU_FEATURE_HYPV) ! 1788: && asi >= 0x30 && asi < 0x80 ! 1789: && !(env->hpstate & HS_PRIV))) 1.1.1.5 root 1790: raise_exception(TT_PRIV_ACT); 1791: 1.1.1.6 ! root 1792: helper_check_align(addr, size - 1); 1.1.1.5 root 1793: /* Convert to little endian */ 1794: switch (asi) { 1795: case 0x0c: // Nucleus Little Endian (LE) 1796: case 0x18: // As if user primary LE 1797: case 0x19: // As if user secondary LE 1798: case 0x1c: // Bypass LE 1799: case 0x1d: // Bypass, non-cacheable LE 1800: case 0x88: // Primary LE 1801: case 0x89: // Secondary LE 1802: switch(size) { 1803: case 2: 1.1.1.6 ! root 1804: addr = bswap16(addr); 1.1.1.5 root 1805: break; 1806: case 4: 1.1.1.6 ! root 1807: addr = bswap32(addr); 1.1.1.5 root 1808: break; 1809: case 8: 1.1.1.6 ! root 1810: addr = bswap64(addr); 1.1.1.5 root 1811: break; 1812: default: 1813: break; 1814: } 1815: default: 1816: break; 1817: } 1.1 root 1818: 1819: switch(asi) { 1.1.1.5 root 1820: case 0x10: // As if user primary 1821: case 0x18: // As if user primary LE 1822: case 0x80: // Primary 1823: case 0x88: // Primary LE 1.1.1.6 ! root 1824: case 0xe2: // UA2007 Primary block init ! 1825: case 0xe3: // UA2007 Secondary block init 1.1.1.5 root 1826: if ((asi & 0x80) && (env->pstate & PS_PRIV)) { 1.1.1.6 ! root 1827: if ((env->def->features & CPU_FEATURE_HYPV) ! 1828: && env->hpstate & HS_PRIV) { 1.1.1.5 root 1829: switch(size) { 1830: case 1: 1.1.1.6 ! root 1831: stb_hypv(addr, val); 1.1.1.5 root 1832: break; 1833: case 2: 1.1.1.6 ! root 1834: stw_hypv(addr, val); 1.1.1.5 root 1835: break; 1836: case 4: 1.1.1.6 ! root 1837: stl_hypv(addr, val); 1.1.1.5 root 1838: break; 1839: case 8: 1840: default: 1.1.1.6 ! root 1841: stq_hypv(addr, val); 1.1.1.5 root 1842: break; 1843: } 1844: } else { 1845: switch(size) { 1846: case 1: 1.1.1.6 ! root 1847: stb_kernel(addr, val); 1.1.1.5 root 1848: break; 1849: case 2: 1.1.1.6 ! root 1850: stw_kernel(addr, val); 1.1.1.5 root 1851: break; 1852: case 4: 1.1.1.6 ! root 1853: stl_kernel(addr, val); 1.1.1.5 root 1854: break; 1855: case 8: 1856: default: 1.1.1.6 ! root 1857: stq_kernel(addr, val); 1.1.1.5 root 1858: break; 1859: } 1860: } 1861: } else { 1862: switch(size) { 1863: case 1: 1.1.1.6 ! root 1864: stb_user(addr, val); 1.1.1.5 root 1865: break; 1866: case 2: 1.1.1.6 ! root 1867: stw_user(addr, val); 1.1.1.5 root 1868: break; 1869: case 4: 1.1.1.6 ! root 1870: stl_user(addr, val); 1.1.1.5 root 1871: break; 1872: case 8: 1873: default: 1.1.1.6 ! root 1874: stq_user(addr, val); 1.1.1.5 root 1875: break; 1876: } 1877: } 1878: break; 1.1 root 1879: case 0x14: // Bypass 1880: case 0x15: // Bypass, non-cacheable 1.1.1.5 root 1881: case 0x1c: // Bypass LE 1882: case 0x1d: // Bypass, non-cacheable LE 1883: { 1.1.1.2 root 1884: switch(size) { 1885: case 1: 1.1.1.6 ! root 1886: stb_phys(addr, val); 1.1.1.2 root 1887: break; 1888: case 2: 1.1.1.6 ! root 1889: stw_phys(addr, val); 1.1.1.2 root 1890: break; 1891: case 4: 1.1.1.6 ! root 1892: stl_phys(addr, val); 1.1.1.2 root 1893: break; 1894: case 8: 1895: default: 1.1.1.6 ! root 1896: stq_phys(addr, val); 1.1.1.2 root 1897: break; 1898: } 1.1.1.5 root 1899: } 1900: return; 1.1.1.6 ! root 1901: case 0x24: // Nucleus quad LDD 128 bit atomic ! 1902: case 0x2c: // Nucleus quad LDD 128 bit atomic LE ! 1903: // Only ldda allowed ! 1904: raise_exception(TT_ILL_INSN); ! 1905: return; 1.1 root 1906: case 0x04: // Nucleus 1907: case 0x0c: // Nucleus Little Endian (LE) 1908: case 0x11: // As if user secondary 1909: case 0x19: // As if user secondary LE 1910: case 0x4a: // UPA config 1.1.1.5 root 1911: case 0x81: // Secondary 1.1 root 1912: case 0x89: // Secondary LE 1.1.1.5 root 1913: // XXX 1914: return; 1.1 root 1915: case 0x45: // LSU 1.1.1.5 root 1916: { 1917: uint64_t oldreg; 1.1 root 1918: 1.1.1.5 root 1919: oldreg = env->lsu; 1.1.1.6 ! root 1920: env->lsu = val & (DMMU_E | IMMU_E); 1.1.1.5 root 1921: // Mappings generated during D/I MMU disabled mode are 1922: // invalid in normal mode 1923: if (oldreg != env->lsu) { 1.1.1.6 ! root 1924: DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", ! 1925: oldreg, env->lsu); 1.1 root 1926: #ifdef DEBUG_MMU 1.1.1.5 root 1927: dump_mmu(env); 1.1 root 1928: #endif 1.1.1.5 root 1929: tlb_flush(env, 1); 1930: } 1931: return; 1932: } 1.1 root 1933: case 0x50: // I-MMU regs 1.1.1.5 root 1934: { 1.1.1.6 ! root 1935: int reg = (addr >> 3) & 0xf; 1.1.1.5 root 1936: uint64_t oldreg; 1937: 1938: oldreg = env->immuregs[reg]; 1.1 root 1939: switch(reg) { 1940: case 0: // RO 1941: case 4: 1942: return; 1943: case 1: // Not in I-MMU 1944: case 2: 1945: case 7: 1946: case 8: 1947: return; 1948: case 3: // SFSR 1.1.1.6 ! root 1949: if ((val & 1) == 0) ! 1950: val = 0; // Clear SFSR 1.1 root 1951: break; 1952: case 5: // TSB access 1953: case 6: // Tag access 1954: default: 1955: break; 1956: } 1.1.1.6 ! root 1957: env->immuregs[reg] = val; 1.1 root 1958: if (oldreg != env->immuregs[reg]) { 1.1.1.6 ! root 1959: DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" ! 1960: PRIx64 "\n", reg, oldreg, env->immuregs[reg]); 1.1 root 1961: } 1.1.1.5 root 1962: #ifdef DEBUG_MMU 1963: dump_mmu(env); 1.1 root 1964: #endif 1.1.1.5 root 1965: return; 1966: } 1.1 root 1967: case 0x54: // I-MMU data in 1.1.1.5 root 1968: { 1969: unsigned int i; 1.1 root 1970: 1.1.1.5 root 1971: // Try finding an invalid entry 1972: for (i = 0; i < 64; i++) { 1973: if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) { 1974: env->itlb_tag[i] = env->immuregs[6]; 1.1.1.6 ! root 1975: env->itlb_tte[i] = val; 1.1.1.5 root 1976: return; 1977: } 1978: } 1979: // Try finding an unlocked entry 1980: for (i = 0; i < 64; i++) { 1981: if ((env->itlb_tte[i] & 0x40) == 0) { 1982: env->itlb_tag[i] = env->immuregs[6]; 1.1.1.6 ! root 1983: env->itlb_tte[i] = val; 1.1.1.5 root 1984: return; 1985: } 1986: } 1987: // error state? 1988: return; 1989: } 1.1 root 1990: case 0x55: // I-MMU data access 1.1.1.5 root 1991: { 1.1.1.6 ! root 1992: // TODO: auto demap ! 1993: ! 1994: unsigned int i = (addr >> 3) & 0x3f; 1.1 root 1995: 1.1.1.5 root 1996: env->itlb_tag[i] = env->immuregs[6]; 1.1.1.6 ! root 1997: env->itlb_tte[i] = val; 1.1.1.5 root 1998: return; 1999: } 1.1 root 2000: case 0x57: // I-MMU demap 1.1.1.6 ! root 2001: { ! 2002: unsigned int i; ! 2003: ! 2004: for (i = 0; i < 64; i++) { ! 2005: if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) { ! 2006: target_ulong mask = 0xffffffffffffe000ULL; ! 2007: ! 2008: mask <<= 3 * ((env->itlb_tte[i] >> 61) & 3); ! 2009: if ((val & mask) == (env->itlb_tag[i] & mask)) { ! 2010: env->itlb_tag[i] = 0; ! 2011: env->itlb_tte[i] = 0; ! 2012: } ! 2013: return; ! 2014: } ! 2015: } ! 2016: } 1.1.1.5 root 2017: return; 1.1 root 2018: case 0x58: // D-MMU regs 1.1.1.5 root 2019: { 1.1.1.6 ! root 2020: int reg = (addr >> 3) & 0xf; 1.1.1.5 root 2021: uint64_t oldreg; 2022: 2023: oldreg = env->dmmuregs[reg]; 1.1 root 2024: switch(reg) { 2025: case 0: // RO 2026: case 4: 2027: return; 2028: case 3: // SFSR 1.1.1.6 ! root 2029: if ((val & 1) == 0) { ! 2030: val = 0; // Clear SFSR, Fault address 1.1.1.5 root 2031: env->dmmuregs[4] = 0; 2032: } 1.1.1.6 ! root 2033: env->dmmuregs[reg] = val; 1.1 root 2034: break; 2035: case 1: // Primary context 2036: case 2: // Secondary context 2037: case 5: // TSB access 2038: case 6: // Tag access 2039: case 7: // Virtual Watchpoint 2040: case 8: // Physical Watchpoint 2041: default: 2042: break; 2043: } 1.1.1.6 ! root 2044: env->dmmuregs[reg] = val; 1.1 root 2045: if (oldreg != env->dmmuregs[reg]) { 1.1.1.6 ! root 2046: DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" ! 2047: PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]); 1.1 root 2048: } 1.1.1.5 root 2049: #ifdef DEBUG_MMU 2050: dump_mmu(env); 1.1 root 2051: #endif 1.1.1.5 root 2052: return; 2053: } 1.1 root 2054: case 0x5c: // D-MMU data in 1.1.1.5 root 2055: { 2056: unsigned int i; 1.1 root 2057: 1.1.1.5 root 2058: // Try finding an invalid entry 2059: for (i = 0; i < 64; i++) { 2060: if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) { 2061: env->dtlb_tag[i] = env->dmmuregs[6]; 1.1.1.6 ! root 2062: env->dtlb_tte[i] = val; 1.1.1.5 root 2063: return; 2064: } 2065: } 2066: // Try finding an unlocked entry 2067: for (i = 0; i < 64; i++) { 2068: if ((env->dtlb_tte[i] & 0x40) == 0) { 2069: env->dtlb_tag[i] = env->dmmuregs[6]; 1.1.1.6 ! root 2070: env->dtlb_tte[i] = val; 1.1.1.5 root 2071: return; 2072: } 2073: } 2074: // error state? 2075: return; 2076: } 1.1 root 2077: case 0x5d: // D-MMU data access 1.1.1.5 root 2078: { 1.1.1.6 ! root 2079: unsigned int i = (addr >> 3) & 0x3f; 1.1 root 2080: 1.1.1.5 root 2081: env->dtlb_tag[i] = env->dmmuregs[6]; 1.1.1.6 ! root 2082: env->dtlb_tte[i] = val; 1.1.1.5 root 2083: return; 2084: } 1.1 root 2085: case 0x5f: // D-MMU demap 1.1.1.6 ! root 2086: { ! 2087: unsigned int i; ! 2088: ! 2089: for (i = 0; i < 64; i++) { ! 2090: if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) { ! 2091: target_ulong mask = 0xffffffffffffe000ULL; ! 2092: ! 2093: mask <<= 3 * ((env->dtlb_tte[i] >> 61) & 3); ! 2094: if ((val & mask) == (env->dtlb_tag[i] & mask)) { ! 2095: env->dtlb_tag[i] = 0; ! 2096: env->dtlb_tte[i] = 0; ! 2097: } ! 2098: return; ! 2099: } ! 2100: } ! 2101: } ! 2102: return; 1.1 root 2103: case 0x49: // Interrupt data receive 1.1.1.5 root 2104: // XXX 2105: return; 1.1.1.6 ! root 2106: case 0x46: // D-cache data ! 2107: case 0x47: // D-cache tag access ! 2108: case 0x4b: // E-cache error enable ! 2109: case 0x4c: // E-cache asynchronous fault status ! 2110: case 0x4d: // E-cache asynchronous fault address ! 2111: case 0x4e: // E-cache tag data ! 2112: case 0x66: // I-cache instruction access ! 2113: case 0x67: // I-cache tag access ! 2114: case 0x6e: // I-cache predecode ! 2115: case 0x6f: // I-cache LRU etc. ! 2116: case 0x76: // E-cache tag ! 2117: case 0x7e: // E-cache tag ! 2118: return; 1.1 root 2119: case 0x51: // I-MMU 8k TSB pointer, RO 2120: case 0x52: // I-MMU 64k TSB pointer, RO 2121: case 0x56: // I-MMU tag read, RO 2122: case 0x59: // D-MMU 8k TSB pointer, RO 2123: case 0x5a: // D-MMU 64k TSB pointer, RO 2124: case 0x5b: // D-MMU data pointer, RO 2125: case 0x5e: // D-MMU tag read, RO 2126: case 0x48: // Interrupt dispatch, RO 2127: case 0x7f: // Incoming interrupt vector, RO 2128: case 0x82: // Primary no-fault, RO 2129: case 0x83: // Secondary no-fault, RO 2130: case 0x8a: // Primary no-fault LE, RO 2131: case 0x8b: // Secondary no-fault LE, RO 2132: default: 1.1.1.6 ! root 2133: do_unassigned_access(addr, 1, 0, 1, size); 1.1.1.5 root 2134: return; 2135: } 2136: } 2137: #endif /* CONFIG_USER_ONLY */ 2138: 1.1.1.6 ! root 2139: void helper_ldda_asi(target_ulong addr, int asi, int rd) ! 2140: { ! 2141: if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) ! 2142: || ((env->def->features & CPU_FEATURE_HYPV) ! 2143: && asi >= 0x30 && asi < 0x80 ! 2144: && !(env->hpstate & HS_PRIV))) ! 2145: raise_exception(TT_PRIV_ACT); ! 2146: ! 2147: switch (asi) { ! 2148: case 0x24: // Nucleus quad LDD 128 bit atomic ! 2149: case 0x2c: // Nucleus quad LDD 128 bit atomic LE ! 2150: helper_check_align(addr, 0xf); ! 2151: if (rd == 0) { ! 2152: env->gregs[1] = ldq_kernel(addr + 8); ! 2153: if (asi == 0x2c) ! 2154: bswap64s(&env->gregs[1]); ! 2155: } else if (rd < 8) { ! 2156: env->gregs[rd] = ldq_kernel(addr); ! 2157: env->gregs[rd + 1] = ldq_kernel(addr + 8); ! 2158: if (asi == 0x2c) { ! 2159: bswap64s(&env->gregs[rd]); ! 2160: bswap64s(&env->gregs[rd + 1]); ! 2161: } ! 2162: } else { ! 2163: env->regwptr[rd] = ldq_kernel(addr); ! 2164: env->regwptr[rd + 1] = ldq_kernel(addr + 8); ! 2165: if (asi == 0x2c) { ! 2166: bswap64s(&env->regwptr[rd]); ! 2167: bswap64s(&env->regwptr[rd + 1]); ! 2168: } ! 2169: } ! 2170: break; ! 2171: default: ! 2172: helper_check_align(addr, 0x3); ! 2173: if (rd == 0) ! 2174: env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0); ! 2175: else if (rd < 8) { ! 2176: env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0); ! 2177: env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0); ! 2178: } else { ! 2179: env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0); ! 2180: env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0); ! 2181: } ! 2182: break; ! 2183: } ! 2184: } ! 2185: ! 2186: void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) 1.1.1.5 root 2187: { 2188: unsigned int i; 1.1.1.6 ! root 2189: target_ulong val; 1.1.1.5 root 2190: 1.1.1.6 ! root 2191: helper_check_align(addr, 3); 1.1.1.5 root 2192: switch (asi) { 2193: case 0xf0: // Block load primary 2194: case 0xf1: // Block load secondary 2195: case 0xf8: // Block load primary LE 2196: case 0xf9: // Block load secondary LE 2197: if (rd & 7) { 2198: raise_exception(TT_ILL_INSN); 2199: return; 2200: } 1.1.1.6 ! root 2201: helper_check_align(addr, 0x3f); 1.1.1.5 root 2202: for (i = 0; i < 16; i++) { 1.1.1.6 ! root 2203: *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, ! 2204: 0); ! 2205: addr += 4; 1.1.1.5 root 2206: } 2207: 2208: return; 2209: default: 2210: break; 2211: } 2212: 1.1.1.6 ! root 2213: val = helper_ld_asi(addr, asi, size, 0); 1.1.1.5 root 2214: switch(size) { 2215: default: 2216: case 4: 1.1.1.6 ! root 2217: *((uint32_t *)&env->fpr[rd]) = val; 1.1.1.5 root 2218: break; 2219: case 8: 1.1.1.6 ! root 2220: *((int64_t *)&DT0) = val; 1.1.1.5 root 2221: break; 2222: case 16: 2223: // XXX 2224: break; 1.1 root 2225: } 2226: } 1.1.1.5 root 2227: 1.1.1.6 ! root 2228: void helper_stf_asi(target_ulong addr, int asi, int size, int rd) 1.1.1.5 root 2229: { 2230: unsigned int i; 1.1.1.6 ! root 2231: target_ulong val = 0; 1.1.1.5 root 2232: 1.1.1.6 ! root 2233: helper_check_align(addr, 3); 1.1.1.5 root 2234: switch (asi) { 1.1.1.6 ! root 2235: case 0xe0: // UA2007 Block commit store primary (cache flush) ! 2236: case 0xe1: // UA2007 Block commit store secondary (cache flush) 1.1.1.5 root 2237: case 0xf0: // Block store primary 2238: case 0xf1: // Block store secondary 2239: case 0xf8: // Block store primary LE 2240: case 0xf9: // Block store secondary LE 2241: if (rd & 7) { 2242: raise_exception(TT_ILL_INSN); 2243: return; 2244: } 1.1.1.6 ! root 2245: helper_check_align(addr, 0x3f); 1.1.1.5 root 2246: for (i = 0; i < 16; i++) { 1.1.1.6 ! root 2247: val = *(uint32_t *)&env->fpr[rd++]; ! 2248: helper_st_asi(addr, val, asi & 0x8f, 4); ! 2249: addr += 4; 1.1.1.5 root 2250: } 2251: 2252: return; 2253: default: 2254: break; 2255: } 2256: 2257: switch(size) { 2258: default: 2259: case 4: 1.1.1.6 ! root 2260: val = *((uint32_t *)&env->fpr[rd]); 1.1.1.5 root 2261: break; 2262: case 8: 1.1.1.6 ! root 2263: val = *((int64_t *)&DT0); 1.1.1.5 root 2264: break; 2265: case 16: 2266: // XXX 2267: break; 2268: } 1.1.1.6 ! root 2269: helper_st_asi(addr, val, asi, size); ! 2270: } ! 2271: ! 2272: target_ulong helper_cas_asi(target_ulong addr, target_ulong val1, ! 2273: target_ulong val2, uint32_t asi) ! 2274: { ! 2275: target_ulong ret; ! 2276: ! 2277: val2 &= 0xffffffffUL; ! 2278: ret = helper_ld_asi(addr, asi, 4, 0); ! 2279: ret &= 0xffffffffUL; ! 2280: if (val2 == ret) ! 2281: helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4); ! 2282: return ret; 1.1.1.5 root 2283: } 2284: 1.1.1.6 ! root 2285: target_ulong helper_casx_asi(target_ulong addr, target_ulong val1, ! 2286: target_ulong val2, uint32_t asi) ! 2287: { ! 2288: target_ulong ret; ! 2289: ! 2290: ret = helper_ld_asi(addr, asi, 8, 0); ! 2291: if (val2 == ret) ! 2292: helper_st_asi(addr, val1, asi, 8); ! 2293: return ret; ! 2294: } 1.1.1.5 root 2295: #endif /* TARGET_SPARC64 */ 1.1 root 2296: 2297: #ifndef TARGET_SPARC64 1.1.1.6 ! root 2298: void helper_rett(void) 1.1 root 2299: { 2300: unsigned int cwp; 2301: 1.1.1.5 root 2302: if (env->psret == 1) 2303: raise_exception(TT_ILL_INSN); 2304: 1.1 root 2305: env->psret = 1; 1.1.1.6 ! root 2306: cwp = cpu_cwp_inc(env, env->cwp + 1) ; 1.1 root 2307: if (env->wim & (1 << cwp)) { 2308: raise_exception(TT_WIN_UNF); 2309: } 2310: set_cwp(cwp); 2311: env->psrs = env->psrps; 2312: } 2313: #endif 2314: 1.1.1.6 ! root 2315: target_ulong helper_udiv(target_ulong a, target_ulong b) ! 2316: { ! 2317: uint64_t x0; ! 2318: uint32_t x1; ! 2319: ! 2320: x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32); ! 2321: x1 = b; ! 2322: ! 2323: if (x1 == 0) { ! 2324: raise_exception(TT_DIV_ZERO); ! 2325: } ! 2326: ! 2327: x0 = x0 / x1; ! 2328: if (x0 > 0xffffffff) { ! 2329: env->cc_src2 = 1; ! 2330: return 0xffffffff; ! 2331: } else { ! 2332: env->cc_src2 = 0; ! 2333: return x0; ! 2334: } ! 2335: } ! 2336: ! 2337: target_ulong helper_sdiv(target_ulong a, target_ulong b) ! 2338: { ! 2339: int64_t x0; ! 2340: int32_t x1; ! 2341: ! 2342: x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32); ! 2343: x1 = b; ! 2344: ! 2345: if (x1 == 0) { ! 2346: raise_exception(TT_DIV_ZERO); ! 2347: } ! 2348: ! 2349: x0 = x0 / x1; ! 2350: if ((int32_t) x0 != x0) { ! 2351: env->cc_src2 = 1; ! 2352: return x0 < 0? 0x80000000: 0x7fffffff; ! 2353: } else { ! 2354: env->cc_src2 = 0; ! 2355: return x0; ! 2356: } ! 2357: } ! 2358: ! 2359: void helper_stdf(target_ulong addr, int mem_idx) ! 2360: { ! 2361: helper_check_align(addr, 7); ! 2362: #if !defined(CONFIG_USER_ONLY) ! 2363: switch (mem_idx) { ! 2364: case 0: ! 2365: stfq_user(addr, DT0); ! 2366: break; ! 2367: case 1: ! 2368: stfq_kernel(addr, DT0); ! 2369: break; ! 2370: #ifdef TARGET_SPARC64 ! 2371: case 2: ! 2372: stfq_hypv(addr, DT0); ! 2373: break; ! 2374: #endif ! 2375: default: ! 2376: break; ! 2377: } ! 2378: #else ! 2379: address_mask(env, &addr); ! 2380: stfq_raw(addr, DT0); ! 2381: #endif ! 2382: } ! 2383: ! 2384: void helper_lddf(target_ulong addr, int mem_idx) ! 2385: { ! 2386: helper_check_align(addr, 7); ! 2387: #if !defined(CONFIG_USER_ONLY) ! 2388: switch (mem_idx) { ! 2389: case 0: ! 2390: DT0 = ldfq_user(addr); ! 2391: break; ! 2392: case 1: ! 2393: DT0 = ldfq_kernel(addr); ! 2394: break; ! 2395: #ifdef TARGET_SPARC64 ! 2396: case 2: ! 2397: DT0 = ldfq_hypv(addr); ! 2398: break; ! 2399: #endif ! 2400: default: ! 2401: break; ! 2402: } ! 2403: #else ! 2404: address_mask(env, &addr); ! 2405: DT0 = ldfq_raw(addr); ! 2406: #endif ! 2407: } ! 2408: ! 2409: void helper_ldqf(target_ulong addr, int mem_idx) ! 2410: { ! 2411: // XXX add 128 bit load ! 2412: CPU_QuadU u; ! 2413: ! 2414: helper_check_align(addr, 7); ! 2415: #if !defined(CONFIG_USER_ONLY) ! 2416: switch (mem_idx) { ! 2417: case 0: ! 2418: u.ll.upper = ldq_user(addr); ! 2419: u.ll.lower = ldq_user(addr + 8); ! 2420: QT0 = u.q; ! 2421: break; ! 2422: case 1: ! 2423: u.ll.upper = ldq_kernel(addr); ! 2424: u.ll.lower = ldq_kernel(addr + 8); ! 2425: QT0 = u.q; ! 2426: break; ! 2427: #ifdef TARGET_SPARC64 ! 2428: case 2: ! 2429: u.ll.upper = ldq_hypv(addr); ! 2430: u.ll.lower = ldq_hypv(addr + 8); ! 2431: QT0 = u.q; ! 2432: break; ! 2433: #endif ! 2434: default: ! 2435: break; ! 2436: } ! 2437: #else ! 2438: address_mask(env, &addr); ! 2439: u.ll.upper = ldq_raw(addr); ! 2440: u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL); ! 2441: QT0 = u.q; ! 2442: #endif ! 2443: } ! 2444: ! 2445: void helper_stqf(target_ulong addr, int mem_idx) ! 2446: { ! 2447: // XXX add 128 bit store ! 2448: CPU_QuadU u; ! 2449: ! 2450: helper_check_align(addr, 7); ! 2451: #if !defined(CONFIG_USER_ONLY) ! 2452: switch (mem_idx) { ! 2453: case 0: ! 2454: u.q = QT0; ! 2455: stq_user(addr, u.ll.upper); ! 2456: stq_user(addr + 8, u.ll.lower); ! 2457: break; ! 2458: case 1: ! 2459: u.q = QT0; ! 2460: stq_kernel(addr, u.ll.upper); ! 2461: stq_kernel(addr + 8, u.ll.lower); ! 2462: break; ! 2463: #ifdef TARGET_SPARC64 ! 2464: case 2: ! 2465: u.q = QT0; ! 2466: stq_hypv(addr, u.ll.upper); ! 2467: stq_hypv(addr + 8, u.ll.lower); ! 2468: break; ! 2469: #endif ! 2470: default: ! 2471: break; ! 2472: } ! 2473: #else ! 2474: u.q = QT0; ! 2475: address_mask(env, &addr); ! 2476: stq_raw(addr, u.ll.upper); ! 2477: stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower); ! 2478: #endif ! 2479: } ! 2480: ! 2481: static inline void set_fsr(void) 1.1 root 2482: { 2483: int rnd_mode; 1.1.1.6 ! root 2484: 1.1 root 2485: switch (env->fsr & FSR_RD_MASK) { 2486: case FSR_RD_NEAREST: 2487: rnd_mode = float_round_nearest_even; 1.1.1.5 root 2488: break; 1.1 root 2489: default: 2490: case FSR_RD_ZERO: 2491: rnd_mode = float_round_to_zero; 1.1.1.5 root 2492: break; 1.1 root 2493: case FSR_RD_POS: 2494: rnd_mode = float_round_up; 1.1.1.5 root 2495: break; 1.1 root 2496: case FSR_RD_NEG: 2497: rnd_mode = float_round_down; 1.1.1.5 root 2498: break; 1.1 root 2499: } 2500: set_float_rounding_mode(rnd_mode, &env->fp_status); 2501: } 2502: 1.1.1.6 ! root 2503: void helper_ldfsr(uint32_t new_fsr) ! 2504: { ! 2505: env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK); ! 2506: set_fsr(); ! 2507: } ! 2508: ! 2509: #ifdef TARGET_SPARC64 ! 2510: void helper_ldxfsr(uint64_t new_fsr) ! 2511: { ! 2512: env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK); ! 2513: set_fsr(); ! 2514: } ! 2515: #endif ! 2516: ! 2517: void helper_debug(void) 1.1 root 2518: { 2519: env->exception_index = EXCP_DEBUG; 2520: cpu_loop_exit(); 2521: } 2522: 2523: #ifndef TARGET_SPARC64 1.1.1.6 ! root 2524: /* XXX: use another pointer for %iN registers to avoid slow wrapping ! 2525: handling ? */ ! 2526: void helper_save(void) ! 2527: { ! 2528: uint32_t cwp; ! 2529: ! 2530: cwp = cpu_cwp_dec(env, env->cwp - 1); ! 2531: if (env->wim & (1 << cwp)) { ! 2532: raise_exception(TT_WIN_OVF); ! 2533: } ! 2534: set_cwp(cwp); ! 2535: } ! 2536: ! 2537: void helper_restore(void) ! 2538: { ! 2539: uint32_t cwp; ! 2540: ! 2541: cwp = cpu_cwp_inc(env, env->cwp + 1); ! 2542: if (env->wim & (1 << cwp)) { ! 2543: raise_exception(TT_WIN_UNF); ! 2544: } ! 2545: set_cwp(cwp); ! 2546: } ! 2547: ! 2548: void helper_wrpsr(target_ulong new_psr) 1.1 root 2549: { 1.1.1.6 ! root 2550: if ((new_psr & PSR_CWP) >= env->nwindows) 1.1.1.5 root 2551: raise_exception(TT_ILL_INSN); 2552: else 1.1.1.6 ! root 2553: PUT_PSR(env, new_psr); 1.1 root 2554: } 2555: 1.1.1.6 ! root 2556: target_ulong helper_rdpsr(void) 1.1 root 2557: { 1.1.1.6 ! root 2558: return GET_PSR(env); 1.1 root 2559: } 2560: 2561: #else 1.1.1.6 ! root 2562: /* XXX: use another pointer for %iN registers to avoid slow wrapping ! 2563: handling ? */ ! 2564: void helper_save(void) ! 2565: { ! 2566: uint32_t cwp; ! 2567: ! 2568: cwp = cpu_cwp_dec(env, env->cwp - 1); ! 2569: if (env->cansave == 0) { ! 2570: raise_exception(TT_SPILL | (env->otherwin != 0 ? ! 2571: (TT_WOTHER | ((env->wstate & 0x38) >> 1)): ! 2572: ((env->wstate & 0x7) << 2))); ! 2573: } else { ! 2574: if (env->cleanwin - env->canrestore == 0) { ! 2575: // XXX Clean windows without trap ! 2576: raise_exception(TT_CLRWIN); ! 2577: } else { ! 2578: env->cansave--; ! 2579: env->canrestore++; ! 2580: set_cwp(cwp); ! 2581: } ! 2582: } ! 2583: } ! 2584: ! 2585: void helper_restore(void) ! 2586: { ! 2587: uint32_t cwp; ! 2588: ! 2589: cwp = cpu_cwp_inc(env, env->cwp + 1); ! 2590: if (env->canrestore == 0) { ! 2591: raise_exception(TT_FILL | (env->otherwin != 0 ? ! 2592: (TT_WOTHER | ((env->wstate & 0x38) >> 1)): ! 2593: ((env->wstate & 0x7) << 2))); ! 2594: } else { ! 2595: env->cansave++; ! 2596: env->canrestore--; ! 2597: set_cwp(cwp); ! 2598: } ! 2599: } ! 2600: ! 2601: void helper_flushw(void) ! 2602: { ! 2603: if (env->cansave != env->nwindows - 2) { ! 2604: raise_exception(TT_SPILL | (env->otherwin != 0 ? ! 2605: (TT_WOTHER | ((env->wstate & 0x38) >> 1)): ! 2606: ((env->wstate & 0x7) << 2))); ! 2607: } ! 2608: } ! 2609: ! 2610: void helper_saved(void) ! 2611: { ! 2612: env->cansave++; ! 2613: if (env->otherwin == 0) ! 2614: env->canrestore--; ! 2615: else ! 2616: env->otherwin--; ! 2617: } 1.1 root 2618: 1.1.1.6 ! root 2619: void helper_restored(void) 1.1 root 2620: { 1.1.1.6 ! root 2621: env->canrestore++; ! 2622: if (env->cleanwin < env->nwindows - 1) ! 2623: env->cleanwin++; ! 2624: if (env->otherwin == 0) ! 2625: env->cansave--; ! 2626: else ! 2627: env->otherwin--; ! 2628: } ! 2629: ! 2630: target_ulong helper_rdccr(void) ! 2631: { ! 2632: return GET_CCR(env); ! 2633: } ! 2634: ! 2635: void helper_wrccr(target_ulong new_ccr) ! 2636: { ! 2637: PUT_CCR(env, new_ccr); ! 2638: } ! 2639: ! 2640: // CWP handling is reversed in V9, but we still use the V8 register ! 2641: // order. ! 2642: target_ulong helper_rdcwp(void) ! 2643: { ! 2644: return GET_CWP64(env); ! 2645: } ! 2646: ! 2647: void helper_wrcwp(target_ulong new_cwp) ! 2648: { ! 2649: PUT_CWP64(env, new_cwp); ! 2650: } ! 2651: ! 2652: // This function uses non-native bit order ! 2653: #define GET_FIELD(X, FROM, TO) \ ! 2654: ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1)) ! 2655: ! 2656: // This function uses the order in the manuals, i.e. bit 0 is 2^0 ! 2657: #define GET_FIELD_SP(X, FROM, TO) \ ! 2658: GET_FIELD(X, 63 - (TO), 63 - (FROM)) ! 2659: ! 2660: target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize) ! 2661: { ! 2662: return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) | ! 2663: (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) | ! 2664: (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) | ! 2665: (GET_FIELD_SP(pixel_addr, 56, 59) << 13) | ! 2666: (GET_FIELD_SP(pixel_addr, 35, 38) << 9) | ! 2667: (GET_FIELD_SP(pixel_addr, 13, 16) << 5) | ! 2668: (((pixel_addr >> 55) & 1) << 4) | ! 2669: (GET_FIELD_SP(pixel_addr, 33, 34) << 2) | ! 2670: GET_FIELD_SP(pixel_addr, 11, 12); ! 2671: } ! 2672: ! 2673: target_ulong helper_alignaddr(target_ulong addr, target_ulong offset) ! 2674: { ! 2675: uint64_t tmp; ! 2676: ! 2677: tmp = addr + offset; ! 2678: env->gsr &= ~7ULL; ! 2679: env->gsr |= tmp & 7ULL; ! 2680: return tmp & ~7ULL; ! 2681: } ! 2682: ! 2683: target_ulong helper_popc(target_ulong val) ! 2684: { ! 2685: return ctpop64(val); 1.1 root 2686: } 2687: 2688: static inline uint64_t *get_gregset(uint64_t pstate) 2689: { 2690: switch (pstate) { 2691: default: 2692: case 0: 1.1.1.5 root 2693: return env->bgregs; 1.1 root 2694: case PS_AG: 1.1.1.5 root 2695: return env->agregs; 1.1 root 2696: case PS_MG: 1.1.1.5 root 2697: return env->mgregs; 1.1 root 2698: case PS_IG: 1.1.1.5 root 2699: return env->igregs; 1.1 root 2700: } 2701: } 2702: 1.1.1.5 root 2703: static inline void change_pstate(uint64_t new_pstate) 1.1 root 2704: { 1.1.1.5 root 2705: uint64_t pstate_regs, new_pstate_regs; 1.1 root 2706: uint64_t *src, *dst; 2707: 2708: pstate_regs = env->pstate & 0xc01; 2709: new_pstate_regs = new_pstate & 0xc01; 2710: if (new_pstate_regs != pstate_regs) { 1.1.1.5 root 2711: // Switch global register bank 2712: src = get_gregset(new_pstate_regs); 2713: dst = get_gregset(pstate_regs); 2714: memcpy32(dst, env->gregs); 2715: memcpy32(env->gregs, src); 1.1 root 2716: } 2717: env->pstate = new_pstate; 2718: } 2719: 1.1.1.6 ! root 2720: void helper_wrpstate(target_ulong new_state) 1.1.1.5 root 2721: { 1.1.1.6 ! root 2722: if (!(env->def->features & CPU_FEATURE_GL)) ! 2723: change_pstate(new_state & 0xf3f); 1.1.1.5 root 2724: } 2725: 1.1.1.6 ! root 2726: void helper_done(void) 1.1 root 2727: { 1.1.1.6 ! root 2728: env->pc = env->tsptr->tpc; ! 2729: env->npc = env->tsptr->tnpc + 4; ! 2730: PUT_CCR(env, env->tsptr->tstate >> 32); ! 2731: env->asi = (env->tsptr->tstate >> 24) & 0xff; ! 2732: change_pstate((env->tsptr->tstate >> 8) & 0xf3f); ! 2733: PUT_CWP64(env, env->tsptr->tstate & 0xff); 1.1 root 2734: env->tl--; 1.1.1.6 ! root 2735: env->tsptr = &env->ts[env->tl & MAXTL_MASK]; 1.1 root 2736: } 2737: 1.1.1.6 ! root 2738: void helper_retry(void) 1.1 root 2739: { 1.1.1.6 ! root 2740: env->pc = env->tsptr->tpc; ! 2741: env->npc = env->tsptr->tnpc; ! 2742: PUT_CCR(env, env->tsptr->tstate >> 32); ! 2743: env->asi = (env->tsptr->tstate >> 24) & 0xff; ! 2744: change_pstate((env->tsptr->tstate >> 8) & 0xf3f); ! 2745: PUT_CWP64(env, env->tsptr->tstate & 0xff); 1.1 root 2746: env->tl--; 1.1.1.6 ! root 2747: env->tsptr = &env->ts[env->tl & MAXTL_MASK]; 1.1 root 2748: } 2749: 1.1.1.6 ! root 2750: void helper_set_softint(uint64_t value) 1.1 root 2751: { 1.1.1.6 ! root 2752: env->softint |= (uint32_t)value; 1.1 root 2753: } 2754: 1.1.1.6 ! root 2755: void helper_clear_softint(uint64_t value) 1.1 root 2756: { 1.1.1.6 ! root 2757: env->softint &= (uint32_t)~value; ! 2758: } 1.1 root 2759: 1.1.1.6 ! root 2760: void helper_write_softint(uint64_t value) ! 2761: { ! 2762: env->softint = (uint32_t)value; ! 2763: } 1.1 root 2764: #endif 1.1.1.6 ! root 2765: ! 2766: void helper_flush(target_ulong addr) ! 2767: { ! 2768: addr &= ~7; ! 2769: tb_invalidate_page_range(addr, addr + 8); 1.1 root 2770: } 2771: 2772: #ifdef TARGET_SPARC64 1.1.1.5 root 2773: #ifdef DEBUG_PCALL 1.1.1.6 ! root 2774: static const char * const excp_names[0x80] = { 1.1.1.5 root 2775: [TT_TFAULT] = "Instruction Access Fault", 2776: [TT_TMISS] = "Instruction Access MMU Miss", 2777: [TT_CODE_ACCESS] = "Instruction Access Error", 2778: [TT_ILL_INSN] = "Illegal Instruction", 2779: [TT_PRIV_INSN] = "Privileged Instruction", 2780: [TT_NFPU_INSN] = "FPU Disabled", 2781: [TT_FP_EXCP] = "FPU Exception", 2782: [TT_TOVF] = "Tag Overflow", 2783: [TT_CLRWIN] = "Clean Windows", 2784: [TT_DIV_ZERO] = "Division By Zero", 2785: [TT_DFAULT] = "Data Access Fault", 2786: [TT_DMISS] = "Data Access MMU Miss", 2787: [TT_DATA_ACCESS] = "Data Access Error", 2788: [TT_DPROT] = "Data Protection Error", 2789: [TT_UNALIGNED] = "Unaligned Memory Access", 2790: [TT_PRIV_ACT] = "Privileged Action", 2791: [TT_EXTINT | 0x1] = "External Interrupt 1", 2792: [TT_EXTINT | 0x2] = "External Interrupt 2", 2793: [TT_EXTINT | 0x3] = "External Interrupt 3", 2794: [TT_EXTINT | 0x4] = "External Interrupt 4", 2795: [TT_EXTINT | 0x5] = "External Interrupt 5", 2796: [TT_EXTINT | 0x6] = "External Interrupt 6", 2797: [TT_EXTINT | 0x7] = "External Interrupt 7", 2798: [TT_EXTINT | 0x8] = "External Interrupt 8", 2799: [TT_EXTINT | 0x9] = "External Interrupt 9", 2800: [TT_EXTINT | 0xa] = "External Interrupt 10", 2801: [TT_EXTINT | 0xb] = "External Interrupt 11", 2802: [TT_EXTINT | 0xc] = "External Interrupt 12", 2803: [TT_EXTINT | 0xd] = "External Interrupt 13", 2804: [TT_EXTINT | 0xe] = "External Interrupt 14", 2805: [TT_EXTINT | 0xf] = "External Interrupt 15", 2806: }; 2807: #endif 2808: 1.1.1.6 ! root 2809: void do_interrupt(CPUState *env) 1.1 root 2810: { 1.1.1.6 ! root 2811: int intno = env->exception_index; ! 2812: 1.1 root 2813: #ifdef DEBUG_PCALL 1.1.1.6 ! root 2814: if (qemu_loglevel_mask(CPU_LOG_INT)) { 1.1.1.5 root 2815: static int count; 2816: const char *name; 2817: 1.1.1.6 ! root 2818: if (intno < 0 || intno >= 0x180) 1.1.1.5 root 2819: name = "Unknown"; 2820: else if (intno >= 0x100) 2821: name = "Trap Instruction"; 2822: else if (intno >= 0xc0) 2823: name = "Window Fill"; 2824: else if (intno >= 0x80) 2825: name = "Window Spill"; 2826: else { 2827: name = excp_names[intno]; 2828: if (!name) 2829: name = "Unknown"; 2830: } 2831: 1.1.1.6 ! root 2832: qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64 1.1.1.5 root 2833: " SP=%016" PRIx64 "\n", 2834: count, name, intno, 1.1 root 2835: env->pc, 2836: env->npc, env->regwptr[6]); 1.1.1.6 ! root 2837: log_cpu_state(env, 0); 1.1 root 2838: #if 0 1.1.1.5 root 2839: { 2840: int i; 2841: uint8_t *ptr; 2842: 1.1.1.6 ! root 2843: qemu_log(" code="); 1.1.1.5 root 2844: ptr = (uint8_t *)env->pc; 2845: for(i = 0; i < 16; i++) { 1.1.1.6 ! root 2846: qemu_log(" %02x", ldub(ptr + i)); 1.1.1.5 root 2847: } 1.1.1.6 ! root 2848: qemu_log("\n"); 1.1.1.5 root 2849: } 1.1 root 2850: #endif 1.1.1.5 root 2851: count++; 1.1 root 2852: } 2853: #endif 1.1.1.5 root 2854: #if !defined(CONFIG_USER_ONLY) 1.1.1.6 ! root 2855: if (env->tl >= env->maxtl) { ! 2856: cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d)," ! 2857: " Error state", env->exception_index, env->tl, env->maxtl); 1.1.1.5 root 2858: return; 1.1 root 2859: } 2860: #endif 1.1.1.6 ! root 2861: if (env->tl < env->maxtl - 1) { 1.1.1.5 root 2862: env->tl++; 1.1 root 2863: } else { 1.1.1.5 root 2864: env->pstate |= PS_RED; 1.1.1.6 ! root 2865: if (env->tl < env->maxtl) 1.1.1.5 root 2866: env->tl++; 1.1 root 2867: } 1.1.1.6 ! root 2868: env->tsptr = &env->ts[env->tl & MAXTL_MASK]; ! 2869: env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) | ! 2870: ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) | ! 2871: GET_CWP64(env); ! 2872: env->tsptr->tpc = env->pc; ! 2873: env->tsptr->tnpc = env->npc; ! 2874: env->tsptr->tt = intno; ! 2875: if (!(env->def->features & CPU_FEATURE_GL)) { ! 2876: switch (intno) { ! 2877: case TT_IVEC: ! 2878: change_pstate(PS_PEF | PS_PRIV | PS_IG); ! 2879: break; ! 2880: case TT_TFAULT: ! 2881: case TT_TMISS: ! 2882: case TT_DFAULT: ! 2883: case TT_DMISS: ! 2884: case TT_DPROT: ! 2885: change_pstate(PS_PEF | PS_PRIV | PS_MG); ! 2886: break; ! 2887: default: ! 2888: change_pstate(PS_PEF | PS_PRIV | PS_AG); ! 2889: break; ! 2890: } ! 2891: } ! 2892: if (intno == TT_CLRWIN) ! 2893: cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1)); ! 2894: else if ((intno & 0x1c0) == TT_SPILL) ! 2895: cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2)); ! 2896: else if ((intno & 0x1c0) == TT_FILL) ! 2897: cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1)); ! 2898: env->tbr &= ~0x7fffULL; ! 2899: env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5); 1.1 root 2900: env->pc = env->tbr; 2901: env->npc = env->pc + 4; 2902: env->exception_index = 0; 2903: } 2904: #else 1.1.1.5 root 2905: #ifdef DEBUG_PCALL 2906: static const char * const excp_names[0x80] = { 2907: [TT_TFAULT] = "Instruction Access Fault", 2908: [TT_ILL_INSN] = "Illegal Instruction", 2909: [TT_PRIV_INSN] = "Privileged Instruction", 2910: [TT_NFPU_INSN] = "FPU Disabled", 2911: [TT_WIN_OVF] = "Window Overflow", 2912: [TT_WIN_UNF] = "Window Underflow", 2913: [TT_UNALIGNED] = "Unaligned Memory Access", 2914: [TT_FP_EXCP] = "FPU Exception", 2915: [TT_DFAULT] = "Data Access Fault", 2916: [TT_TOVF] = "Tag Overflow", 2917: [TT_EXTINT | 0x1] = "External Interrupt 1", 2918: [TT_EXTINT | 0x2] = "External Interrupt 2", 2919: [TT_EXTINT | 0x3] = "External Interrupt 3", 2920: [TT_EXTINT | 0x4] = "External Interrupt 4", 2921: [TT_EXTINT | 0x5] = "External Interrupt 5", 2922: [TT_EXTINT | 0x6] = "External Interrupt 6", 2923: [TT_EXTINT | 0x7] = "External Interrupt 7", 2924: [TT_EXTINT | 0x8] = "External Interrupt 8", 2925: [TT_EXTINT | 0x9] = "External Interrupt 9", 2926: [TT_EXTINT | 0xa] = "External Interrupt 10", 2927: [TT_EXTINT | 0xb] = "External Interrupt 11", 2928: [TT_EXTINT | 0xc] = "External Interrupt 12", 2929: [TT_EXTINT | 0xd] = "External Interrupt 13", 2930: [TT_EXTINT | 0xe] = "External Interrupt 14", 2931: [TT_EXTINT | 0xf] = "External Interrupt 15", 2932: [TT_TOVF] = "Tag Overflow", 2933: [TT_CODE_ACCESS] = "Instruction Access Error", 2934: [TT_DATA_ACCESS] = "Data Access Error", 2935: [TT_DIV_ZERO] = "Division By Zero", 2936: [TT_NCP_INSN] = "Coprocessor Disabled", 2937: }; 2938: #endif 2939: 1.1.1.6 ! root 2940: void do_interrupt(CPUState *env) 1.1 root 2941: { 1.1.1.6 ! root 2942: int cwp, intno = env->exception_index; 1.1 root 2943: 2944: #ifdef DEBUG_PCALL 1.1.1.6 ! root 2945: if (qemu_loglevel_mask(CPU_LOG_INT)) { 1.1.1.5 root 2946: static int count; 2947: const char *name; 2948: 2949: if (intno < 0 || intno >= 0x100) 2950: name = "Unknown"; 2951: else if (intno >= 0x80) 2952: name = "Trap Instruction"; 2953: else { 2954: name = excp_names[intno]; 2955: if (!name) 2956: name = "Unknown"; 2957: } 2958: 1.1.1.6 ! root 2959: qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n", 1.1.1.5 root 2960: count, name, intno, 1.1 root 2961: env->pc, 2962: env->npc, env->regwptr[6]); 1.1.1.6 ! root 2963: log_cpu_state(env, 0); 1.1 root 2964: #if 0 1.1.1.5 root 2965: { 2966: int i; 2967: uint8_t *ptr; 2968: 1.1.1.6 ! root 2969: qemu_log(" code="); 1.1.1.5 root 2970: ptr = (uint8_t *)env->pc; 2971: for(i = 0; i < 16; i++) { 1.1.1.6 ! root 2972: qemu_log(" %02x", ldub(ptr + i)); 1.1.1.5 root 2973: } 1.1.1.6 ! root 2974: qemu_log("\n"); 1.1.1.5 root 2975: } 1.1 root 2976: #endif 1.1.1.5 root 2977: count++; 1.1 root 2978: } 2979: #endif 1.1.1.5 root 2980: #if !defined(CONFIG_USER_ONLY) 1.1 root 2981: if (env->psret == 0) { 1.1.1.6 ! root 2982: cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", ! 2983: env->exception_index); 1.1.1.5 root 2984: return; 1.1 root 2985: } 2986: #endif 2987: env->psret = 0; 1.1.1.6 ! root 2988: cwp = cpu_cwp_dec(env, env->cwp - 1); ! 2989: cpu_set_cwp(env, cwp); 1.1 root 2990: env->regwptr[9] = env->pc; 2991: env->regwptr[10] = env->npc; 2992: env->psrps = env->psrs; 2993: env->psrs = 1; 2994: env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4); 2995: env->pc = env->tbr; 2996: env->npc = env->pc + 4; 2997: env->exception_index = 0; 2998: } 2999: #endif 3000: 1.1.1.5 root 3001: #if !defined(CONFIG_USER_ONLY) 3002: 3003: static void do_unaligned_access(target_ulong addr, int is_write, int is_user, 3004: void *retaddr); 1.1 root 3005: 3006: #define MMUSUFFIX _mmu 1.1.1.5 root 3007: #define ALIGNED_ONLY 1.1 root 3008: 3009: #define SHIFT 0 3010: #include "softmmu_template.h" 3011: 3012: #define SHIFT 1 3013: #include "softmmu_template.h" 3014: 3015: #define SHIFT 2 3016: #include "softmmu_template.h" 3017: 3018: #define SHIFT 3 3019: #include "softmmu_template.h" 3020: 1.1.1.6 ! root 3021: /* XXX: make it generic ? */ ! 3022: static void cpu_restore_state2(void *retaddr) ! 3023: { ! 3024: TranslationBlock *tb; ! 3025: unsigned long pc; ! 3026: ! 3027: if (retaddr) { ! 3028: /* now we have a real cpu fault */ ! 3029: pc = (unsigned long)retaddr; ! 3030: tb = tb_find_pc(pc); ! 3031: if (tb) { ! 3032: /* the PC is inside the translated code. It means that we have ! 3033: a virtual CPU fault */ ! 3034: cpu_restore_state(tb, env, pc, (void *)(long)env->cond); ! 3035: } ! 3036: } ! 3037: } ! 3038: 1.1.1.5 root 3039: static void do_unaligned_access(target_ulong addr, int is_write, int is_user, 3040: void *retaddr) 3041: { 3042: #ifdef DEBUG_UNALIGNED 1.1.1.6 ! root 3043: printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx ! 3044: "\n", addr, env->pc); 1.1.1.5 root 3045: #endif 1.1.1.6 ! root 3046: cpu_restore_state2(retaddr); 1.1.1.5 root 3047: raise_exception(TT_UNALIGNED); 3048: } 1.1 root 3049: 3050: /* try to fill the TLB and return an exception if error. If retaddr is 3051: NULL, it means that the function was called in C code (i.e. not 3052: from generated code or from helper.c) */ 3053: /* XXX: fix it to restore all registers */ 1.1.1.5 root 3054: void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) 1.1 root 3055: { 3056: int ret; 3057: CPUState *saved_env; 3058: 3059: /* XXX: hack to restore env in all cases, even if not called from 3060: generated code */ 3061: saved_env = env; 3062: env = cpu_single_env; 3063: 1.1.1.5 root 3064: ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); 1.1 root 3065: if (ret) { 1.1.1.6 ! root 3066: cpu_restore_state2(retaddr); 1.1 root 3067: cpu_loop_exit(); 3068: } 3069: env = saved_env; 3070: } 3071: 3072: #endif 1.1.1.5 root 3073: 3074: #ifndef TARGET_SPARC64 3075: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, 1.1.1.6 ! root 3076: int is_asi, int size) 1.1.1.5 root 3077: { 3078: CPUState *saved_env; 3079: 3080: /* XXX: hack to restore env in all cases, even if not called from 3081: generated code */ 3082: saved_env = env; 3083: env = cpu_single_env; 3084: #ifdef DEBUG_UNASSIGNED 3085: if (is_asi) 1.1.1.6 ! root 3086: printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx ! 3087: " asi 0x%02x from " TARGET_FMT_lx "\n", ! 3088: is_exec ? "exec" : is_write ? "write" : "read", size, ! 3089: size == 1 ? "" : "s", addr, is_asi, env->pc); 1.1.1.5 root 3090: else 1.1.1.6 ! root 3091: printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx ! 3092: " from " TARGET_FMT_lx "\n", ! 3093: is_exec ? "exec" : is_write ? "write" : "read", size, ! 3094: size == 1 ? "" : "s", addr, env->pc); 1.1.1.5 root 3095: #endif 3096: if (env->mmuregs[3]) /* Fault status register */ 3097: env->mmuregs[3] = 1; /* overflow (not read before another fault) */ 3098: if (is_asi) 3099: env->mmuregs[3] |= 1 << 16; 3100: if (env->psrs) 3101: env->mmuregs[3] |= 1 << 5; 3102: if (is_exec) 3103: env->mmuregs[3] |= 1 << 6; 3104: if (is_write) 3105: env->mmuregs[3] |= 1 << 7; 3106: env->mmuregs[3] |= (5 << 2) | 2; 3107: env->mmuregs[4] = addr; /* Fault address register */ 3108: if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) { 3109: if (is_exec) 3110: raise_exception(TT_CODE_ACCESS); 3111: else 3112: raise_exception(TT_DATA_ACCESS); 3113: } 3114: env = saved_env; 3115: } 3116: #else 3117: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, 1.1.1.6 ! root 3118: int is_asi, int size) 1.1.1.5 root 3119: { 3120: #ifdef DEBUG_UNASSIGNED 3121: CPUState *saved_env; 3122: 3123: /* XXX: hack to restore env in all cases, even if not called from 3124: generated code */ 3125: saved_env = env; 3126: env = cpu_single_env; 1.1.1.6 ! root 3127: printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx ! 3128: "\n", addr, env->pc); 1.1.1.5 root 3129: env = saved_env; 3130: #endif 3131: if (is_exec) 3132: raise_exception(TT_CODE_ACCESS); 3133: else 3134: raise_exception(TT_DATA_ACCESS); 3135: } 3136: #endif 3137: 1.1.1.6 ! root 3138: #ifdef TARGET_SPARC64 ! 3139: void helper_tick_set_count(void *opaque, uint64_t count) ! 3140: { ! 3141: #if !defined(CONFIG_USER_ONLY) ! 3142: cpu_tick_set_count(opaque, count); ! 3143: #endif ! 3144: } ! 3145: ! 3146: uint64_t helper_tick_get_count(void *opaque) ! 3147: { ! 3148: #if !defined(CONFIG_USER_ONLY) ! 3149: return cpu_tick_get_count(opaque); ! 3150: #else ! 3151: return 0; ! 3152: #endif ! 3153: } ! 3154: ! 3155: void helper_tick_set_limit(void *opaque, uint64_t limit) ! 3156: { ! 3157: #if !defined(CONFIG_USER_ONLY) ! 3158: cpu_tick_set_limit(opaque, limit); ! 3159: #endif ! 3160: } ! 3161: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.