Commit c62db10577295ed4dc26fa9acd6e6f30cea7ffd0
1 parent
636aaad7
Support for PowerPC BookE exception model.
No need to requeue timer exceptions. Fix nip saving for 64 bits PowerPC. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2556 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
92 additions
and
49 deletions
target-ppc/helper.c
@@ -1340,11 +1340,12 @@ void ppc_store_msr_32 (CPUPPCState *env, uint32_t value) | @@ -1340,11 +1340,12 @@ void ppc_store_msr_32 (CPUPPCState *env, uint32_t value) | ||
1340 | void do_compute_hflags (CPUPPCState *env) | 1340 | void do_compute_hflags (CPUPPCState *env) |
1341 | { | 1341 | { |
1342 | /* Compute current hflags */ | 1342 | /* Compute current hflags */ |
1343 | - env->hflags = (msr_pr << MSR_PR) | (msr_le << MSR_LE) | | ||
1344 | - (msr_fp << MSR_FP) | (msr_fe0 << MSR_FE0) | (msr_fe1 << MSR_FE1) | | ||
1345 | - (msr_vr << MSR_VR) | (msr_ap << MSR_AP) | (msr_sa << MSR_SA) | | ||
1346 | - (msr_se << MSR_SE) | (msr_be << MSR_BE); | 1343 | + env->hflags = (msr_cm << MSR_CM) | (msr_vr << MSR_VR) | |
1344 | + (msr_ap << MSR_AP) | (msr_sa << MSR_SA) | (msr_pr << MSR_PR) | | ||
1345 | + (msr_fp << MSR_FP) | (msr_fe0 << MSR_FE0) | (msr_se << MSR_SE) | | ||
1346 | + (msr_be << MSR_BE) | (msr_fe1 << MSR_FE1) | (msr_le << MSR_LE); | ||
1347 | #if defined (TARGET_PPC64) | 1347 | #if defined (TARGET_PPC64) |
1348 | + /* No care here: PowerPC 64 MSR_SF means the same as MSR_CM for BookE */ | ||
1348 | env->hflags |= (msr_sf << (MSR_SF - 32)) | (msr_hv << (MSR_HV - 32)); | 1349 | env->hflags |= (msr_sf << (MSR_SF - 32)) | (msr_hv << (MSR_HV - 32)); |
1349 | #endif | 1350 | #endif |
1350 | } | 1351 | } |
@@ -1374,14 +1375,16 @@ static void dump_syscall(CPUState *env) | @@ -1374,14 +1375,16 @@ static void dump_syscall(CPUState *env) | ||
1374 | 1375 | ||
1375 | void do_interrupt (CPUState *env) | 1376 | void do_interrupt (CPUState *env) |
1376 | { | 1377 | { |
1377 | - target_ulong msr, *srr_0, *srr_1; | ||
1378 | - int excp; | 1378 | + target_ulong msr, *srr_0, *srr_1, *asrr_0, *asrr_1; |
1379 | + int excp, idx; | ||
1379 | 1380 | ||
1380 | excp = env->exception_index; | 1381 | excp = env->exception_index; |
1381 | msr = do_load_msr(env); | 1382 | msr = do_load_msr(env); |
1382 | /* The default is to use SRR0 & SRR1 to save the exception context */ | 1383 | /* The default is to use SRR0 & SRR1 to save the exception context */ |
1383 | srr_0 = &env->spr[SPR_SRR0]; | 1384 | srr_0 = &env->spr[SPR_SRR0]; |
1384 | srr_1 = &env->spr[SPR_SRR1]; | 1385 | srr_1 = &env->spr[SPR_SRR1]; |
1386 | + asrr_0 = NULL; | ||
1387 | + asrr_1 = NULL; | ||
1385 | #if defined (DEBUG_EXCEPTIONS) | 1388 | #if defined (DEBUG_EXCEPTIONS) |
1386 | if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1) { | 1389 | if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1) { |
1387 | if (loglevel != 0) { | 1390 | if (loglevel != 0) { |
@@ -1397,26 +1400,44 @@ void do_interrupt (CPUState *env) | @@ -1397,26 +1400,44 @@ void do_interrupt (CPUState *env) | ||
1397 | env->nip, excp, env->error_code); | 1400 | env->nip, excp, env->error_code); |
1398 | } | 1401 | } |
1399 | msr_pow = 0; | 1402 | msr_pow = 0; |
1403 | + idx = -1; | ||
1400 | /* Generate informations in save/restore registers */ | 1404 | /* Generate informations in save/restore registers */ |
1401 | switch (excp) { | 1405 | switch (excp) { |
1402 | /* Generic PowerPC exceptions */ | 1406 | /* Generic PowerPC exceptions */ |
1403 | case EXCP_RESET: /* 0x0100 */ | 1407 | case EXCP_RESET: /* 0x0100 */ |
1404 | - if (PPC_EXCP(env) != PPC_FLAGS_EXCP_40x) { | 1408 | + switch (PPC_EXCP(env)) { |
1409 | + case PPC_FLAGS_EXCP_40x: | ||
1410 | + srr_0 = &env->spr[SPR_40x_SRR2]; | ||
1411 | + srr_1 = &env->spr[SPR_40x_SRR3]; | ||
1412 | + break; | ||
1413 | + case PPC_FLAGS_EXCP_BOOKE: | ||
1414 | + idx = 0; | ||
1415 | + srr_0 = &env->spr[SPR_BOOKE_CSRR0]; | ||
1416 | + srr_1 = &env->spr[SPR_BOOKE_CSRR1]; | ||
1417 | + break; | ||
1418 | + default: | ||
1405 | if (msr_ip) | 1419 | if (msr_ip) |
1406 | excp += 0xFFC00; | 1420 | excp += 0xFFC00; |
1407 | excp |= 0xFFC00000; | 1421 | excp |= 0xFFC00000; |
1408 | - } else { | ||
1409 | - srr_0 = &env->spr[SPR_40x_SRR2]; | ||
1410 | - srr_1 = &env->spr[SPR_40x_SRR3]; | 1422 | + break; |
1411 | } | 1423 | } |
1412 | goto store_next; | 1424 | goto store_next; |
1413 | case EXCP_MACHINE_CHECK: /* 0x0200 */ | 1425 | case EXCP_MACHINE_CHECK: /* 0x0200 */ |
1414 | - if (msr_me == 0) { | ||
1415 | - cpu_abort(env, "Machine check exception while not allowed\n"); | ||
1416 | - } | ||
1417 | - if (unlikely(PPC_EXCP(env) == PPC_FLAGS_EXCP_40x)) { | 1426 | + switch (PPC_EXCP(env)) { |
1427 | + case PPC_FLAGS_EXCP_40x: | ||
1418 | srr_0 = &env->spr[SPR_40x_SRR2]; | 1428 | srr_0 = &env->spr[SPR_40x_SRR2]; |
1419 | srr_1 = &env->spr[SPR_40x_SRR3]; | 1429 | srr_1 = &env->spr[SPR_40x_SRR3]; |
1430 | + break; | ||
1431 | + case PPC_FLAGS_EXCP_BOOKE: | ||
1432 | + idx = 1; | ||
1433 | + srr_0 = &env->spr[SPR_BOOKE_MCSRR0]; | ||
1434 | + srr_1 = &env->spr[SPR_BOOKE_MCSRR1]; | ||
1435 | + asrr_0 = &env->spr[SPR_BOOKE_CSRR0]; | ||
1436 | + asrr_1 = &env->spr[SPR_BOOKE_CSRR1]; | ||
1437 | + msr_ce = 0; | ||
1438 | + break; | ||
1439 | + default: | ||
1440 | + break; | ||
1420 | } | 1441 | } |
1421 | msr_me = 0; | 1442 | msr_me = 0; |
1422 | break; | 1443 | break; |
@@ -1425,6 +1446,7 @@ void do_interrupt (CPUState *env) | @@ -1425,6 +1446,7 @@ void do_interrupt (CPUState *env) | ||
1425 | /* data location address has been stored | 1446 | /* data location address has been stored |
1426 | * when the fault has been detected | 1447 | * when the fault has been detected |
1427 | */ | 1448 | */ |
1449 | + idx = 2; | ||
1428 | msr &= ~0xFFFF0000; | 1450 | msr &= ~0xFFFF0000; |
1429 | #if defined (DEBUG_EXCEPTIONS) | 1451 | #if defined (DEBUG_EXCEPTIONS) |
1430 | if (loglevel) { | 1452 | if (loglevel) { |
@@ -1438,6 +1460,7 @@ void do_interrupt (CPUState *env) | @@ -1438,6 +1460,7 @@ void do_interrupt (CPUState *env) | ||
1438 | goto store_next; | 1460 | goto store_next; |
1439 | case EXCP_ISI: /* 0x0400 */ | 1461 | case EXCP_ISI: /* 0x0400 */ |
1440 | /* Store exception cause */ | 1462 | /* Store exception cause */ |
1463 | + idx = 3; | ||
1441 | msr &= ~0xFFFF0000; | 1464 | msr &= ~0xFFFF0000; |
1442 | msr |= env->error_code; | 1465 | msr |= env->error_code; |
1443 | #if defined (DEBUG_EXCEPTIONS) | 1466 | #if defined (DEBUG_EXCEPTIONS) |
@@ -1448,20 +1471,12 @@ void do_interrupt (CPUState *env) | @@ -1448,20 +1471,12 @@ void do_interrupt (CPUState *env) | ||
1448 | #endif | 1471 | #endif |
1449 | goto store_next; | 1472 | goto store_next; |
1450 | case EXCP_EXTERNAL: /* 0x0500 */ | 1473 | case EXCP_EXTERNAL: /* 0x0500 */ |
1451 | - if (msr_ee == 0) { | ||
1452 | -#if defined (DEBUG_EXCEPTIONS) | ||
1453 | - if (loglevel > 0) { | ||
1454 | - fprintf(logfile, "Skipping hardware interrupt\n"); | ||
1455 | - } | ||
1456 | -#endif | ||
1457 | - /* Requeue it */ | ||
1458 | - env->interrupt_request |= CPU_INTERRUPT_HARD; | ||
1459 | - return; | ||
1460 | - } | 1474 | + idx = 4; |
1461 | goto store_next; | 1475 | goto store_next; |
1462 | case EXCP_ALIGN: /* 0x0600 */ | 1476 | case EXCP_ALIGN: /* 0x0600 */ |
1463 | if (likely(PPC_EXCP(env) != PPC_FLAGS_EXCP_601)) { | 1477 | if (likely(PPC_EXCP(env) != PPC_FLAGS_EXCP_601)) { |
1464 | /* Store exception cause */ | 1478 | /* Store exception cause */ |
1479 | + idx = 5; | ||
1465 | /* Get rS/rD and rA from faulting opcode */ | 1480 | /* Get rS/rD and rA from faulting opcode */ |
1466 | env->spr[SPR_DSISR] |= | 1481 | env->spr[SPR_DSISR] |= |
1467 | (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16; | 1482 | (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16; |
@@ -1476,6 +1491,7 @@ void do_interrupt (CPUState *env) | @@ -1476,6 +1491,7 @@ void do_interrupt (CPUState *env) | ||
1476 | } | 1491 | } |
1477 | goto store_current; | 1492 | goto store_current; |
1478 | case EXCP_PROGRAM: /* 0x0700 */ | 1493 | case EXCP_PROGRAM: /* 0x0700 */ |
1494 | + idx = 6; | ||
1479 | msr &= ~0xFFFF0000; | 1495 | msr &= ~0xFFFF0000; |
1480 | switch (env->error_code & ~0xF) { | 1496 | switch (env->error_code & ~0xF) { |
1481 | case EXCP_FP: | 1497 | case EXCP_FP: |
@@ -1501,6 +1517,7 @@ void do_interrupt (CPUState *env) | @@ -1501,6 +1517,7 @@ void do_interrupt (CPUState *env) | ||
1501 | msr |= 0x00040000; | 1517 | msr |= 0x00040000; |
1502 | break; | 1518 | break; |
1503 | case EXCP_TRAP: | 1519 | case EXCP_TRAP: |
1520 | + idx = 15; | ||
1504 | msr |= 0x00020000; | 1521 | msr |= 0x00020000; |
1505 | break; | 1522 | break; |
1506 | default: | 1523 | default: |
@@ -1510,18 +1527,13 @@ void do_interrupt (CPUState *env) | @@ -1510,18 +1527,13 @@ void do_interrupt (CPUState *env) | ||
1510 | msr |= 0x00010000; | 1527 | msr |= 0x00010000; |
1511 | goto store_current; | 1528 | goto store_current; |
1512 | case EXCP_NO_FP: /* 0x0800 */ | 1529 | case EXCP_NO_FP: /* 0x0800 */ |
1530 | + idx = 7; | ||
1513 | msr &= ~0xFFFF0000; | 1531 | msr &= ~0xFFFF0000; |
1514 | goto store_current; | 1532 | goto store_current; |
1515 | case EXCP_DECR: | 1533 | case EXCP_DECR: |
1516 | - if (msr_ee == 0) { | ||
1517 | -#if 1 | ||
1518 | - /* Requeue it */ | ||
1519 | - env->interrupt_request |= CPU_INTERRUPT_TIMER; | ||
1520 | -#endif | ||
1521 | - return; | ||
1522 | - } | ||
1523 | goto store_next; | 1534 | goto store_next; |
1524 | case EXCP_SYSCALL: /* 0x0C00 */ | 1535 | case EXCP_SYSCALL: /* 0x0C00 */ |
1536 | + idx = 8; | ||
1525 | /* NOTE: this is a temporary hack to support graphics OSI | 1537 | /* NOTE: this is a temporary hack to support graphics OSI |
1526 | calls from the MOL driver */ | 1538 | calls from the MOL driver */ |
1527 | if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b && | 1539 | if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b && |
@@ -1557,13 +1569,6 @@ void do_interrupt (CPUState *env) | @@ -1557,13 +1569,6 @@ void do_interrupt (CPUState *env) | ||
1557 | "Instruction segment exception is not implemented yet !\n"); | 1569 | "Instruction segment exception is not implemented yet !\n"); |
1558 | goto store_next; | 1570 | goto store_next; |
1559 | case EXCP_HDECR: /* 0x0980 */ | 1571 | case EXCP_HDECR: /* 0x0980 */ |
1560 | - if (msr_ee == 0) { | ||
1561 | -#if 1 | ||
1562 | - /* Requeue it */ | ||
1563 | - env->interrupt_request |= CPU_INTERRUPT_TIMER; | ||
1564 | -#endif | ||
1565 | - return; | ||
1566 | - } | ||
1567 | /* XXX: TODO */ | 1572 | /* XXX: TODO */ |
1568 | cpu_abort(env, "Hypervisor decrementer exception is not implemented " | 1573 | cpu_abort(env, "Hypervisor decrementer exception is not implemented " |
1569 | "yet !\n"); | 1574 | "yet !\n"); |
@@ -1581,6 +1586,7 @@ void do_interrupt (CPUState *env) | @@ -1581,6 +1586,7 @@ void do_interrupt (CPUState *env) | ||
1581 | } | 1586 | } |
1582 | return; | 1587 | return; |
1583 | case 0x0F20: | 1588 | case 0x0F20: |
1589 | + idx = 9; | ||
1584 | switch (PPC_EXCP(env)) { | 1590 | switch (PPC_EXCP(env)) { |
1585 | case PPC_FLAGS_EXCP_40x: | 1591 | case PPC_FLAGS_EXCP_40x: |
1586 | /* APU unavailable on 405 */ | 1592 | /* APU unavailable on 405 */ |
@@ -1600,11 +1606,13 @@ void do_interrupt (CPUState *env) | @@ -1600,11 +1606,13 @@ void do_interrupt (CPUState *env) | ||
1600 | } | 1606 | } |
1601 | return; | 1607 | return; |
1602 | case 0x1000: | 1608 | case 0x1000: |
1609 | + idx = 10; | ||
1603 | switch (PPC_EXCP(env)) { | 1610 | switch (PPC_EXCP(env)) { |
1604 | case PPC_FLAGS_EXCP_40x: | 1611 | case PPC_FLAGS_EXCP_40x: |
1605 | /* PIT on 4xx */ | 1612 | /* PIT on 4xx */ |
1606 | - /* XXX: TODO */ | ||
1607 | - cpu_abort(env, "40x PIT exception is not implemented yet !\n"); | 1613 | + msr &= ~0xFFFF0000; |
1614 | + if (loglevel != 0) | ||
1615 | + fprintf(logfile, "PIT exception\n"); | ||
1608 | goto store_next; | 1616 | goto store_next; |
1609 | case PPC_FLAGS_EXCP_602: | 1617 | case PPC_FLAGS_EXCP_602: |
1610 | case PPC_FLAGS_EXCP_603: | 1618 | case PPC_FLAGS_EXCP_603: |
@@ -1619,11 +1627,13 @@ void do_interrupt (CPUState *env) | @@ -1619,11 +1627,13 @@ void do_interrupt (CPUState *env) | ||
1619 | } | 1627 | } |
1620 | return; | 1628 | return; |
1621 | case 0x1010: | 1629 | case 0x1010: |
1630 | + idx = 11; | ||
1622 | switch (PPC_EXCP(env)) { | 1631 | switch (PPC_EXCP(env)) { |
1623 | case PPC_FLAGS_EXCP_40x: | 1632 | case PPC_FLAGS_EXCP_40x: |
1624 | /* FIT on 4xx */ | 1633 | /* FIT on 4xx */ |
1625 | - /* XXX: TODO */ | ||
1626 | - cpu_abort(env, "40x FIT exception is not implemented yet !\n"); | 1634 | + msr &= ~0xFFFF0000; |
1635 | + if (loglevel != 0) | ||
1636 | + fprintf(logfile, "FIT exception\n"); | ||
1627 | goto store_next; | 1637 | goto store_next; |
1628 | default: | 1638 | default: |
1629 | cpu_abort(env, "Invalid exception 0x1010 !\n"); | 1639 | cpu_abort(env, "Invalid exception 0x1010 !\n"); |
@@ -1631,19 +1641,25 @@ void do_interrupt (CPUState *env) | @@ -1631,19 +1641,25 @@ void do_interrupt (CPUState *env) | ||
1631 | } | 1641 | } |
1632 | return; | 1642 | return; |
1633 | case 0x1020: | 1643 | case 0x1020: |
1644 | + idx = 12; | ||
1634 | switch (PPC_EXCP(env)) { | 1645 | switch (PPC_EXCP(env)) { |
1635 | case PPC_FLAGS_EXCP_40x: | 1646 | case PPC_FLAGS_EXCP_40x: |
1636 | /* Watchdog on 4xx */ | 1647 | /* Watchdog on 4xx */ |
1637 | - /* XXX: TODO */ | ||
1638 | - cpu_abort(env, | ||
1639 | - "40x watchdog exception is not implemented yet !\n"); | 1648 | + msr &= ~0xFFFF0000; |
1649 | + if (loglevel != 0) | ||
1650 | + fprintf(logfile, "WDT exception\n"); | ||
1640 | goto store_next; | 1651 | goto store_next; |
1652 | + case PPC_FLAGS_EXCP_BOOKE: | ||
1653 | + srr_0 = &env->spr[SPR_BOOKE_CSRR0]; | ||
1654 | + srr_1 = &env->spr[SPR_BOOKE_CSRR1]; | ||
1655 | + break; | ||
1641 | default: | 1656 | default: |
1642 | cpu_abort(env, "Invalid exception 0x1020 !\n"); | 1657 | cpu_abort(env, "Invalid exception 0x1020 !\n"); |
1643 | break; | 1658 | break; |
1644 | } | 1659 | } |
1645 | return; | 1660 | return; |
1646 | case 0x1100: | 1661 | case 0x1100: |
1662 | + idx = 13; | ||
1647 | switch (PPC_EXCP(env)) { | 1663 | switch (PPC_EXCP(env)) { |
1648 | case PPC_FLAGS_EXCP_40x: | 1664 | case PPC_FLAGS_EXCP_40x: |
1649 | /* DTLBMISS on 4xx */ | 1665 | /* DTLBMISS on 4xx */ |
@@ -1662,6 +1678,7 @@ void do_interrupt (CPUState *env) | @@ -1662,6 +1678,7 @@ void do_interrupt (CPUState *env) | ||
1662 | } | 1678 | } |
1663 | return; | 1679 | return; |
1664 | case 0x1200: | 1680 | case 0x1200: |
1681 | + idx = 14; | ||
1665 | switch (PPC_EXCP(env)) { | 1682 | switch (PPC_EXCP(env)) { |
1666 | case PPC_FLAGS_EXCP_40x: | 1683 | case PPC_FLAGS_EXCP_40x: |
1667 | /* ITLBMISS on 4xx */ | 1684 | /* ITLBMISS on 4xx */ |
@@ -1838,6 +1855,10 @@ void do_interrupt (CPUState *env) | @@ -1838,6 +1855,10 @@ void do_interrupt (CPUState *env) | ||
1838 | cpu_abort(env, | 1855 | cpu_abort(env, |
1839 | "601 run mode exception is not implemented yet !\n"); | 1856 | "601 run mode exception is not implemented yet !\n"); |
1840 | goto store_next; | 1857 | goto store_next; |
1858 | + case PPC_FLAGS_EXCP_BOOKE: | ||
1859 | + srr_0 = &env->spr[SPR_BOOKE_CSRR0]; | ||
1860 | + srr_1 = &env->spr[SPR_BOOKE_CSRR1]; | ||
1861 | + break; | ||
1841 | default: | 1862 | default: |
1842 | cpu_abort(env, "Invalid exception 0x1800 !\n"); | 1863 | cpu_abort(env, "Invalid exception 0x1800 !\n"); |
1843 | break; | 1864 | break; |
@@ -1852,15 +1873,19 @@ void do_interrupt (CPUState *env) | @@ -1852,15 +1873,19 @@ void do_interrupt (CPUState *env) | ||
1852 | return; | 1873 | return; |
1853 | store_current: | 1874 | store_current: |
1854 | /* save current instruction location */ | 1875 | /* save current instruction location */ |
1855 | - *srr_0 = (env->nip - 4) & 0xFFFFFFFFULL; | 1876 | + *srr_0 = env->nip - 4; |
1856 | break; | 1877 | break; |
1857 | store_next: | 1878 | store_next: |
1858 | /* save next instruction location */ | 1879 | /* save next instruction location */ |
1859 | - *srr_0 = env->nip & 0xFFFFFFFFULL; | 1880 | + *srr_0 = env->nip; |
1860 | break; | 1881 | break; |
1861 | } | 1882 | } |
1862 | /* Save msr */ | 1883 | /* Save msr */ |
1863 | *srr_1 = msr; | 1884 | *srr_1 = msr; |
1885 | + if (asrr_0 != NULL) | ||
1886 | + *asrr_0 = *srr_0; | ||
1887 | + if (asrr_1 != NULL) | ||
1888 | + *asrr_1 = *srr_1; | ||
1864 | /* If we disactivated any translation, flush TLBs */ | 1889 | /* If we disactivated any translation, flush TLBs */ |
1865 | if (msr_ir || msr_dr) { | 1890 | if (msr_ir || msr_dr) { |
1866 | tlb_flush(env, 1); | 1891 | tlb_flush(env, 1); |
@@ -1877,10 +1902,28 @@ void do_interrupt (CPUState *env) | @@ -1877,10 +1902,28 @@ void do_interrupt (CPUState *env) | ||
1877 | msr_dr = 0; | 1902 | msr_dr = 0; |
1878 | msr_ri = 0; | 1903 | msr_ri = 0; |
1879 | msr_le = msr_ile; | 1904 | msr_le = msr_ile; |
1880 | - msr_sf = msr_isf; | 1905 | + if (PPC_EXCP(env) == PPC_FLAGS_EXCP_BOOKE) { |
1906 | + msr_cm = msr_icm; | ||
1907 | + if (idx == -1 || (idx >= 16 && idx < 32)) { | ||
1908 | + cpu_abort(env, "Invalid exception index for excp %d %08x idx %d\n", | ||
1909 | + excp, excp, idx); | ||
1910 | + } | ||
1911 | +#if defined(TARGET_PPC64) | ||
1912 | + if (msr_cm) | ||
1913 | + env->nip = (uint64_t)env->spr[SPR_BOOKE_IVPR]; | ||
1914 | + else | ||
1915 | +#endif | ||
1916 | + env->nip = (uint32_t)env->spr[SPR_BOOKE_IVPR]; | ||
1917 | + if (idx < 16) | ||
1918 | + env->nip |= env->spr[SPR_BOOKE_IVOR0 + idx]; | ||
1919 | + else if (idx < 38) | ||
1920 | + env->nip |= env->spr[SPR_BOOKE_IVOR32 + idx - 32]; | ||
1921 | + } else { | ||
1922 | + msr_sf = msr_isf; | ||
1923 | + env->nip = excp; | ||
1924 | + } | ||
1881 | do_compute_hflags(env); | 1925 | do_compute_hflags(env); |
1882 | /* Jump to handler */ | 1926 | /* Jump to handler */ |
1883 | - env->nip = excp; | ||
1884 | env->exception_index = EXCP_NONE; | 1927 | env->exception_index = EXCP_NONE; |
1885 | } | 1928 | } |
1886 | 1929 |