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