|
|
1.1 ! root 1: /* ! 2: * MIPS emulation helpers for qemu. ! 3: * ! 4: * Copyright (c) 2004-2005 Jocelyn Mayer ! 5: * ! 6: * This library is free software; you can redistribute it and/or ! 7: * modify it under the terms of the GNU Lesser General Public ! 8: * License as published by the Free Software Foundation; either ! 9: * version 2 of the License, or (at your option) any later version. ! 10: * ! 11: * This library is distributed in the hope that it will be useful, ! 12: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 14: * Lesser General Public License for more details. ! 15: * ! 16: * You should have received a copy of the GNU Lesser General Public ! 17: * License along with this library; if not, write to the Free Software ! 18: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ! 19: */ ! 20: #include <math.h> ! 21: #include "exec.h" ! 22: ! 23: #define MIPS_DEBUG_DISAS ! 24: ! 25: /*****************************************************************************/ ! 26: /* Exceptions processing helpers */ ! 27: void cpu_loop_exit(void) ! 28: { ! 29: longjmp(env->jmp_env, 1); ! 30: } ! 31: ! 32: void do_raise_exception_err (uint32_t exception, int error_code) ! 33: { ! 34: #if 1 ! 35: if (logfile && exception < 0x100) ! 36: fprintf(logfile, "%s: %d %d\n", __func__, exception, error_code); ! 37: #endif ! 38: env->exception_index = exception; ! 39: env->error_code = error_code; ! 40: T0 = 0; ! 41: cpu_loop_exit(); ! 42: } ! 43: ! 44: void do_raise_exception (uint32_t exception) ! 45: { ! 46: do_raise_exception_err(exception, 0); ! 47: } ! 48: ! 49: #define MEMSUFFIX _raw ! 50: #include "op_helper_mem.c" ! 51: #undef MEMSUFFIX ! 52: #if !defined(CONFIG_USER_ONLY) ! 53: #define MEMSUFFIX _user ! 54: #include "op_helper_mem.c" ! 55: #undef MEMSUFFIX ! 56: #define MEMSUFFIX _kernel ! 57: #include "op_helper_mem.c" ! 58: #undef MEMSUFFIX ! 59: #endif ! 60: ! 61: /* 64 bits arithmetic for 32 bits hosts */ ! 62: #if (HOST_LONG_BITS == 32) ! 63: static inline uint64_t get_HILO (void) ! 64: { ! 65: return ((uint64_t)env->HI << 32) | (uint64_t)env->LO; ! 66: } ! 67: ! 68: static inline void set_HILO (uint64_t HILO) ! 69: { ! 70: env->LO = HILO & 0xFFFFFFFF; ! 71: env->HI = HILO >> 32; ! 72: } ! 73: ! 74: void do_mult (void) ! 75: { ! 76: set_HILO((int64_t)T0 * (int64_t)T1); ! 77: } ! 78: ! 79: void do_multu (void) ! 80: { ! 81: set_HILO((uint64_t)T0 * (uint64_t)T1); ! 82: } ! 83: ! 84: void do_madd (void) ! 85: { ! 86: int64_t tmp; ! 87: ! 88: tmp = ((int64_t)T0 * (int64_t)T1); ! 89: set_HILO((int64_t)get_HILO() + tmp); ! 90: } ! 91: ! 92: void do_maddu (void) ! 93: { ! 94: uint64_t tmp; ! 95: ! 96: tmp = ((uint64_t)T0 * (uint64_t)T1); ! 97: set_HILO(get_HILO() + tmp); ! 98: } ! 99: ! 100: void do_msub (void) ! 101: { ! 102: int64_t tmp; ! 103: ! 104: tmp = ((int64_t)T0 * (int64_t)T1); ! 105: set_HILO((int64_t)get_HILO() - tmp); ! 106: } ! 107: ! 108: void do_msubu (void) ! 109: { ! 110: uint64_t tmp; ! 111: ! 112: tmp = ((uint64_t)T0 * (uint64_t)T1); ! 113: set_HILO(get_HILO() - tmp); ! 114: } ! 115: #endif ! 116: ! 117: /* CP0 helpers */ ! 118: void do_mfc0 (int reg, int sel) ! 119: { ! 120: const unsigned char *rn; ! 121: ! 122: if (sel != 0 && reg != 16 && reg != 28) { ! 123: rn = "invalid"; ! 124: goto print; ! 125: } ! 126: switch (reg) { ! 127: case 0: ! 128: T0 = env->CP0_index; ! 129: rn = "Index"; ! 130: break; ! 131: case 1: ! 132: T0 = cpu_mips_get_random(env); ! 133: rn = "Random"; ! 134: break; ! 135: case 2: ! 136: T0 = env->CP0_EntryLo0; ! 137: rn = "EntryLo0"; ! 138: break; ! 139: case 3: ! 140: T0 = env->CP0_EntryLo1; ! 141: rn = "EntryLo1"; ! 142: break; ! 143: case 4: ! 144: T0 = env->CP0_Context; ! 145: rn = "Context"; ! 146: break; ! 147: case 5: ! 148: T0 = env->CP0_PageMask; ! 149: rn = "PageMask"; ! 150: break; ! 151: case 6: ! 152: T0 = env->CP0_Wired; ! 153: rn = "Wired"; ! 154: break; ! 155: case 8: ! 156: T0 = env->CP0_BadVAddr; ! 157: rn = "BadVaddr"; ! 158: break; ! 159: case 9: ! 160: T0 = cpu_mips_get_count(env); ! 161: rn = "Count"; ! 162: break; ! 163: case 10: ! 164: T0 = env->CP0_EntryHi; ! 165: rn = "EntryHi"; ! 166: break; ! 167: case 11: ! 168: T0 = env->CP0_Compare; ! 169: rn = "Compare"; ! 170: break; ! 171: case 12: ! 172: T0 = env->CP0_Status; ! 173: if (env->hflags & MIPS_HFLAG_UM) ! 174: T0 |= (1 << CP0St_UM); ! 175: if (env->hflags & MIPS_HFLAG_ERL) ! 176: T0 |= (1 << CP0St_ERL); ! 177: if (env->hflags & MIPS_HFLAG_EXL) ! 178: T0 |= (1 << CP0St_EXL); ! 179: rn = "Status"; ! 180: break; ! 181: case 13: ! 182: T0 = env->CP0_Cause; ! 183: rn = "Cause"; ! 184: break; ! 185: case 14: ! 186: T0 = env->CP0_EPC; ! 187: rn = "EPC"; ! 188: break; ! 189: case 15: ! 190: T0 = env->CP0_PRid; ! 191: rn = "PRid"; ! 192: break; ! 193: case 16: ! 194: switch (sel) { ! 195: case 0: ! 196: T0 = env->CP0_Config0; ! 197: rn = "Config"; ! 198: break; ! 199: case 1: ! 200: T0 = env->CP0_Config1; ! 201: rn = "Config1"; ! 202: break; ! 203: default: ! 204: rn = "Unknown config register"; ! 205: break; ! 206: } ! 207: break; ! 208: case 17: ! 209: T0 = env->CP0_LLAddr >> 4; ! 210: rn = "LLAddr"; ! 211: break; ! 212: case 18: ! 213: T0 = env->CP0_WatchLo; ! 214: rn = "WatchLo"; ! 215: break; ! 216: case 19: ! 217: T0 = env->CP0_WatchHi; ! 218: rn = "WatchHi"; ! 219: break; ! 220: case 23: ! 221: T0 = env->CP0_Debug; ! 222: if (env->hflags & MIPS_HFLAG_DM) ! 223: T0 |= 1 << CP0DB_DM; ! 224: rn = "Debug"; ! 225: break; ! 226: case 24: ! 227: T0 = env->CP0_DEPC; ! 228: rn = "DEPC"; ! 229: break; ! 230: case 28: ! 231: switch (sel) { ! 232: case 0: ! 233: T0 = env->CP0_TagLo; ! 234: rn = "TagLo"; ! 235: break; ! 236: case 1: ! 237: T0 = env->CP0_DataLo; ! 238: rn = "DataLo"; ! 239: break; ! 240: default: ! 241: rn = "unknown sel"; ! 242: break; ! 243: } ! 244: break; ! 245: case 30: ! 246: T0 = env->CP0_ErrorEPC; ! 247: rn = "ErrorEPC"; ! 248: break; ! 249: case 31: ! 250: T0 = env->CP0_DESAVE; ! 251: rn = "DESAVE"; ! 252: break; ! 253: default: ! 254: rn = "unknown"; ! 255: break; ! 256: } ! 257: print: ! 258: #if defined MIPS_DEBUG_DISAS ! 259: if (loglevel & CPU_LOG_TB_IN_ASM) { ! 260: fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n", ! 261: env->PC, rn, T0, reg, sel); ! 262: } ! 263: #endif ! 264: return; ! 265: } ! 266: ! 267: void do_mtc0 (int reg, int sel) ! 268: { ! 269: const unsigned char *rn; ! 270: uint32_t val, old, mask; ! 271: ! 272: if (sel != 0 && reg != 16 && reg != 28) { ! 273: val = -1; ! 274: old = -1; ! 275: rn = "invalid"; ! 276: goto print; ! 277: } ! 278: switch (reg) { ! 279: case 0: ! 280: val = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F); ! 281: old = env->CP0_index; ! 282: env->CP0_index = val; ! 283: rn = "Index"; ! 284: break; ! 285: case 2: ! 286: val = T0 & 0x03FFFFFFF; ! 287: old = env->CP0_EntryLo0; ! 288: env->CP0_EntryLo0 = val; ! 289: rn = "EntryLo0"; ! 290: break; ! 291: case 3: ! 292: val = T0 & 0x03FFFFFFF; ! 293: old = env->CP0_EntryLo1; ! 294: env->CP0_EntryLo1 = val; ! 295: rn = "EntryLo1"; ! 296: break; ! 297: case 4: ! 298: val = (env->CP0_Context & 0xFF000000) | (T0 & 0x00FFFFF0); ! 299: old = env->CP0_Context; ! 300: env->CP0_Context = val; ! 301: rn = "Context"; ! 302: break; ! 303: case 5: ! 304: val = T0 & 0x01FFE000; ! 305: old = env->CP0_PageMask; ! 306: env->CP0_PageMask = val; ! 307: rn = "PageMask"; ! 308: break; ! 309: case 6: ! 310: val = T0 & 0x0000000F; ! 311: old = env->CP0_Wired; ! 312: env->CP0_Wired = val; ! 313: rn = "Wired"; ! 314: break; ! 315: case 9: ! 316: val = T0; ! 317: old = cpu_mips_get_count(env); ! 318: cpu_mips_store_count(env, val); ! 319: rn = "Count"; ! 320: break; ! 321: case 10: ! 322: val = T0 & 0xFFFFF0FF; ! 323: old = env->CP0_EntryHi; ! 324: env->CP0_EntryHi = val; ! 325: rn = "EntryHi"; ! 326: break; ! 327: case 11: ! 328: val = T0; ! 329: old = env->CP0_Compare; ! 330: cpu_mips_store_compare(env, val); ! 331: rn = "Compare"; ! 332: break; ! 333: case 12: ! 334: val = T0 & 0xFA78FF01; ! 335: if (T0 & (1 << CP0St_UM)) ! 336: env->hflags |= MIPS_HFLAG_UM; ! 337: else ! 338: env->hflags &= ~MIPS_HFLAG_UM; ! 339: if (T0 & (1 << CP0St_ERL)) ! 340: env->hflags |= MIPS_HFLAG_ERL; ! 341: else ! 342: env->hflags &= ~MIPS_HFLAG_ERL; ! 343: if (T0 & (1 << CP0St_EXL)) ! 344: env->hflags |= MIPS_HFLAG_EXL; ! 345: else ! 346: env->hflags &= ~MIPS_HFLAG_EXL; ! 347: old = env->CP0_Status; ! 348: env->CP0_Status = val; ! 349: /* If we unmasked an asserted IRQ, raise it */ ! 350: mask = 0x0000FF00; ! 351: if (loglevel & CPU_LOG_TB_IN_ASM) { ! 352: fprintf(logfile, "Status %08x => %08x Cause %08x (%08x %08x %08x)\n", ! 353: old, val, env->CP0_Cause, old & mask, val & mask, ! 354: env->CP0_Cause & mask); ! 355: } ! 356: #if 1 ! 357: if ((val & (1 << CP0St_IE)) && !(old & (1 << CP0St_IE)) && ! 358: !(env->hflags & MIPS_HFLAG_EXL) && ! 359: !(env->hflags & MIPS_HFLAG_ERL) && ! 360: !(env->hflags & MIPS_HFLAG_DM) && ! 361: (env->CP0_Status & env->CP0_Cause & mask)) { ! 362: if (logfile) ! 363: fprintf(logfile, "Raise pending IRQs\n"); ! 364: env->interrupt_request |= CPU_INTERRUPT_HARD; ! 365: do_raise_exception(EXCP_EXT_INTERRUPT); ! 366: } else if (!(val & 0x00000001) && (old & 0x00000001)) { ! 367: env->interrupt_request &= ~CPU_INTERRUPT_HARD; ! 368: } ! 369: #endif ! 370: rn = "Status"; ! 371: break; ! 372: case 13: ! 373: val = (env->CP0_Cause & 0xB000F87C) | (T0 & 0x000C00300); ! 374: old = env->CP0_Cause; ! 375: env->CP0_Cause = val; ! 376: #if 0 ! 377: { ! 378: int i; ! 379: /* Check if we ever asserted a software IRQ */ ! 380: for (i = 0; i < 2; i++) { ! 381: mask = 0x100 << i; ! 382: if ((val & mask) & !(old & mask)) ! 383: mips_set_irq(i); ! 384: } ! 385: } ! 386: #endif ! 387: rn = "Cause"; ! 388: break; ! 389: case 14: ! 390: val = T0; ! 391: old = env->CP0_EPC; ! 392: env->CP0_EPC = val; ! 393: rn = "EPC"; ! 394: break; ! 395: case 16: ! 396: switch (sel) { ! 397: case 0: ! 398: #if defined(MIPS_USES_R4K_TLB) ! 399: val = (env->CP0_Config0 & 0x8017FF80) | (T0 & 0x7E000001); ! 400: #else ! 401: val = (env->CP0_Config0 & 0xFE17FF80) | (T0 & 0x00000001); ! 402: #endif ! 403: old = env->CP0_Config0; ! 404: env->CP0_Config0 = val; ! 405: rn = "Config0"; ! 406: break; ! 407: default: ! 408: val = -1; ! 409: old = -1; ! 410: rn = "bad config selector"; ! 411: break; ! 412: } ! 413: break; ! 414: case 18: ! 415: val = T0; ! 416: old = env->CP0_WatchLo; ! 417: env->CP0_WatchLo = val; ! 418: rn = "WatchLo"; ! 419: break; ! 420: case 19: ! 421: val = T0 & 0x40FF0FF8; ! 422: old = env->CP0_WatchHi; ! 423: env->CP0_WatchHi = val; ! 424: rn = "WatchHi"; ! 425: break; ! 426: case 23: ! 427: val = (env->CP0_Debug & 0x8C03FC1F) | (T0 & 0x13300120); ! 428: if (T0 & (1 << CP0DB_DM)) ! 429: env->hflags |= MIPS_HFLAG_DM; ! 430: else ! 431: env->hflags &= ~MIPS_HFLAG_DM; ! 432: old = env->CP0_Debug; ! 433: env->CP0_Debug = val; ! 434: rn = "Debug"; ! 435: break; ! 436: case 24: ! 437: val = T0; ! 438: old = env->CP0_DEPC; ! 439: env->CP0_DEPC = val; ! 440: rn = "DEPC"; ! 441: break; ! 442: case 28: ! 443: switch (sel) { ! 444: case 0: ! 445: val = T0 & 0xFFFFFCF6; ! 446: old = env->CP0_TagLo; ! 447: env->CP0_TagLo = val; ! 448: rn = "TagLo"; ! 449: break; ! 450: default: ! 451: val = -1; ! 452: old = -1; ! 453: rn = "invalid sel"; ! 454: break; ! 455: } ! 456: break; ! 457: case 30: ! 458: val = T0; ! 459: old = env->CP0_ErrorEPC; ! 460: env->CP0_ErrorEPC = val; ! 461: rn = "EPC"; ! 462: break; ! 463: case 31: ! 464: val = T0; ! 465: old = env->CP0_DESAVE; ! 466: env->CP0_DESAVE = val; ! 467: rn = "DESAVE"; ! 468: break; ! 469: default: ! 470: val = -1; ! 471: old = -1; ! 472: rn = "unknown"; ! 473: break; ! 474: } ! 475: print: ! 476: #if defined MIPS_DEBUG_DISAS ! 477: if (loglevel & CPU_LOG_TB_IN_ASM) { ! 478: fprintf(logfile, "%08x mtc0 %s %08x => %08x (%d %d %08x)\n", ! 479: env->PC, rn, T0, val, reg, sel, old); ! 480: } ! 481: #endif ! 482: return; ! 483: } ! 484: ! 485: /* TLB management */ ! 486: #if defined(MIPS_USES_R4K_TLB) ! 487: static void invalidate_tb (int idx) ! 488: { ! 489: tlb_t *tlb; ! 490: target_ulong addr, end; ! 491: ! 492: tlb = &env->tlb[idx]; ! 493: if (tlb->V[0]) { ! 494: addr = tlb->PFN[0]; ! 495: end = addr + (tlb->end - tlb->VPN); ! 496: tb_invalidate_page_range(addr, end); ! 497: } ! 498: if (tlb->V[1]) { ! 499: addr = tlb->PFN[1]; ! 500: end = addr + (tlb->end - tlb->VPN); ! 501: tb_invalidate_page_range(addr, end); ! 502: } ! 503: } ! 504: ! 505: static void fill_tb (int idx) ! 506: { ! 507: tlb_t *tlb; ! 508: int size; ! 509: ! 510: /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ ! 511: tlb = &env->tlb[idx]; ! 512: tlb->VPN = env->CP0_EntryHi & 0xFFFFE000; ! 513: tlb->ASID = env->CP0_EntryHi & 0x000000FF; ! 514: size = env->CP0_PageMask >> 13; ! 515: size = 4 * (size + 1); ! 516: tlb->end = tlb->VPN + (1 << (8 + size)); ! 517: tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; ! 518: tlb->V[0] = env->CP0_EntryLo0 & 2; ! 519: tlb->D[0] = env->CP0_EntryLo0 & 4; ! 520: tlb->C[0] = (env->CP0_EntryLo0 >> 3) & 0x7; ! 521: tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12; ! 522: tlb->V[1] = env->CP0_EntryLo1 & 2; ! 523: tlb->D[1] = env->CP0_EntryLo1 & 4; ! 524: tlb->C[1] = (env->CP0_EntryLo1 >> 3) & 0x7; ! 525: tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12; ! 526: } ! 527: ! 528: void do_tlbwi (void) ! 529: { ! 530: /* Wildly undefined effects for CP0_index containing a too high value and ! 531: MIPS_TLB_NB not being a power of two. But so does real silicon. */ ! 532: invalidate_tb(env->CP0_index & (MIPS_TLB_NB - 1)); ! 533: fill_tb(env->CP0_index & (MIPS_TLB_NB - 1)); ! 534: } ! 535: ! 536: void do_tlbwr (void) ! 537: { ! 538: int r = cpu_mips_get_random(env); ! 539: ! 540: invalidate_tb(r); ! 541: fill_tb(r); ! 542: } ! 543: ! 544: void do_tlbp (void) ! 545: { ! 546: tlb_t *tlb; ! 547: target_ulong tag; ! 548: uint8_t ASID; ! 549: int i; ! 550: ! 551: tag = (env->CP0_EntryHi & 0xFFFFE000); ! 552: ASID = env->CP0_EntryHi & 0x000000FF; ! 553: for (i = 0; i < MIPS_TLB_NB; i++) { ! 554: tlb = &env->tlb[i]; ! 555: /* Check ASID, virtual page number & size */ ! 556: if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) { ! 557: /* TLB match */ ! 558: env->CP0_index = i; ! 559: break; ! 560: } ! 561: } ! 562: if (i == MIPS_TLB_NB) { ! 563: env->CP0_index |= 0x80000000; ! 564: } ! 565: } ! 566: ! 567: void do_tlbr (void) ! 568: { ! 569: tlb_t *tlb; ! 570: int size; ! 571: ! 572: tlb = &env->tlb[env->CP0_index & (MIPS_TLB_NB - 1)]; ! 573: env->CP0_EntryHi = tlb->VPN | tlb->ASID; ! 574: size = (tlb->end - tlb->VPN) >> 12; ! 575: env->CP0_PageMask = (size - 1) << 13; ! 576: env->CP0_EntryLo0 = tlb->V[0] | tlb->D[0] | (tlb->C[0] << 3) | ! 577: (tlb->PFN[0] >> 6); ! 578: env->CP0_EntryLo1 = tlb->V[1] | tlb->D[1] | (tlb->C[1] << 3) | ! 579: (tlb->PFN[1] >> 6); ! 580: } ! 581: #endif ! 582: ! 583: void op_dump_ldst (const unsigned char *func) ! 584: { ! 585: if (loglevel) ! 586: fprintf(logfile, "%s => %08x %08x\n", __func__, T0, T1); ! 587: } ! 588: ! 589: void dump_sc (void) ! 590: { ! 591: if (loglevel) { ! 592: fprintf(logfile, "%s %08x at %08x (%08x)\n", __func__, ! 593: T1, T0, env->CP0_LLAddr); ! 594: } ! 595: } ! 596: ! 597: void debug_eret (void) ! 598: { ! 599: if (loglevel) { ! 600: fprintf(logfile, "ERET: pc %08x EPC %08x ErrorEPC %08x (%d)\n", ! 601: env->PC, env->CP0_EPC, env->CP0_ErrorEPC, ! 602: env->hflags & MIPS_HFLAG_ERL ? 1 : 0); ! 603: } ! 604: } ! 605: ! 606: void do_pmon (int function) ! 607: { ! 608: function /= 2; ! 609: switch (function) { ! 610: case 2: /* TODO: char inbyte(int waitflag); */ ! 611: if (env->gpr[4] == 0) ! 612: env->gpr[2] = -1; ! 613: /* Fall through */ ! 614: case 11: /* TODO: char inbyte (void); */ ! 615: env->gpr[2] = -1; ! 616: break; ! 617: case 3: ! 618: case 12: ! 619: printf("%c", env->gpr[4] & 0xFF); ! 620: break; ! 621: case 17: ! 622: break; ! 623: case 158: ! 624: { ! 625: unsigned char *fmt = (void *)env->gpr[4]; ! 626: printf("%s", fmt); ! 627: } ! 628: break; ! 629: } ! 630: } ! 631: ! 632: #if !defined(CONFIG_USER_ONLY) ! 633: ! 634: #define MMUSUFFIX _mmu ! 635: #define GETPC() (__builtin_return_address(0)) ! 636: ! 637: #define SHIFT 0 ! 638: #include "softmmu_template.h" ! 639: ! 640: #define SHIFT 1 ! 641: #include "softmmu_template.h" ! 642: ! 643: #define SHIFT 2 ! 644: #include "softmmu_template.h" ! 645: ! 646: #define SHIFT 3 ! 647: #include "softmmu_template.h" ! 648: ! 649: void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) ! 650: { ! 651: TranslationBlock *tb; ! 652: CPUState *saved_env; ! 653: unsigned long pc; ! 654: int ret; ! 655: ! 656: /* XXX: hack to restore env in all cases, even if not called from ! 657: generated code */ ! 658: saved_env = env; ! 659: env = cpu_single_env; ! 660: ret = cpu_mips_handle_mmu_fault(env, addr, is_write, is_user, 1); ! 661: if (ret) { ! 662: if (retaddr) { ! 663: /* now we have a real cpu fault */ ! 664: pc = (unsigned long)retaddr; ! 665: tb = tb_find_pc(pc); ! 666: if (tb) { ! 667: /* the PC is inside the translated code. It means that we have ! 668: a virtual CPU fault */ ! 669: cpu_restore_state(tb, env, pc, NULL); ! 670: } ! 671: } ! 672: do_raise_exception_err(env->exception_index, env->error_code); ! 673: } ! 674: env = saved_env; ! 675: } ! 676: ! 677: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.