|
|
1.1 root 1: #include "exec.h" 1.1.1.5 ! root 2: #include "host-utils.h" 1.1 root 3: 4: //#define DEBUG_PCALL 5: //#define DEBUG_MMU 1.1.1.5 ! root 6: //#define DEBUG_MXCC ! 7: //#define DEBUG_UNALIGNED ! 8: //#define DEBUG_UNASSIGNED ! 9: //#define DEBUG_ASI ! 10: ! 11: #ifdef DEBUG_MMU ! 12: #define DPRINTF_MMU(fmt, args...) \ ! 13: do { printf("MMU: " fmt , ##args); } while (0) ! 14: #else ! 15: #define DPRINTF_MMU(fmt, args...) ! 16: #endif ! 17: ! 18: #ifdef DEBUG_MXCC ! 19: #define DPRINTF_MXCC(fmt, args...) \ ! 20: do { printf("MXCC: " fmt , ##args); } while (0) ! 21: #else ! 22: #define DPRINTF_MXCC(fmt, args...) ! 23: #endif ! 24: ! 25: #ifdef DEBUG_ASI ! 26: #define DPRINTF_ASI(fmt, args...) \ ! 27: do { printf("ASI: " fmt , ##args); } while (0) ! 28: #else ! 29: #define DPRINTF_ASI(fmt, args...) ! 30: #endif 1.1 root 31: 32: void raise_exception(int tt) 33: { 34: env->exception_index = tt; 35: cpu_loop_exit(); 1.1.1.5 ! root 36: } ! 37: ! 38: void check_ieee_exceptions() ! 39: { ! 40: T0 = get_float_exception_flags(&env->fp_status); ! 41: if (T0) ! 42: { ! 43: /* Copy IEEE 754 flags into FSR */ ! 44: if (T0 & float_flag_invalid) ! 45: env->fsr |= FSR_NVC; ! 46: if (T0 & float_flag_overflow) ! 47: env->fsr |= FSR_OFC; ! 48: if (T0 & float_flag_underflow) ! 49: env->fsr |= FSR_UFC; ! 50: if (T0 & float_flag_divbyzero) ! 51: env->fsr |= FSR_DZC; ! 52: if (T0 & float_flag_inexact) ! 53: env->fsr |= FSR_NXC; ! 54: ! 55: if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) ! 56: { ! 57: /* Unmasked exception, generate a trap */ ! 58: env->fsr |= FSR_FTT_IEEE_EXCP; ! 59: raise_exception(TT_FP_EXCP); ! 60: } ! 61: else ! 62: { ! 63: /* Accumulate exceptions */ ! 64: env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5; ! 65: } ! 66: } ! 67: } 1.1 root 68: 69: #ifdef USE_INT_TO_FLOAT_HELPERS 70: void do_fitos(void) 71: { 1.1.1.5 ! root 72: set_float_exception_flags(0, &env->fp_status); 1.1.1.4 root 73: FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status); 1.1.1.5 ! root 74: check_ieee_exceptions(); 1.1 root 75: } 76: 77: void do_fitod(void) 78: { 1.1.1.4 root 79: DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status); 1.1 root 80: } 1.1.1.5 ! root 81: ! 82: #if defined(CONFIG_USER_ONLY) ! 83: void do_fitoq(void) ! 84: { ! 85: QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status); ! 86: } ! 87: #endif ! 88: ! 89: #ifdef TARGET_SPARC64 ! 90: void do_fxtos(void) ! 91: { ! 92: set_float_exception_flags(0, &env->fp_status); ! 93: FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status); ! 94: check_ieee_exceptions(); ! 95: } ! 96: ! 97: void do_fxtod(void) ! 98: { ! 99: set_float_exception_flags(0, &env->fp_status); ! 100: DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status); ! 101: check_ieee_exceptions(); ! 102: } ! 103: ! 104: #if defined(CONFIG_USER_ONLY) ! 105: void do_fxtoq(void) ! 106: { ! 107: set_float_exception_flags(0, &env->fp_status); ! 108: QT0 = int64_to_float128(*((int32_t *)&DT1), &env->fp_status); ! 109: check_ieee_exceptions(); ! 110: } ! 111: #endif ! 112: #endif 1.1 root 113: #endif 114: 115: void do_fabss(void) 116: { 117: FT0 = float32_abs(FT1); 118: } 119: 120: #ifdef TARGET_SPARC64 121: void do_fabsd(void) 122: { 123: DT0 = float64_abs(DT1); 124: } 1.1.1.5 ! root 125: ! 126: #if defined(CONFIG_USER_ONLY) ! 127: void do_fabsq(void) ! 128: { ! 129: QT0 = float128_abs(QT1); ! 130: } ! 131: #endif 1.1 root 132: #endif 133: 134: void do_fsqrts(void) 135: { 1.1.1.5 ! root 136: set_float_exception_flags(0, &env->fp_status); 1.1 root 137: FT0 = float32_sqrt(FT1, &env->fp_status); 1.1.1.5 ! root 138: check_ieee_exceptions(); 1.1 root 139: } 140: 141: void do_fsqrtd(void) 142: { 1.1.1.5 ! root 143: set_float_exception_flags(0, &env->fp_status); 1.1 root 144: DT0 = float64_sqrt(DT1, &env->fp_status); 1.1.1.5 ! root 145: check_ieee_exceptions(); 1.1 root 146: } 147: 1.1.1.5 ! root 148: #if defined(CONFIG_USER_ONLY) ! 149: void do_fsqrtq(void) ! 150: { ! 151: set_float_exception_flags(0, &env->fp_status); ! 152: QT0 = float128_sqrt(QT1, &env->fp_status); ! 153: check_ieee_exceptions(); ! 154: } ! 155: #endif ! 156: ! 157: #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \ 1.1.1.3 root 158: void glue(do_, name) (void) \ 159: { \ 160: env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ 161: switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \ 162: case float_relation_unordered: \ 163: T0 = (FSR_FCC1 | FSR_FCC0) << FS; \ 1.1.1.5 ! root 164: if ((env->fsr & FSR_NVM) || TRAP) { \ 1.1.1.3 root 165: env->fsr |= T0; \ 1.1.1.5 ! root 166: env->fsr |= FSR_NVC; \ ! 167: env->fsr |= FSR_FTT_IEEE_EXCP; \ 1.1.1.3 root 168: raise_exception(TT_FP_EXCP); \ 169: } else { \ 170: env->fsr |= FSR_NVA; \ 171: } \ 172: break; \ 173: case float_relation_less: \ 174: T0 = FSR_FCC0 << FS; \ 175: break; \ 176: case float_relation_greater: \ 177: T0 = FSR_FCC1 << FS; \ 178: break; \ 179: default: \ 180: T0 = 0; \ 181: break; \ 182: } \ 183: env->fsr |= T0; \ 1.1 root 184: } 185: 1.1.1.5 ! root 186: GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0); ! 187: GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0); ! 188: ! 189: GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1); ! 190: GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1); ! 191: ! 192: #ifdef CONFIG_USER_ONLY ! 193: GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0); ! 194: GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1); ! 195: #endif 1.1 root 196: 197: #ifdef TARGET_SPARC64 1.1.1.5 ! root 198: GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0); ! 199: GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0); 1.1 root 200: 1.1.1.5 ! root 201: GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0); ! 202: GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0); 1.1 root 203: 1.1.1.5 ! root 204: GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0); ! 205: GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0); ! 206: ! 207: GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1); ! 208: GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1); ! 209: ! 210: GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1); ! 211: GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1); ! 212: ! 213: GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1); ! 214: GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1); ! 215: #ifdef CONFIG_USER_ONLY ! 216: GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0); ! 217: GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0); ! 218: GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0); ! 219: GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1); ! 220: GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1); ! 221: GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1); ! 222: #endif 1.1 root 223: #endif 224: 1.1.1.5 ! root 225: #ifndef TARGET_SPARC64 ! 226: #ifndef CONFIG_USER_ONLY ! 227: ! 228: #ifdef DEBUG_MXCC ! 229: static void dump_mxcc(CPUState *env) 1.1.1.2 root 230: { 1.1.1.5 ! root 231: printf("mxccdata: %016llx %016llx %016llx %016llx\n", ! 232: env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]); ! 233: printf("mxccregs: %016llx %016llx %016llx %016llx\n" ! 234: " %016llx %016llx %016llx %016llx\n", ! 235: env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3], ! 236: env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]); 1.1.1.2 root 237: } 1.1.1.5 ! root 238: #endif 1.1.1.2 root 239: 1.1.1.5 ! root 240: #ifdef DEBUG_ASI ! 241: static void dump_asi(const char * txt, uint32_t addr, int asi, int size, ! 242: uint32_t r1, uint32_t r2) ! 243: { ! 244: switch (size) ! 245: { ! 246: case 1: ! 247: DPRINTF_ASI("%s %08x asi 0x%02x = %02x\n", txt, addr, asi, r1 & 0xff); ! 248: break; ! 249: case 2: ! 250: DPRINTF_ASI("%s %08x asi 0x%02x = %04x\n", txt, addr, asi, r1 & 0xffff); ! 251: break; ! 252: case 4: ! 253: DPRINTF_ASI("%s %08x asi 0x%02x = %08x\n", txt, addr, asi, r1); ! 254: break; ! 255: case 8: ! 256: DPRINTF_ASI("%s %08x asi 0x%02x = %016llx\n", txt, addr, asi, ! 257: r2 | ((uint64_t)r1 << 32)); ! 258: break; ! 259: } 1.1.1.2 root 260: } 1.1.1.5 ! root 261: #endif ! 262: 1.1 root 263: void helper_ld_asi(int asi, int size, int sign) 264: { 265: uint32_t ret = 0; 1.1.1.5 ! root 266: uint64_t tmp; ! 267: #if defined(DEBUG_MXCC) || defined(DEBUG_ASI) ! 268: uint32_t last_T0 = T0; ! 269: #endif 1.1 root 270: 271: switch (asi) { 1.1.1.5 ! root 272: case 2: /* SuperSparc MXCC registers */ ! 273: switch (T0) { ! 274: case 0x01c00a00: /* MXCC control register */ ! 275: if (size == 8) { ! 276: ret = env->mxccregs[3] >> 32; ! 277: T0 = env->mxccregs[3]; ! 278: } else ! 279: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); ! 280: break; ! 281: case 0x01c00a04: /* MXCC control register */ ! 282: if (size == 4) ! 283: ret = env->mxccregs[3]; ! 284: else ! 285: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); ! 286: break; ! 287: case 0x01c00c00: /* Module reset register */ ! 288: if (size == 8) { ! 289: ret = env->mxccregs[5] >> 32; ! 290: T0 = env->mxccregs[5]; ! 291: // should we do something here? ! 292: } else ! 293: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); ! 294: break; ! 295: case 0x01c00f00: /* MBus port address register */ ! 296: if (size == 8) { ! 297: ret = env->mxccregs[7] >> 32; ! 298: T0 = env->mxccregs[7]; ! 299: } else ! 300: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); ! 301: break; ! 302: default: ! 303: DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size); ! 304: break; ! 305: } ! 306: DPRINTF_MXCC("asi = %d, size = %d, sign = %d, T0 = %08x -> ret = %08x," ! 307: "T0 = %08x\n", asi, size, sign, last_T0, ret, T0); ! 308: #ifdef DEBUG_MXCC ! 309: dump_mxcc(env); ! 310: #endif ! 311: break; 1.1 root 312: case 3: /* MMU probe */ 1.1.1.5 ! root 313: { ! 314: int mmulev; 1.1 root 315: 1.1.1.5 ! root 316: mmulev = (T0 >> 8) & 15; ! 317: if (mmulev > 4) ! 318: ret = 0; ! 319: else { ! 320: ret = mmu_probe(env, T0, mmulev); ! 321: //bswap32s(&ret); ! 322: } ! 323: DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret); ! 324: } ! 325: break; 1.1 root 326: case 4: /* read MMU regs */ 1.1.1.5 ! root 327: { ! 328: int reg = (T0 >> 8) & 0x1f; ! 329: ! 330: ret = env->mmuregs[reg]; ! 331: if (reg == 3) /* Fault status cleared on read */ ! 332: env->mmuregs[3] = 0; ! 333: else if (reg == 0x13) /* Fault status read */ ! 334: ret = env->mmuregs[3]; ! 335: else if (reg == 0x14) /* Fault address read */ ! 336: ret = env->mmuregs[4]; ! 337: DPRINTF_MMU("mmu_read: reg[%d] = 0x%08x\n", reg, ret); ! 338: } ! 339: break; ! 340: case 5: // Turbosparc ITLB Diagnostic ! 341: case 6: // Turbosparc DTLB Diagnostic ! 342: case 7: // Turbosparc IOTLB Diagnostic ! 343: break; ! 344: case 9: /* Supervisor code access */ ! 345: switch(size) { ! 346: case 1: ! 347: ret = ldub_code(T0); ! 348: break; ! 349: case 2: ! 350: ret = lduw_code(T0 & ~1); ! 351: break; ! 352: default: ! 353: case 4: ! 354: ret = ldl_code(T0 & ~3); ! 355: break; ! 356: case 8: ! 357: tmp = ldq_code(T0 & ~7); ! 358: ret = tmp >> 32; ! 359: T0 = tmp; ! 360: break; ! 361: } ! 362: break; ! 363: case 0xa: /* User data access */ ! 364: switch(size) { ! 365: case 1: ! 366: ret = ldub_user(T0); ! 367: break; ! 368: case 2: ! 369: ret = lduw_user(T0 & ~1); ! 370: break; ! 371: default: ! 372: case 4: ! 373: ret = ldl_user(T0 & ~3); ! 374: break; ! 375: case 8: ! 376: tmp = ldq_user(T0 & ~7); ! 377: ret = tmp >> 32; ! 378: T0 = tmp; ! 379: break; ! 380: } ! 381: break; ! 382: case 0xb: /* Supervisor data access */ ! 383: switch(size) { ! 384: case 1: ! 385: ret = ldub_kernel(T0); ! 386: break; ! 387: case 2: ! 388: ret = lduw_kernel(T0 & ~1); ! 389: break; ! 390: default: ! 391: case 4: ! 392: ret = ldl_kernel(T0 & ~3); ! 393: break; ! 394: case 8: ! 395: tmp = ldq_kernel(T0 & ~7); ! 396: ret = tmp >> 32; ! 397: T0 = tmp; ! 398: break; ! 399: } ! 400: break; ! 401: case 0xc: /* I-cache tag */ ! 402: case 0xd: /* I-cache data */ ! 403: case 0xe: /* D-cache tag */ ! 404: case 0xf: /* D-cache data */ ! 405: break; ! 406: case 0x20: /* MMU passthrough */ 1.1.1.2 root 407: switch(size) { 408: case 1: 409: ret = ldub_phys(T0); 410: break; 411: case 2: 412: ret = lduw_phys(T0 & ~1); 413: break; 414: default: 415: case 4: 416: ret = ldl_phys(T0 & ~3); 417: break; 418: case 8: 1.1.1.5 ! root 419: tmp = ldq_phys(T0 & ~7); ! 420: ret = tmp >> 32; ! 421: T0 = tmp; ! 422: break; 1.1.1.2 root 423: } 1.1.1.5 ! root 424: break; ! 425: case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */ ! 426: switch(size) { ! 427: case 1: ! 428: ret = ldub_phys((target_phys_addr_t)T0 ! 429: | ((target_phys_addr_t)(asi & 0xf) << 32)); ! 430: break; ! 431: case 2: ! 432: ret = lduw_phys((target_phys_addr_t)(T0 & ~1) ! 433: | ((target_phys_addr_t)(asi & 0xf) << 32)); ! 434: break; ! 435: default: ! 436: case 4: ! 437: ret = ldl_phys((target_phys_addr_t)(T0 & ~3) ! 438: | ((target_phys_addr_t)(asi & 0xf) << 32)); ! 439: break; ! 440: case 8: ! 441: tmp = ldq_phys((target_phys_addr_t)(T0 & ~7) ! 442: | ((target_phys_addr_t)(asi & 0xf) << 32)); ! 443: ret = tmp >> 32; ! 444: T0 = tmp; ! 445: break; ! 446: } ! 447: break; ! 448: case 0x30: // Turbosparc secondary cache diagnostic ! 449: case 0x31: // Turbosparc RAM snoop ! 450: case 0x32: // Turbosparc page table descriptor diagnostic ! 451: case 0x39: /* data cache diagnostic register */ ! 452: ret = 0; ! 453: break; ! 454: case 8: /* User code access, XXX */ 1.1 root 455: default: 1.1.1.5 ! root 456: do_unassigned_access(T0, 0, 0, asi); ! 457: ret = 0; ! 458: break; 1.1 root 459: } 1.1.1.5 ! root 460: if (sign) { ! 461: switch(size) { ! 462: case 1: ! 463: T1 = (int8_t) ret; ! 464: break; ! 465: case 2: ! 466: T1 = (int16_t) ret; ! 467: break; ! 468: default: ! 469: T1 = ret; ! 470: break; ! 471: } ! 472: } ! 473: else ! 474: T1 = ret; ! 475: #ifdef DEBUG_ASI ! 476: dump_asi("read ", last_T0, asi, size, T1, T0); ! 477: #endif 1.1 root 478: } 479: 1.1.1.5 ! root 480: void helper_st_asi(int asi, int size) 1.1 root 481: { 482: switch(asi) { 1.1.1.5 ! root 483: case 2: /* SuperSparc MXCC registers */ ! 484: switch (T0) { ! 485: case 0x01c00000: /* MXCC stream data register 0 */ ! 486: if (size == 8) ! 487: env->mxccdata[0] = ((uint64_t)T1 << 32) | T2; ! 488: else ! 489: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); ! 490: break; ! 491: case 0x01c00008: /* MXCC stream data register 1 */ ! 492: if (size == 8) ! 493: env->mxccdata[1] = ((uint64_t)T1 << 32) | T2; ! 494: else ! 495: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); ! 496: break; ! 497: case 0x01c00010: /* MXCC stream data register 2 */ ! 498: if (size == 8) ! 499: env->mxccdata[2] = ((uint64_t)T1 << 32) | T2; ! 500: else ! 501: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); ! 502: break; ! 503: case 0x01c00018: /* MXCC stream data register 3 */ ! 504: if (size == 8) ! 505: env->mxccdata[3] = ((uint64_t)T1 << 32) | T2; ! 506: else ! 507: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); ! 508: break; ! 509: case 0x01c00100: /* MXCC stream source */ ! 510: if (size == 8) ! 511: env->mxccregs[0] = ((uint64_t)T1 << 32) | T2; ! 512: else ! 513: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); ! 514: env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 0); ! 515: env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 8); ! 516: env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16); ! 517: env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24); ! 518: break; ! 519: case 0x01c00200: /* MXCC stream destination */ ! 520: if (size == 8) ! 521: env->mxccregs[1] = ((uint64_t)T1 << 32) | T2; ! 522: else ! 523: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); ! 524: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0, env->mxccdata[0]); ! 525: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8, env->mxccdata[1]); ! 526: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]); ! 527: stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]); ! 528: break; ! 529: case 0x01c00a00: /* MXCC control register */ ! 530: if (size == 8) ! 531: env->mxccregs[3] = ((uint64_t)T1 << 32) | T2; ! 532: else ! 533: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); ! 534: break; ! 535: case 0x01c00a04: /* MXCC control register */ ! 536: if (size == 4) ! 537: env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | T1; ! 538: else ! 539: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); ! 540: break; ! 541: case 0x01c00e00: /* MXCC error register */ ! 542: // writing a 1 bit clears the error ! 543: if (size == 8) ! 544: env->mxccregs[6] &= ~(((uint64_t)T1 << 32) | T2); ! 545: else ! 546: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); ! 547: break; ! 548: case 0x01c00f00: /* MBus port address register */ ! 549: if (size == 8) ! 550: env->mxccregs[7] = ((uint64_t)T1 << 32) | T2; ! 551: else ! 552: DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); ! 553: break; ! 554: default: ! 555: DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size); ! 556: break; ! 557: } ! 558: DPRINTF_MXCC("asi = %d, size = %d, T0 = %08x, T1 = %08x\n", asi, size, T0, T1); ! 559: #ifdef DEBUG_MXCC ! 560: dump_mxcc(env); ! 561: #endif ! 562: break; 1.1 root 563: case 3: /* MMU flush */ 1.1.1.5 ! root 564: { ! 565: int mmulev; 1.1 root 566: 1.1.1.5 ! root 567: mmulev = (T0 >> 8) & 15; ! 568: DPRINTF_MMU("mmu flush level %d\n", mmulev); ! 569: switch (mmulev) { ! 570: case 0: // flush page ! 571: tlb_flush_page(env, T0 & 0xfffff000); ! 572: break; ! 573: case 1: // flush segment (256k) ! 574: case 2: // flush region (16M) ! 575: case 3: // flush context (4G) ! 576: case 4: // flush entire ! 577: tlb_flush(env, 1); ! 578: break; ! 579: default: ! 580: break; ! 581: } 1.1 root 582: #ifdef DEBUG_MMU 1.1.1.5 ! root 583: dump_mmu(env); 1.1 root 584: #endif 1.1.1.5 ! root 585: } ! 586: break; 1.1 root 587: case 4: /* write MMU regs */ 1.1.1.5 ! root 588: { ! 589: int reg = (T0 >> 8) & 0x1f; ! 590: uint32_t oldreg; ! 591: ! 592: oldreg = env->mmuregs[reg]; 1.1 root 593: switch(reg) { 594: case 0: 1.1.1.5 ! root 595: env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) | ! 596: (T1 & 0x00ffffff); ! 597: // Mappings generated during no-fault mode or MMU ! 598: // disabled mode are invalid in normal mode ! 599: if ((oldreg & (MMU_E | MMU_NF | env->mmu_bm)) != ! 600: (env->mmuregs[reg] & (MMU_E | MMU_NF | env->mmu_bm))) 1.1 root 601: tlb_flush(env, 1); 602: break; 603: case 2: 1.1.1.5 ! root 604: env->mmuregs[reg] = T1; 1.1 root 605: if (oldreg != env->mmuregs[reg]) { 606: /* we flush when the MMU context changes because 607: QEMU has no MMU context support */ 608: tlb_flush(env, 1); 609: } 610: break; 611: case 3: 612: case 4: 613: break; 1.1.1.5 ! root 614: case 0x13: ! 615: env->mmuregs[3] = T1; ! 616: break; ! 617: case 0x14: ! 618: env->mmuregs[4] = T1; ! 619: break; 1.1 root 620: default: 1.1.1.5 ! root 621: env->mmuregs[reg] = T1; 1.1 root 622: break; 623: } 624: if (oldreg != env->mmuregs[reg]) { 1.1.1.5 ! root 625: DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]); 1.1 root 626: } 1.1.1.5 ! root 627: #ifdef DEBUG_MMU ! 628: dump_mmu(env); 1.1 root 629: #endif 1.1.1.5 ! root 630: } ! 631: break; ! 632: case 5: // Turbosparc ITLB Diagnostic ! 633: case 6: // Turbosparc DTLB Diagnostic ! 634: case 7: // Turbosparc IOTLB Diagnostic ! 635: break; ! 636: case 0xa: /* User data access */ ! 637: switch(size) { ! 638: case 1: ! 639: stb_user(T0, T1); ! 640: break; ! 641: case 2: ! 642: stw_user(T0 & ~1, T1); ! 643: break; ! 644: default: ! 645: case 4: ! 646: stl_user(T0 & ~3, T1); ! 647: break; ! 648: case 8: ! 649: stq_user(T0 & ~7, ((uint64_t)T1 << 32) | T2); ! 650: break; ! 651: } ! 652: break; ! 653: case 0xb: /* Supervisor data access */ ! 654: switch(size) { ! 655: case 1: ! 656: stb_kernel(T0, T1); ! 657: break; ! 658: case 2: ! 659: stw_kernel(T0 & ~1, T1); ! 660: break; ! 661: default: ! 662: case 4: ! 663: stl_kernel(T0 & ~3, T1); ! 664: break; ! 665: case 8: ! 666: stq_kernel(T0 & ~7, ((uint64_t)T1 << 32) | T2); ! 667: break; ! 668: } ! 669: break; ! 670: case 0xc: /* I-cache tag */ ! 671: case 0xd: /* I-cache data */ ! 672: case 0xe: /* D-cache tag */ ! 673: case 0xf: /* D-cache data */ ! 674: case 0x10: /* I/D-cache flush page */ ! 675: case 0x11: /* I/D-cache flush segment */ ! 676: case 0x12: /* I/D-cache flush region */ ! 677: case 0x13: /* I/D-cache flush context */ ! 678: case 0x14: /* I/D-cache flush user */ ! 679: break; 1.1 root 680: case 0x17: /* Block copy, sta access */ 1.1.1.5 ! root 681: { ! 682: // value (T1) = src ! 683: // address (T0) = dst ! 684: // copy 32 bytes ! 685: unsigned int i; ! 686: uint32_t src = T1 & ~3, dst = T0 & ~3, temp; ! 687: ! 688: for (i = 0; i < 32; i += 4, src += 4, dst += 4) { ! 689: temp = ldl_kernel(src); ! 690: stl_kernel(dst, temp); ! 691: } ! 692: } ! 693: break; 1.1 root 694: case 0x1f: /* Block fill, stda access */ 1.1.1.5 ! root 695: { ! 696: // value (T1, T2) ! 697: // address (T0) = dst ! 698: // fill 32 bytes ! 699: unsigned int i; ! 700: uint32_t dst = T0 & 7; ! 701: uint64_t val; ! 702: ! 703: val = (((uint64_t)T1) << 32) | T2; ! 704: ! 705: for (i = 0; i < 32; i += 8, dst += 8) ! 706: stq_kernel(dst, val); ! 707: } ! 708: break; ! 709: case 0x20: /* MMU passthrough */ ! 710: { ! 711: switch(size) { ! 712: case 1: ! 713: stb_phys(T0, T1); ! 714: break; ! 715: case 2: ! 716: stw_phys(T0 & ~1, T1); ! 717: break; ! 718: case 4: ! 719: default: ! 720: stl_phys(T0 & ~3, T1); ! 721: break; ! 722: case 8: ! 723: stq_phys(T0 & ~7, ((uint64_t)T1 << 32) | T2); ! 724: break; ! 725: } ! 726: } ! 727: break; ! 728: case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */ ! 729: { ! 730: switch(size) { ! 731: case 1: ! 732: stb_phys((target_phys_addr_t)T0 ! 733: | ((target_phys_addr_t)(asi & 0xf) << 32), T1); ! 734: break; ! 735: case 2: ! 736: stw_phys((target_phys_addr_t)(T0 & ~1) ! 737: | ((target_phys_addr_t)(asi & 0xf) << 32), T1); ! 738: break; ! 739: case 4: ! 740: default: ! 741: stl_phys((target_phys_addr_t)(T0 & ~3) ! 742: | ((target_phys_addr_t)(asi & 0xf) << 32), T1); ! 743: break; ! 744: case 8: ! 745: stq_phys((target_phys_addr_t)(T0 & ~7) ! 746: | ((target_phys_addr_t)(asi & 0xf) << 32), ! 747: ((uint64_t)T1 << 32) | T2); ! 748: break; ! 749: } ! 750: } ! 751: break; ! 752: case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic ! 753: case 0x31: // store buffer data, Ross RT620 I-cache flush or ! 754: // Turbosparc snoop RAM ! 755: case 0x32: // store buffer control or Turbosparc page table descriptor diagnostic ! 756: case 0x36: /* I-cache flash clear */ ! 757: case 0x37: /* D-cache flash clear */ ! 758: case 0x38: /* breakpoint diagnostics */ ! 759: case 0x4c: /* breakpoint action */ ! 760: break; ! 761: case 8: /* User code access, XXX */ ! 762: case 9: /* Supervisor code access, XXX */ ! 763: default: ! 764: do_unassigned_access(T0, 1, 0, asi); ! 765: break; ! 766: } ! 767: #ifdef DEBUG_ASI ! 768: dump_asi("write", T0, asi, size, T1, T2); ! 769: #endif ! 770: } ! 771: ! 772: #endif /* CONFIG_USER_ONLY */ ! 773: #else /* TARGET_SPARC64 */ ! 774: ! 775: #ifdef CONFIG_USER_ONLY ! 776: void helper_ld_asi(int asi, int size, int sign) ! 777: { ! 778: uint64_t ret = 0; ! 779: ! 780: if (asi < 0x80) ! 781: raise_exception(TT_PRIV_ACT); ! 782: ! 783: switch (asi) { ! 784: case 0x80: // Primary ! 785: case 0x82: // Primary no-fault ! 786: case 0x88: // Primary LE ! 787: case 0x8a: // Primary no-fault LE ! 788: { ! 789: switch(size) { ! 790: case 1: ! 791: ret = ldub_raw(T0); ! 792: break; ! 793: case 2: ! 794: ret = lduw_raw(T0 & ~1); ! 795: break; ! 796: case 4: ! 797: ret = ldl_raw(T0 & ~3); ! 798: break; ! 799: default: ! 800: case 8: ! 801: ret = ldq_raw(T0 & ~7); ! 802: break; ! 803: } ! 804: } ! 805: break; ! 806: case 0x81: // Secondary ! 807: case 0x83: // Secondary no-fault ! 808: case 0x89: // Secondary LE ! 809: case 0x8b: // Secondary no-fault LE ! 810: // XXX ! 811: break; ! 812: default: ! 813: break; ! 814: } ! 815: ! 816: /* Convert from little endian */ ! 817: switch (asi) { ! 818: case 0x88: // Primary LE ! 819: case 0x89: // Secondary LE ! 820: case 0x8a: // Primary no-fault LE ! 821: case 0x8b: // Secondary no-fault LE ! 822: switch(size) { ! 823: case 2: ! 824: ret = bswap16(ret); ! 825: break; ! 826: case 4: ! 827: ret = bswap32(ret); ! 828: break; ! 829: case 8: ! 830: ret = bswap64(ret); ! 831: break; ! 832: default: ! 833: break; ! 834: } ! 835: default: ! 836: break; ! 837: } ! 838: ! 839: /* Convert to signed number */ ! 840: if (sign) { ! 841: switch(size) { ! 842: case 1: ! 843: ret = (int8_t) ret; ! 844: break; ! 845: case 2: ! 846: ret = (int16_t) ret; ! 847: break; ! 848: case 4: ! 849: ret = (int32_t) ret; ! 850: break; ! 851: default: ! 852: break; ! 853: } ! 854: } ! 855: T1 = ret; ! 856: } ! 857: ! 858: void helper_st_asi(int asi, int size) ! 859: { ! 860: if (asi < 0x80) ! 861: raise_exception(TT_PRIV_ACT); ! 862: ! 863: /* Convert to little endian */ ! 864: switch (asi) { ! 865: case 0x88: // Primary LE ! 866: case 0x89: // Secondary LE ! 867: switch(size) { ! 868: case 2: ! 869: T0 = bswap16(T0); ! 870: break; ! 871: case 4: ! 872: T0 = bswap32(T0); ! 873: break; ! 874: case 8: ! 875: T0 = bswap64(T0); ! 876: break; ! 877: default: ! 878: break; ! 879: } ! 880: default: ! 881: break; ! 882: } ! 883: ! 884: switch(asi) { ! 885: case 0x80: // Primary ! 886: case 0x88: // Primary LE ! 887: { 1.1.1.2 root 888: switch(size) { 889: case 1: 1.1.1.5 ! root 890: stb_raw(T0, T1); 1.1.1.2 root 891: break; 892: case 2: 1.1.1.5 ! root 893: stw_raw(T0 & ~1, T1); 1.1.1.2 root 894: break; 895: case 4: 1.1.1.5 ! root 896: stl_raw(T0 & ~3, T1); 1.1.1.2 root 897: break; 898: case 8: 1.1.1.5 ! root 899: default: ! 900: stq_raw(T0 & ~7, T1); 1.1.1.2 root 901: break; 902: } 1.1.1.5 ! root 903: } ! 904: break; ! 905: case 0x81: // Secondary ! 906: case 0x89: // Secondary LE ! 907: // XXX ! 908: return; ! 909: ! 910: case 0x82: // Primary no-fault, RO ! 911: case 0x83: // Secondary no-fault, RO ! 912: case 0x8a: // Primary no-fault LE, RO ! 913: case 0x8b: // Secondary no-fault LE, RO 1.1 root 914: default: 1.1.1.5 ! root 915: do_unassigned_access(T0, 1, 0, 1); ! 916: return; 1.1 root 917: } 918: } 919: 1.1.1.5 ! root 920: #else /* CONFIG_USER_ONLY */ 1.1 root 921: 922: void helper_ld_asi(int asi, int size, int sign) 923: { 924: uint64_t ret = 0; 925: 1.1.1.5 ! root 926: if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) ! 927: || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) ! 928: raise_exception(TT_PRIV_ACT); 1.1 root 929: 930: switch (asi) { 1.1.1.5 ! root 931: case 0x10: // As if user primary ! 932: case 0x18: // As if user primary LE ! 933: case 0x80: // Primary ! 934: case 0x82: // Primary no-fault ! 935: case 0x88: // Primary LE ! 936: case 0x8a: // Primary no-fault LE ! 937: if ((asi & 0x80) && (env->pstate & PS_PRIV)) { ! 938: if (env->hpstate & HS_PRIV) { ! 939: switch(size) { ! 940: case 1: ! 941: ret = ldub_hypv(T0); ! 942: break; ! 943: case 2: ! 944: ret = lduw_hypv(T0 & ~1); ! 945: break; ! 946: case 4: ! 947: ret = ldl_hypv(T0 & ~3); ! 948: break; ! 949: default: ! 950: case 8: ! 951: ret = ldq_hypv(T0 & ~7); ! 952: break; ! 953: } ! 954: } else { ! 955: switch(size) { ! 956: case 1: ! 957: ret = ldub_kernel(T0); ! 958: break; ! 959: case 2: ! 960: ret = lduw_kernel(T0 & ~1); ! 961: break; ! 962: case 4: ! 963: ret = ldl_kernel(T0 & ~3); ! 964: break; ! 965: default: ! 966: case 8: ! 967: ret = ldq_kernel(T0 & ~7); ! 968: break; ! 969: } ! 970: } ! 971: } else { ! 972: switch(size) { ! 973: case 1: ! 974: ret = ldub_user(T0); ! 975: break; ! 976: case 2: ! 977: ret = lduw_user(T0 & ~1); ! 978: break; ! 979: case 4: ! 980: ret = ldl_user(T0 & ~3); ! 981: break; ! 982: default: ! 983: case 8: ! 984: ret = ldq_user(T0 & ~7); ! 985: break; ! 986: } ! 987: } ! 988: break; 1.1 root 989: case 0x14: // Bypass 990: case 0x15: // Bypass, non-cacheable 1.1.1.5 ! root 991: case 0x1c: // Bypass LE ! 992: case 0x1d: // Bypass, non-cacheable LE ! 993: { 1.1.1.2 root 994: switch(size) { 995: case 1: 996: ret = ldub_phys(T0); 997: break; 998: case 2: 999: ret = lduw_phys(T0 & ~1); 1000: break; 1001: case 4: 1002: ret = ldl_phys(T0 & ~3); 1003: break; 1004: default: 1005: case 8: 1006: ret = ldq_phys(T0 & ~7); 1007: break; 1008: } 1.1.1.5 ! root 1009: break; ! 1010: } 1.1 root 1011: case 0x04: // Nucleus 1012: case 0x0c: // Nucleus Little Endian (LE) 1013: case 0x11: // As if user secondary 1014: case 0x19: // As if user secondary LE 1015: case 0x24: // Nucleus quad LDD 128 bit atomic 1016: case 0x2c: // Nucleus quad LDD 128 bit atomic 1017: case 0x4a: // UPA config 1.1.1.5 ! root 1018: case 0x81: // Secondary 1.1 root 1019: case 0x83: // Secondary no-fault 1020: case 0x89: // Secondary LE 1021: case 0x8b: // Secondary no-fault LE 1.1.1.5 ! root 1022: // XXX ! 1023: break; 1.1 root 1024: case 0x45: // LSU 1.1.1.5 ! root 1025: ret = env->lsu; ! 1026: break; 1.1 root 1027: case 0x50: // I-MMU regs 1.1.1.5 ! root 1028: { ! 1029: int reg = (T0 >> 3) & 0xf; 1.1 root 1030: 1.1.1.5 ! root 1031: ret = env->immuregs[reg]; ! 1032: break; ! 1033: } 1.1 root 1034: case 0x51: // I-MMU 8k TSB pointer 1035: case 0x52: // I-MMU 64k TSB pointer 1036: case 0x55: // I-MMU data access 1.1.1.5 ! root 1037: // XXX ! 1038: break; 1.1 root 1039: case 0x56: // I-MMU tag read 1.1.1.5 ! root 1040: { ! 1041: unsigned int i; ! 1042: ! 1043: for (i = 0; i < 64; i++) { ! 1044: // Valid, ctx match, vaddr match ! 1045: if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 && ! 1046: env->itlb_tag[i] == T0) { ! 1047: ret = env->itlb_tag[i]; ! 1048: break; ! 1049: } ! 1050: } ! 1051: break; ! 1052: } 1.1 root 1053: case 0x58: // D-MMU regs 1.1.1.5 ! root 1054: { ! 1055: int reg = (T0 >> 3) & 0xf; 1.1 root 1056: 1.1.1.5 ! root 1057: ret = env->dmmuregs[reg]; ! 1058: break; ! 1059: } 1.1 root 1060: case 0x5e: // D-MMU tag read 1.1.1.5 ! root 1061: { ! 1062: unsigned int i; ! 1063: ! 1064: for (i = 0; i < 64; i++) { ! 1065: // Valid, ctx match, vaddr match ! 1066: if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 && ! 1067: env->dtlb_tag[i] == T0) { ! 1068: ret = env->dtlb_tag[i]; ! 1069: break; ! 1070: } ! 1071: } ! 1072: break; ! 1073: } 1.1 root 1074: case 0x59: // D-MMU 8k TSB pointer 1075: case 0x5a: // D-MMU 64k TSB pointer 1076: case 0x5b: // D-MMU data pointer 1077: case 0x5d: // D-MMU data access 1078: case 0x48: // Interrupt dispatch, RO 1079: case 0x49: // Interrupt data receive 1080: case 0x7f: // Incoming interrupt vector, RO 1.1.1.5 ! root 1081: // XXX ! 1082: break; 1.1 root 1083: case 0x54: // I-MMU data in, WO 1084: case 0x57: // I-MMU demap, WO 1085: case 0x5c: // D-MMU data in, WO 1086: case 0x5f: // D-MMU demap, WO 1087: case 0x77: // Interrupt vector, WO 1088: default: 1.1.1.5 ! root 1089: do_unassigned_access(T0, 0, 0, 1); ! 1090: ret = 0; ! 1091: break; ! 1092: } ! 1093: ! 1094: /* Convert from little endian */ ! 1095: switch (asi) { ! 1096: case 0x0c: // Nucleus Little Endian (LE) ! 1097: case 0x18: // As if user primary LE ! 1098: case 0x19: // As if user secondary LE ! 1099: case 0x1c: // Bypass LE ! 1100: case 0x1d: // Bypass, non-cacheable LE ! 1101: case 0x88: // Primary LE ! 1102: case 0x89: // Secondary LE ! 1103: case 0x8a: // Primary no-fault LE ! 1104: case 0x8b: // Secondary no-fault LE ! 1105: switch(size) { ! 1106: case 2: ! 1107: ret = bswap16(ret); ! 1108: break; ! 1109: case 4: ! 1110: ret = bswap32(ret); ! 1111: break; ! 1112: case 8: ! 1113: ret = bswap64(ret); ! 1114: break; ! 1115: default: ! 1116: break; ! 1117: } ! 1118: default: ! 1119: break; ! 1120: } ! 1121: ! 1122: /* Convert to signed number */ ! 1123: if (sign) { ! 1124: switch(size) { ! 1125: case 1: ! 1126: ret = (int8_t) ret; ! 1127: break; ! 1128: case 2: ! 1129: ret = (int16_t) ret; ! 1130: break; ! 1131: case 4: ! 1132: ret = (int32_t) ret; ! 1133: break; ! 1134: default: ! 1135: break; ! 1136: } 1.1 root 1137: } 1138: T1 = ret; 1139: } 1140: 1.1.1.5 ! root 1141: void helper_st_asi(int asi, int size) 1.1 root 1142: { 1.1.1.5 ! root 1143: if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) ! 1144: || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) ! 1145: raise_exception(TT_PRIV_ACT); ! 1146: ! 1147: /* Convert to little endian */ ! 1148: switch (asi) { ! 1149: case 0x0c: // Nucleus Little Endian (LE) ! 1150: case 0x18: // As if user primary LE ! 1151: case 0x19: // As if user secondary LE ! 1152: case 0x1c: // Bypass LE ! 1153: case 0x1d: // Bypass, non-cacheable LE ! 1154: case 0x88: // Primary LE ! 1155: case 0x89: // Secondary LE ! 1156: switch(size) { ! 1157: case 2: ! 1158: T0 = bswap16(T0); ! 1159: break; ! 1160: case 4: ! 1161: T0 = bswap32(T0); ! 1162: break; ! 1163: case 8: ! 1164: T0 = bswap64(T0); ! 1165: break; ! 1166: default: ! 1167: break; ! 1168: } ! 1169: default: ! 1170: break; ! 1171: } 1.1 root 1172: 1173: switch(asi) { 1.1.1.5 ! root 1174: case 0x10: // As if user primary ! 1175: case 0x18: // As if user primary LE ! 1176: case 0x80: // Primary ! 1177: case 0x88: // Primary LE ! 1178: if ((asi & 0x80) && (env->pstate & PS_PRIV)) { ! 1179: if (env->hpstate & HS_PRIV) { ! 1180: switch(size) { ! 1181: case 1: ! 1182: stb_hypv(T0, T1); ! 1183: break; ! 1184: case 2: ! 1185: stw_hypv(T0 & ~1, T1); ! 1186: break; ! 1187: case 4: ! 1188: stl_hypv(T0 & ~3, T1); ! 1189: break; ! 1190: case 8: ! 1191: default: ! 1192: stq_hypv(T0 & ~7, T1); ! 1193: break; ! 1194: } ! 1195: } else { ! 1196: switch(size) { ! 1197: case 1: ! 1198: stb_kernel(T0, T1); ! 1199: break; ! 1200: case 2: ! 1201: stw_kernel(T0 & ~1, T1); ! 1202: break; ! 1203: case 4: ! 1204: stl_kernel(T0 & ~3, T1); ! 1205: break; ! 1206: case 8: ! 1207: default: ! 1208: stq_kernel(T0 & ~7, T1); ! 1209: break; ! 1210: } ! 1211: } ! 1212: } else { ! 1213: switch(size) { ! 1214: case 1: ! 1215: stb_user(T0, T1); ! 1216: break; ! 1217: case 2: ! 1218: stw_user(T0 & ~1, T1); ! 1219: break; ! 1220: case 4: ! 1221: stl_user(T0 & ~3, T1); ! 1222: break; ! 1223: case 8: ! 1224: default: ! 1225: stq_user(T0 & ~7, T1); ! 1226: break; ! 1227: } ! 1228: } ! 1229: break; 1.1 root 1230: case 0x14: // Bypass 1231: case 0x15: // Bypass, non-cacheable 1.1.1.5 ! root 1232: case 0x1c: // Bypass LE ! 1233: case 0x1d: // Bypass, non-cacheable LE ! 1234: { 1.1.1.2 root 1235: switch(size) { 1236: case 1: 1237: stb_phys(T0, T1); 1238: break; 1239: case 2: 1240: stw_phys(T0 & ~1, T1); 1241: break; 1242: case 4: 1243: stl_phys(T0 & ~3, T1); 1244: break; 1245: case 8: 1246: default: 1247: stq_phys(T0 & ~7, T1); 1248: break; 1249: } 1.1.1.5 ! root 1250: } ! 1251: return; 1.1 root 1252: case 0x04: // Nucleus 1253: case 0x0c: // Nucleus Little Endian (LE) 1254: case 0x11: // As if user secondary 1255: case 0x19: // As if user secondary LE 1256: case 0x24: // Nucleus quad LDD 128 bit atomic 1257: case 0x2c: // Nucleus quad LDD 128 bit atomic 1258: case 0x4a: // UPA config 1.1.1.5 ! root 1259: case 0x81: // Secondary 1.1 root 1260: case 0x89: // Secondary LE 1.1.1.5 ! root 1261: // XXX ! 1262: return; 1.1 root 1263: case 0x45: // LSU 1.1.1.5 ! root 1264: { ! 1265: uint64_t oldreg; 1.1 root 1266: 1.1.1.5 ! root 1267: oldreg = env->lsu; ! 1268: env->lsu = T1 & (DMMU_E | IMMU_E); ! 1269: // Mappings generated during D/I MMU disabled mode are ! 1270: // invalid in normal mode ! 1271: if (oldreg != env->lsu) { ! 1272: DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu); 1.1 root 1273: #ifdef DEBUG_MMU 1.1.1.5 ! root 1274: dump_mmu(env); 1.1 root 1275: #endif 1.1.1.5 ! root 1276: tlb_flush(env, 1); ! 1277: } ! 1278: return; ! 1279: } 1.1 root 1280: case 0x50: // I-MMU regs 1.1.1.5 ! root 1281: { ! 1282: int reg = (T0 >> 3) & 0xf; ! 1283: uint64_t oldreg; ! 1284: ! 1285: oldreg = env->immuregs[reg]; 1.1 root 1286: switch(reg) { 1287: case 0: // RO 1288: case 4: 1289: return; 1290: case 1: // Not in I-MMU 1291: case 2: 1292: case 7: 1293: case 8: 1294: return; 1295: case 3: // SFSR 1.1.1.5 ! root 1296: if ((T1 & 1) == 0) ! 1297: T1 = 0; // Clear SFSR 1.1 root 1298: break; 1299: case 5: // TSB access 1300: case 6: // Tag access 1301: default: 1302: break; 1303: } 1.1.1.5 ! root 1304: env->immuregs[reg] = T1; 1.1 root 1305: if (oldreg != env->immuregs[reg]) { 1.1.1.5 ! root 1306: DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]); 1.1 root 1307: } 1.1.1.5 ! root 1308: #ifdef DEBUG_MMU ! 1309: dump_mmu(env); 1.1 root 1310: #endif 1.1.1.5 ! root 1311: return; ! 1312: } 1.1 root 1313: case 0x54: // I-MMU data in 1.1.1.5 ! root 1314: { ! 1315: unsigned int i; 1.1 root 1316: 1.1.1.5 ! root 1317: // Try finding an invalid entry ! 1318: for (i = 0; i < 64; i++) { ! 1319: if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) { ! 1320: env->itlb_tag[i] = env->immuregs[6]; ! 1321: env->itlb_tte[i] = T1; ! 1322: return; ! 1323: } ! 1324: } ! 1325: // Try finding an unlocked entry ! 1326: for (i = 0; i < 64; i++) { ! 1327: if ((env->itlb_tte[i] & 0x40) == 0) { ! 1328: env->itlb_tag[i] = env->immuregs[6]; ! 1329: env->itlb_tte[i] = T1; ! 1330: return; ! 1331: } ! 1332: } ! 1333: // error state? ! 1334: return; ! 1335: } 1.1 root 1336: case 0x55: // I-MMU data access 1.1.1.5 ! root 1337: { ! 1338: unsigned int i = (T0 >> 3) & 0x3f; 1.1 root 1339: 1.1.1.5 ! root 1340: env->itlb_tag[i] = env->immuregs[6]; ! 1341: env->itlb_tte[i] = T1; ! 1342: return; ! 1343: } 1.1 root 1344: case 0x57: // I-MMU demap 1.1.1.5 ! root 1345: // XXX ! 1346: return; 1.1 root 1347: case 0x58: // D-MMU regs 1.1.1.5 ! root 1348: { ! 1349: int reg = (T0 >> 3) & 0xf; ! 1350: uint64_t oldreg; ! 1351: ! 1352: oldreg = env->dmmuregs[reg]; 1.1 root 1353: switch(reg) { 1354: case 0: // RO 1355: case 4: 1356: return; 1357: case 3: // SFSR 1.1.1.5 ! root 1358: if ((T1 & 1) == 0) { ! 1359: T1 = 0; // Clear SFSR, Fault address ! 1360: env->dmmuregs[4] = 0; ! 1361: } ! 1362: env->dmmuregs[reg] = T1; 1.1 root 1363: break; 1364: case 1: // Primary context 1365: case 2: // Secondary context 1366: case 5: // TSB access 1367: case 6: // Tag access 1368: case 7: // Virtual Watchpoint 1369: case 8: // Physical Watchpoint 1370: default: 1371: break; 1372: } 1.1.1.5 ! root 1373: env->dmmuregs[reg] = T1; 1.1 root 1374: if (oldreg != env->dmmuregs[reg]) { 1.1.1.5 ! root 1375: DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]); 1.1 root 1376: } 1.1.1.5 ! root 1377: #ifdef DEBUG_MMU ! 1378: dump_mmu(env); 1.1 root 1379: #endif 1.1.1.5 ! root 1380: return; ! 1381: } 1.1 root 1382: case 0x5c: // D-MMU data in 1.1.1.5 ! root 1383: { ! 1384: unsigned int i; 1.1 root 1385: 1.1.1.5 ! root 1386: // Try finding an invalid entry ! 1387: for (i = 0; i < 64; i++) { ! 1388: if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) { ! 1389: env->dtlb_tag[i] = env->dmmuregs[6]; ! 1390: env->dtlb_tte[i] = T1; ! 1391: return; ! 1392: } ! 1393: } ! 1394: // Try finding an unlocked entry ! 1395: for (i = 0; i < 64; i++) { ! 1396: if ((env->dtlb_tte[i] & 0x40) == 0) { ! 1397: env->dtlb_tag[i] = env->dmmuregs[6]; ! 1398: env->dtlb_tte[i] = T1; ! 1399: return; ! 1400: } ! 1401: } ! 1402: // error state? ! 1403: return; ! 1404: } 1.1 root 1405: case 0x5d: // D-MMU data access 1.1.1.5 ! root 1406: { ! 1407: unsigned int i = (T0 >> 3) & 0x3f; 1.1 root 1408: 1.1.1.5 ! root 1409: env->dtlb_tag[i] = env->dmmuregs[6]; ! 1410: env->dtlb_tte[i] = T1; ! 1411: return; ! 1412: } 1.1 root 1413: case 0x5f: // D-MMU demap 1414: case 0x49: // Interrupt data receive 1.1.1.5 ! root 1415: // XXX ! 1416: return; 1.1 root 1417: case 0x51: // I-MMU 8k TSB pointer, RO 1418: case 0x52: // I-MMU 64k TSB pointer, RO 1419: case 0x56: // I-MMU tag read, RO 1420: case 0x59: // D-MMU 8k TSB pointer, RO 1421: case 0x5a: // D-MMU 64k TSB pointer, RO 1422: case 0x5b: // D-MMU data pointer, RO 1423: case 0x5e: // D-MMU tag read, RO 1424: case 0x48: // Interrupt dispatch, RO 1425: case 0x7f: // Incoming interrupt vector, RO 1426: case 0x82: // Primary no-fault, RO 1427: case 0x83: // Secondary no-fault, RO 1428: case 0x8a: // Primary no-fault LE, RO 1429: case 0x8b: // Secondary no-fault LE, RO 1430: default: 1.1.1.5 ! root 1431: do_unassigned_access(T0, 1, 0, 1); ! 1432: return; ! 1433: } ! 1434: } ! 1435: #endif /* CONFIG_USER_ONLY */ ! 1436: ! 1437: void helper_ldf_asi(int asi, int size, int rd) ! 1438: { ! 1439: target_ulong tmp_T0 = T0, tmp_T1 = T1; ! 1440: unsigned int i; ! 1441: ! 1442: switch (asi) { ! 1443: case 0xf0: // Block load primary ! 1444: case 0xf1: // Block load secondary ! 1445: case 0xf8: // Block load primary LE ! 1446: case 0xf9: // Block load secondary LE ! 1447: if (rd & 7) { ! 1448: raise_exception(TT_ILL_INSN); ! 1449: return; ! 1450: } ! 1451: if (T0 & 0x3f) { ! 1452: raise_exception(TT_UNALIGNED); ! 1453: return; ! 1454: } ! 1455: for (i = 0; i < 16; i++) { ! 1456: helper_ld_asi(asi & 0x8f, 4, 0); ! 1457: *(uint32_t *)&env->fpr[rd++] = T1; ! 1458: T0 += 4; ! 1459: } ! 1460: T0 = tmp_T0; ! 1461: T1 = tmp_T1; ! 1462: ! 1463: return; ! 1464: default: ! 1465: break; ! 1466: } ! 1467: ! 1468: helper_ld_asi(asi, size, 0); ! 1469: switch(size) { ! 1470: default: ! 1471: case 4: ! 1472: *((uint32_t *)&FT0) = T1; ! 1473: break; ! 1474: case 8: ! 1475: *((int64_t *)&DT0) = T1; ! 1476: break; ! 1477: #if defined(CONFIG_USER_ONLY) ! 1478: case 16: ! 1479: // XXX ! 1480: break; ! 1481: #endif 1.1 root 1482: } 1.1.1.5 ! root 1483: T1 = tmp_T1; 1.1 root 1484: } 1.1.1.5 ! root 1485: ! 1486: void helper_stf_asi(int asi, int size, int rd) ! 1487: { ! 1488: target_ulong tmp_T0 = T0, tmp_T1 = T1; ! 1489: unsigned int i; ! 1490: ! 1491: switch (asi) { ! 1492: case 0xf0: // Block store primary ! 1493: case 0xf1: // Block store secondary ! 1494: case 0xf8: // Block store primary LE ! 1495: case 0xf9: // Block store secondary LE ! 1496: if (rd & 7) { ! 1497: raise_exception(TT_ILL_INSN); ! 1498: return; ! 1499: } ! 1500: if (T0 & 0x3f) { ! 1501: raise_exception(TT_UNALIGNED); ! 1502: return; ! 1503: } ! 1504: for (i = 0; i < 16; i++) { ! 1505: T1 = *(uint32_t *)&env->fpr[rd++]; ! 1506: helper_st_asi(asi & 0x8f, 4); ! 1507: T0 += 4; ! 1508: } ! 1509: T0 = tmp_T0; ! 1510: T1 = tmp_T1; ! 1511: ! 1512: return; ! 1513: default: ! 1514: break; ! 1515: } ! 1516: ! 1517: switch(size) { ! 1518: default: ! 1519: case 4: ! 1520: T1 = *((uint32_t *)&FT0); ! 1521: break; ! 1522: case 8: ! 1523: T1 = *((int64_t *)&DT0); ! 1524: break; ! 1525: #if defined(CONFIG_USER_ONLY) ! 1526: case 16: ! 1527: // XXX ! 1528: break; 1.1 root 1529: #endif 1.1.1.5 ! root 1530: } ! 1531: helper_st_asi(asi, size); ! 1532: T1 = tmp_T1; ! 1533: } ! 1534: ! 1535: #endif /* TARGET_SPARC64 */ 1.1 root 1536: 1537: #ifndef TARGET_SPARC64 1538: void helper_rett() 1539: { 1540: unsigned int cwp; 1541: 1.1.1.5 ! root 1542: if (env->psret == 1) ! 1543: raise_exception(TT_ILL_INSN); ! 1544: 1.1 root 1545: env->psret = 1; 1.1.1.5 ! root 1546: cwp = (env->cwp + 1) & (NWINDOWS - 1); 1.1 root 1547: if (env->wim & (1 << cwp)) { 1548: raise_exception(TT_WIN_UNF); 1549: } 1550: set_cwp(cwp); 1551: env->psrs = env->psrps; 1552: } 1553: #endif 1554: 1555: void helper_ldfsr(void) 1556: { 1557: int rnd_mode; 1558: switch (env->fsr & FSR_RD_MASK) { 1559: case FSR_RD_NEAREST: 1560: rnd_mode = float_round_nearest_even; 1.1.1.5 ! root 1561: break; 1.1 root 1562: default: 1563: case FSR_RD_ZERO: 1564: rnd_mode = float_round_to_zero; 1.1.1.5 ! root 1565: break; 1.1 root 1566: case FSR_RD_POS: 1567: rnd_mode = float_round_up; 1.1.1.5 ! root 1568: break; 1.1 root 1569: case FSR_RD_NEG: 1570: rnd_mode = float_round_down; 1.1.1.5 ! root 1571: break; 1.1 root 1572: } 1573: set_float_rounding_mode(rnd_mode, &env->fp_status); 1574: } 1575: 1576: void helper_debug() 1577: { 1578: env->exception_index = EXCP_DEBUG; 1579: cpu_loop_exit(); 1580: } 1581: 1582: #ifndef TARGET_SPARC64 1583: void do_wrpsr() 1584: { 1.1.1.5 ! root 1585: if ((T0 & PSR_CWP) >= NWINDOWS) ! 1586: raise_exception(TT_ILL_INSN); ! 1587: else ! 1588: PUT_PSR(env, T0); 1.1 root 1589: } 1590: 1591: void do_rdpsr() 1592: { 1593: T0 = GET_PSR(env); 1594: } 1595: 1596: #else 1597: 1598: void do_popc() 1599: { 1.1.1.5 ! root 1600: T0 = ctpop64(T1); 1.1 root 1601: } 1602: 1603: static inline uint64_t *get_gregset(uint64_t pstate) 1604: { 1605: switch (pstate) { 1606: default: 1607: case 0: 1.1.1.5 ! root 1608: return env->bgregs; 1.1 root 1609: case PS_AG: 1.1.1.5 ! root 1610: return env->agregs; 1.1 root 1611: case PS_MG: 1.1.1.5 ! root 1612: return env->mgregs; 1.1 root 1613: case PS_IG: 1.1.1.5 ! root 1614: return env->igregs; 1.1 root 1615: } 1616: } 1617: 1.1.1.5 ! root 1618: static inline void change_pstate(uint64_t new_pstate) 1.1 root 1619: { 1.1.1.5 ! root 1620: uint64_t pstate_regs, new_pstate_regs; 1.1 root 1621: uint64_t *src, *dst; 1622: 1623: pstate_regs = env->pstate & 0xc01; 1624: new_pstate_regs = new_pstate & 0xc01; 1625: if (new_pstate_regs != pstate_regs) { 1.1.1.5 ! root 1626: // Switch global register bank ! 1627: src = get_gregset(new_pstate_regs); ! 1628: dst = get_gregset(pstate_regs); ! 1629: memcpy32(dst, env->gregs); ! 1630: memcpy32(env->gregs, src); 1.1 root 1631: } 1632: env->pstate = new_pstate; 1633: } 1634: 1.1.1.5 ! root 1635: void do_wrpstate(void) ! 1636: { ! 1637: change_pstate(T0 & 0xf3f); ! 1638: } ! 1639: 1.1 root 1640: void do_done(void) 1641: { 1642: env->tl--; 1643: env->pc = env->tnpc[env->tl]; 1644: env->npc = env->tnpc[env->tl] + 4; 1645: PUT_CCR(env, env->tstate[env->tl] >> 32); 1646: env->asi = (env->tstate[env->tl] >> 24) & 0xff; 1.1.1.5 ! root 1647: change_pstate((env->tstate[env->tl] >> 8) & 0xf3f); ! 1648: PUT_CWP64(env, env->tstate[env->tl] & 0xff); 1.1 root 1649: } 1650: 1651: void do_retry(void) 1652: { 1653: env->tl--; 1654: env->pc = env->tpc[env->tl]; 1655: env->npc = env->tnpc[env->tl]; 1656: PUT_CCR(env, env->tstate[env->tl] >> 32); 1657: env->asi = (env->tstate[env->tl] >> 24) & 0xff; 1.1.1.5 ! root 1658: change_pstate((env->tstate[env->tl] >> 8) & 0xf3f); ! 1659: PUT_CWP64(env, env->tstate[env->tl] & 0xff); 1.1 root 1660: } 1661: #endif 1662: 1663: void set_cwp(int new_cwp) 1664: { 1665: /* put the modified wrap registers at their proper location */ 1666: if (env->cwp == (NWINDOWS - 1)) 1667: memcpy32(env->regbase, env->regbase + NWINDOWS * 16); 1668: env->cwp = new_cwp; 1669: /* put the wrap registers at their temporary location */ 1670: if (new_cwp == (NWINDOWS - 1)) 1671: memcpy32(env->regbase + NWINDOWS * 16, env->regbase); 1672: env->regwptr = env->regbase + (new_cwp * 16); 1673: REGWPTR = env->regwptr; 1674: } 1675: 1676: void cpu_set_cwp(CPUState *env1, int new_cwp) 1677: { 1678: CPUState *saved_env; 1679: #ifdef reg_REGWPTR 1680: target_ulong *saved_regwptr; 1681: #endif 1682: 1683: saved_env = env; 1684: #ifdef reg_REGWPTR 1685: saved_regwptr = REGWPTR; 1686: #endif 1687: env = env1; 1688: set_cwp(new_cwp); 1689: env = saved_env; 1690: #ifdef reg_REGWPTR 1691: REGWPTR = saved_regwptr; 1692: #endif 1693: } 1694: 1695: #ifdef TARGET_SPARC64 1.1.1.5 ! root 1696: #ifdef DEBUG_PCALL ! 1697: static const char * const excp_names[0x50] = { ! 1698: [TT_TFAULT] = "Instruction Access Fault", ! 1699: [TT_TMISS] = "Instruction Access MMU Miss", ! 1700: [TT_CODE_ACCESS] = "Instruction Access Error", ! 1701: [TT_ILL_INSN] = "Illegal Instruction", ! 1702: [TT_PRIV_INSN] = "Privileged Instruction", ! 1703: [TT_NFPU_INSN] = "FPU Disabled", ! 1704: [TT_FP_EXCP] = "FPU Exception", ! 1705: [TT_TOVF] = "Tag Overflow", ! 1706: [TT_CLRWIN] = "Clean Windows", ! 1707: [TT_DIV_ZERO] = "Division By Zero", ! 1708: [TT_DFAULT] = "Data Access Fault", ! 1709: [TT_DMISS] = "Data Access MMU Miss", ! 1710: [TT_DATA_ACCESS] = "Data Access Error", ! 1711: [TT_DPROT] = "Data Protection Error", ! 1712: [TT_UNALIGNED] = "Unaligned Memory Access", ! 1713: [TT_PRIV_ACT] = "Privileged Action", ! 1714: [TT_EXTINT | 0x1] = "External Interrupt 1", ! 1715: [TT_EXTINT | 0x2] = "External Interrupt 2", ! 1716: [TT_EXTINT | 0x3] = "External Interrupt 3", ! 1717: [TT_EXTINT | 0x4] = "External Interrupt 4", ! 1718: [TT_EXTINT | 0x5] = "External Interrupt 5", ! 1719: [TT_EXTINT | 0x6] = "External Interrupt 6", ! 1720: [TT_EXTINT | 0x7] = "External Interrupt 7", ! 1721: [TT_EXTINT | 0x8] = "External Interrupt 8", ! 1722: [TT_EXTINT | 0x9] = "External Interrupt 9", ! 1723: [TT_EXTINT | 0xa] = "External Interrupt 10", ! 1724: [TT_EXTINT | 0xb] = "External Interrupt 11", ! 1725: [TT_EXTINT | 0xc] = "External Interrupt 12", ! 1726: [TT_EXTINT | 0xd] = "External Interrupt 13", ! 1727: [TT_EXTINT | 0xe] = "External Interrupt 14", ! 1728: [TT_EXTINT | 0xf] = "External Interrupt 15", ! 1729: }; ! 1730: #endif ! 1731: 1.1 root 1732: void do_interrupt(int intno) 1733: { 1734: #ifdef DEBUG_PCALL 1735: if (loglevel & CPU_LOG_INT) { 1.1.1.5 ! root 1736: static int count; ! 1737: const char *name; ! 1738: ! 1739: if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80)) ! 1740: name = "Unknown"; ! 1741: else if (intno >= 0x100) ! 1742: name = "Trap Instruction"; ! 1743: else if (intno >= 0xc0) ! 1744: name = "Window Fill"; ! 1745: else if (intno >= 0x80) ! 1746: name = "Window Spill"; ! 1747: else { ! 1748: name = excp_names[intno]; ! 1749: if (!name) ! 1750: name = "Unknown"; ! 1751: } ! 1752: ! 1753: fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64 ! 1754: " SP=%016" PRIx64 "\n", ! 1755: count, name, intno, 1.1 root 1756: env->pc, 1757: env->npc, env->regwptr[6]); 1.1.1.5 ! root 1758: cpu_dump_state(env, logfile, fprintf, 0); 1.1 root 1759: #if 0 1.1.1.5 ! root 1760: { ! 1761: int i; ! 1762: uint8_t *ptr; ! 1763: ! 1764: fprintf(logfile, " code="); ! 1765: ptr = (uint8_t *)env->pc; ! 1766: for(i = 0; i < 16; i++) { ! 1767: fprintf(logfile, " %02x", ldub(ptr + i)); ! 1768: } ! 1769: fprintf(logfile, "\n"); ! 1770: } 1.1 root 1771: #endif 1.1.1.5 ! root 1772: count++; 1.1 root 1773: } 1774: #endif 1.1.1.5 ! root 1775: #if !defined(CONFIG_USER_ONLY) 1.1 root 1776: if (env->tl == MAXTL) { 1.1.1.2 root 1777: cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index); 1.1.1.5 ! root 1778: return; 1.1 root 1779: } 1780: #endif 1781: env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) | 1.1.1.5 ! root 1782: ((env->pstate & 0xf3f) << 8) | GET_CWP64(env); 1.1 root 1783: env->tpc[env->tl] = env->pc; 1784: env->tnpc[env->tl] = env->npc; 1785: env->tt[env->tl] = intno; 1.1.1.5 ! root 1786: change_pstate(PS_PEF | PS_PRIV | PS_AG); ! 1787: ! 1788: if (intno == TT_CLRWIN) ! 1789: set_cwp((env->cwp - 1) & (NWINDOWS - 1)); ! 1790: else if ((intno & 0x1c0) == TT_SPILL) ! 1791: set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1)); ! 1792: else if ((intno & 0x1c0) == TT_FILL) ! 1793: set_cwp((env->cwp + 1) & (NWINDOWS - 1)); 1.1 root 1794: env->tbr &= ~0x7fffULL; 1795: env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5); 1796: if (env->tl < MAXTL - 1) { 1.1.1.5 ! root 1797: env->tl++; 1.1 root 1798: } else { 1.1.1.5 ! root 1799: env->pstate |= PS_RED; ! 1800: if (env->tl != MAXTL) ! 1801: env->tl++; 1.1 root 1802: } 1803: env->pc = env->tbr; 1804: env->npc = env->pc + 4; 1805: env->exception_index = 0; 1806: } 1807: #else 1.1.1.5 ! root 1808: #ifdef DEBUG_PCALL ! 1809: static const char * const excp_names[0x80] = { ! 1810: [TT_TFAULT] = "Instruction Access Fault", ! 1811: [TT_ILL_INSN] = "Illegal Instruction", ! 1812: [TT_PRIV_INSN] = "Privileged Instruction", ! 1813: [TT_NFPU_INSN] = "FPU Disabled", ! 1814: [TT_WIN_OVF] = "Window Overflow", ! 1815: [TT_WIN_UNF] = "Window Underflow", ! 1816: [TT_UNALIGNED] = "Unaligned Memory Access", ! 1817: [TT_FP_EXCP] = "FPU Exception", ! 1818: [TT_DFAULT] = "Data Access Fault", ! 1819: [TT_TOVF] = "Tag Overflow", ! 1820: [TT_EXTINT | 0x1] = "External Interrupt 1", ! 1821: [TT_EXTINT | 0x2] = "External Interrupt 2", ! 1822: [TT_EXTINT | 0x3] = "External Interrupt 3", ! 1823: [TT_EXTINT | 0x4] = "External Interrupt 4", ! 1824: [TT_EXTINT | 0x5] = "External Interrupt 5", ! 1825: [TT_EXTINT | 0x6] = "External Interrupt 6", ! 1826: [TT_EXTINT | 0x7] = "External Interrupt 7", ! 1827: [TT_EXTINT | 0x8] = "External Interrupt 8", ! 1828: [TT_EXTINT | 0x9] = "External Interrupt 9", ! 1829: [TT_EXTINT | 0xa] = "External Interrupt 10", ! 1830: [TT_EXTINT | 0xb] = "External Interrupt 11", ! 1831: [TT_EXTINT | 0xc] = "External Interrupt 12", ! 1832: [TT_EXTINT | 0xd] = "External Interrupt 13", ! 1833: [TT_EXTINT | 0xe] = "External Interrupt 14", ! 1834: [TT_EXTINT | 0xf] = "External Interrupt 15", ! 1835: [TT_TOVF] = "Tag Overflow", ! 1836: [TT_CODE_ACCESS] = "Instruction Access Error", ! 1837: [TT_DATA_ACCESS] = "Data Access Error", ! 1838: [TT_DIV_ZERO] = "Division By Zero", ! 1839: [TT_NCP_INSN] = "Coprocessor Disabled", ! 1840: }; ! 1841: #endif ! 1842: 1.1 root 1843: void do_interrupt(int intno) 1844: { 1845: int cwp; 1846: 1847: #ifdef DEBUG_PCALL 1848: if (loglevel & CPU_LOG_INT) { 1.1.1.5 ! root 1849: static int count; ! 1850: const char *name; ! 1851: ! 1852: if (intno < 0 || intno >= 0x100) ! 1853: name = "Unknown"; ! 1854: else if (intno >= 0x80) ! 1855: name = "Trap Instruction"; ! 1856: else { ! 1857: name = excp_names[intno]; ! 1858: if (!name) ! 1859: name = "Unknown"; ! 1860: } ! 1861: ! 1862: fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n", ! 1863: count, name, intno, 1.1 root 1864: env->pc, 1865: env->npc, env->regwptr[6]); 1.1.1.5 ! root 1866: cpu_dump_state(env, logfile, fprintf, 0); 1.1 root 1867: #if 0 1.1.1.5 ! root 1868: { ! 1869: int i; ! 1870: uint8_t *ptr; ! 1871: ! 1872: fprintf(logfile, " code="); ! 1873: ptr = (uint8_t *)env->pc; ! 1874: for(i = 0; i < 16; i++) { ! 1875: fprintf(logfile, " %02x", ldub(ptr + i)); ! 1876: } ! 1877: fprintf(logfile, "\n"); ! 1878: } 1.1 root 1879: #endif 1.1.1.5 ! root 1880: count++; 1.1 root 1881: } 1882: #endif 1.1.1.5 ! root 1883: #if !defined(CONFIG_USER_ONLY) 1.1 root 1884: if (env->psret == 0) { 1.1.1.2 root 1885: cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index); 1.1.1.5 ! root 1886: return; 1.1 root 1887: } 1888: #endif 1889: env->psret = 0; 1.1.1.5 ! root 1890: cwp = (env->cwp - 1) & (NWINDOWS - 1); 1.1 root 1891: set_cwp(cwp); 1892: env->regwptr[9] = env->pc; 1893: env->regwptr[10] = env->npc; 1894: env->psrps = env->psrs; 1895: env->psrs = 1; 1896: env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4); 1897: env->pc = env->tbr; 1898: env->npc = env->pc + 4; 1899: env->exception_index = 0; 1900: } 1901: #endif 1902: 1.1.1.5 ! root 1903: #if !defined(CONFIG_USER_ONLY) ! 1904: ! 1905: static void do_unaligned_access(target_ulong addr, int is_write, int is_user, ! 1906: void *retaddr); 1.1 root 1907: 1908: #define MMUSUFFIX _mmu 1.1.1.5 ! root 1909: #define ALIGNED_ONLY ! 1910: #ifdef __s390__ ! 1911: # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL)) ! 1912: #else ! 1913: # define GETPC() (__builtin_return_address(0)) ! 1914: #endif 1.1 root 1915: 1916: #define SHIFT 0 1917: #include "softmmu_template.h" 1918: 1919: #define SHIFT 1 1920: #include "softmmu_template.h" 1921: 1922: #define SHIFT 2 1923: #include "softmmu_template.h" 1924: 1925: #define SHIFT 3 1926: #include "softmmu_template.h" 1927: 1.1.1.5 ! root 1928: static void do_unaligned_access(target_ulong addr, int is_write, int is_user, ! 1929: void *retaddr) ! 1930: { ! 1931: #ifdef DEBUG_UNALIGNED ! 1932: printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc); ! 1933: #endif ! 1934: raise_exception(TT_UNALIGNED); ! 1935: } 1.1 root 1936: 1937: /* try to fill the TLB and return an exception if error. If retaddr is 1938: NULL, it means that the function was called in C code (i.e. not 1939: from generated code or from helper.c) */ 1940: /* XXX: fix it to restore all registers */ 1.1.1.5 ! root 1941: void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) 1.1 root 1942: { 1943: TranslationBlock *tb; 1944: int ret; 1945: unsigned long pc; 1946: CPUState *saved_env; 1947: 1948: /* XXX: hack to restore env in all cases, even if not called from 1949: generated code */ 1950: saved_env = env; 1951: env = cpu_single_env; 1952: 1.1.1.5 ! root 1953: ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); 1.1 root 1954: if (ret) { 1955: if (retaddr) { 1956: /* now we have a real cpu fault */ 1957: pc = (unsigned long)retaddr; 1958: tb = tb_find_pc(pc); 1959: if (tb) { 1960: /* the PC is inside the translated code. It means that we have 1961: a virtual CPU fault */ 1962: cpu_restore_state(tb, env, pc, (void *)T2); 1963: } 1964: } 1965: cpu_loop_exit(); 1966: } 1967: env = saved_env; 1968: } 1969: 1970: #endif 1.1.1.5 ! root 1971: ! 1972: #ifndef TARGET_SPARC64 ! 1973: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, ! 1974: int is_asi) ! 1975: { ! 1976: CPUState *saved_env; ! 1977: ! 1978: /* XXX: hack to restore env in all cases, even if not called from ! 1979: generated code */ ! 1980: saved_env = env; ! 1981: env = cpu_single_env; ! 1982: #ifdef DEBUG_UNASSIGNED ! 1983: if (is_asi) ! 1984: printf("Unassigned mem %s access to " TARGET_FMT_plx " asi 0x%02x from " ! 1985: TARGET_FMT_lx "\n", ! 1986: is_exec ? "exec" : is_write ? "write" : "read", addr, is_asi, ! 1987: env->pc); ! 1988: else ! 1989: printf("Unassigned mem %s access to " TARGET_FMT_plx " from " ! 1990: TARGET_FMT_lx "\n", ! 1991: is_exec ? "exec" : is_write ? "write" : "read", addr, env->pc); ! 1992: #endif ! 1993: if (env->mmuregs[3]) /* Fault status register */ ! 1994: env->mmuregs[3] = 1; /* overflow (not read before another fault) */ ! 1995: if (is_asi) ! 1996: env->mmuregs[3] |= 1 << 16; ! 1997: if (env->psrs) ! 1998: env->mmuregs[3] |= 1 << 5; ! 1999: if (is_exec) ! 2000: env->mmuregs[3] |= 1 << 6; ! 2001: if (is_write) ! 2002: env->mmuregs[3] |= 1 << 7; ! 2003: env->mmuregs[3] |= (5 << 2) | 2; ! 2004: env->mmuregs[4] = addr; /* Fault address register */ ! 2005: if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) { ! 2006: if (is_exec) ! 2007: raise_exception(TT_CODE_ACCESS); ! 2008: else ! 2009: raise_exception(TT_DATA_ACCESS); ! 2010: } ! 2011: env = saved_env; ! 2012: } ! 2013: #else ! 2014: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, ! 2015: int is_asi) ! 2016: { ! 2017: #ifdef DEBUG_UNASSIGNED ! 2018: CPUState *saved_env; ! 2019: ! 2020: /* XXX: hack to restore env in all cases, even if not called from ! 2021: generated code */ ! 2022: saved_env = env; ! 2023: env = cpu_single_env; ! 2024: printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n", ! 2025: addr, env->pc); ! 2026: env = saved_env; ! 2027: #endif ! 2028: if (is_exec) ! 2029: raise_exception(TT_CODE_ACCESS); ! 2030: else ! 2031: raise_exception(TT_DATA_ACCESS); ! 2032: } ! 2033: #endif ! 2034:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.