Common Source Code Project for Qt (a.k.a for FM-7).
Revision | b4fa03bb94a9af4b7438d04da689067c93c7c652 (tree) |
---|---|
Zeit | 2019-04-09 20:07:44 |
Autor | K.Ohta <whatisthis.sowhat@gmai...> |
Commiter | K.Ohta |
[VM][I386][WIP] FLAGS around IRET/POPF/POPFD.This is WIP.
@@ -2451,7 +2451,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32) | ||
2451 | 2451 | UINT8 CPL, RPL, DPL; |
2452 | 2452 | UINT32 newflags; |
2453 | 2453 | UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1); |
2454 | - | |
2454 | + UINT32 stack_size = 6; | |
2455 | 2455 | CPL = cpustate->CPL; |
2456 | 2456 | UINT32 ea = i386_translate(cpustate, SS, (STACK_32BIT)?REG32(ESP):REG16(SP), 0, (operand32)?12:6); |
2457 | 2457 | if(operand32 == 0) |
@@ -2459,12 +2459,14 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32) | ||
2459 | 2459 | newEIP = READ16(cpustate, ea) & 0xffff; |
2460 | 2460 | newCS = READ16(cpustate, ea+2) & 0xffff; |
2461 | 2461 | newflags = READ16(cpustate, ea+4) & 0xffff; |
2462 | + stack_size = 6; | |
2462 | 2463 | } |
2463 | 2464 | else |
2464 | 2465 | { |
2465 | 2466 | newEIP = READ32(cpustate, ea); |
2466 | 2467 | newCS = READ32(cpustate, ea+4) & 0xffff; |
2467 | 2468 | newflags = READ32(cpustate, ea+8); |
2469 | + stack_size = 12; | |
2468 | 2470 | } |
2469 | 2471 | |
2470 | 2472 | if(V8086_MODE) |
@@ -2489,9 +2491,9 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32) | ||
2489 | 2491 | newflags |= (oldflags & I386_EFLAGS_IOPL); |
2490 | 2492 | set_flags(cpustate,(newflags & 0xffff) | (oldflags & ~0xffff)); |
2491 | 2493 | if(STACK_32BIT) { |
2492 | - REG32(ESP) += 6; | |
2494 | + REG32(ESP) += stack_size; | |
2493 | 2495 | } else { |
2494 | - REG16(SP) += 6; | |
2496 | + REG16(SP) += stack_size; | |
2495 | 2497 | } |
2496 | 2498 | } |
2497 | 2499 | else |
@@ -2508,9 +2510,9 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32) | ||
2508 | 2510 | newflags |= (oldflags & I386_EFLAGS_IOPL) | I386_EFLAGS_VM; |
2509 | 2511 | set_flags(cpustate,newflags); |
2510 | 2512 | if(STACK_32BIT) { |
2511 | - REG32(ESP) += 12; | |
2513 | + REG32(ESP) += stack_size; | |
2512 | 2514 | } else { |
2513 | - REG16(SP) += 12; | |
2515 | + REG16(SP) += stack_size; | |
2514 | 2516 | } |
2515 | 2517 | } |
2516 | 2518 |
@@ -2552,7 +2554,7 @@ static void i386_protected_mode_iret(i386_state* cpustate, int operand32) | ||
2552 | 2554 | } |
2553 | 2555 | else |
2554 | 2556 | { |
2555 | - if(newflags & 0x00020000) // if returning to virtual 8086 mode | |
2557 | + if((newflags & 0x00020000) && (cpustate->CPL == 0)) // if returning to virtual 8086 mode | |
2556 | 2558 | { |
2557 | 2559 | // 16-bit iret can't reach here |
2558 | 2560 | newESP = READ32(cpustate, ea+12); |
@@ -1744,18 +1744,18 @@ static void I386OP(popf)(i386_state *cpustate) // Opcode 0x9d | ||
1744 | 1744 | UINT32 value; |
1745 | 1745 | UINT32 current = get_flags(cpustate); |
1746 | 1746 | UINT8 IOPL = (current >> 12) & 0x03; |
1747 | - UINT32 mask = 0x7fd5; | |
1747 | + //UINT32 mask = 0x7fd5; | |
1748 | + UINT32 mask = I386_EFLAGS_IF | I386_EFLAGS_IOPL | I386_EFLAGS_SZAPC | I386_EFLAGS_T | I386_EFLAGS_D | I386_EFLAGS_O | I386_EFLAGS_NT /*| I386_EFLAGS_AC | I386_EFLAGS_ID*/; | |
1748 | 1749 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
1749 | 1750 | |
1751 | +#if 1 | |
1750 | 1752 | // IOPL can only change if CPL is 0 |
1751 | 1753 | if(cpustate->CPL != 0) { |
1752 | - //mask &= ~0x00003000; | |
1753 | 1754 | mask &= ~I386_EFLAGS_IOPL; |
1754 | 1755 | } |
1755 | 1756 | |
1756 | 1757 | // IF can only change if CPL is at least as privileged as IOPL |
1757 | 1758 | if(cpustate->CPL > IOPL) { |
1758 | - //mask &= ~0x00000200; | |
1759 | 1759 | mask &= ~I386_EFLAGS_IF; |
1760 | 1760 | } |
1761 | 1761 |
@@ -1766,10 +1766,30 @@ static void I386OP(popf)(i386_state *cpustate) // Opcode 0x9d | ||
1766 | 1766 | logerror("POPFD(%08x): IOPL < 3 while in V86 mode.\n",cpustate->pc); |
1767 | 1767 | FAULT(FAULT_GP,0) // #GP(0) |
1768 | 1768 | } |
1769 | - //mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode | |
1770 | 1769 | mask &= ~I386_EFLAGS_IOPL; // IOPL cannot be changed while in V8086 mode |
1771 | 1770 | } |
1772 | - | |
1771 | +#else | |
1772 | + // Port from NP2 | |
1773 | + if(!(PROTECTED_MODE)) { | |
1774 | + mask |= (I386_EFLAGS_IF | I386_EFLAGS_IOPL); | |
1775 | + } else if(!(V8086_MODE)) { | |
1776 | + | |
1777 | + if(cpustate->CPL == 0) { | |
1778 | + mask |= (I386_EFLAGS_IF | I386_EFLAGS_IOPL); | |
1779 | + } else if(cpustate->CPL <= IOPL) { | |
1780 | + mask |= I386_EFLAGS_IF; | |
1781 | + } | |
1782 | + } else if(IOPL == 3) { | |
1783 | + mask |= I386_EFLAGS_IF; | |
1784 | + } else { | |
1785 | + mask = 0; | |
1786 | + logerror("POPF(%08x): Wrong mode and IOPL.PC=%08X\n",cpustate->pc); | |
1787 | + FAULT(FAULT_GP,0); // #GP(0) | |
1788 | + set_flags(cpustate,current); // mask out reserved bits | |
1789 | + return; | |
1790 | + } | |
1791 | +#endif | |
1792 | + | |
1773 | 1793 | if(i386_limit_check(cpustate,SS,offset,2) == 0) |
1774 | 1794 | { |
1775 | 1795 | value = POP16(cpustate); |
@@ -2024,7 +2044,7 @@ static void I386OP(pushf)(i386_state *cpustate) // Opcode 0x9c | ||
2024 | 2044 | offset = (REG16(SP) - 2) & 0xffff; |
2025 | 2045 | if(!PROTECTED_MODE || !V8086_MODE || ((cpustate->IOP1) && (cpustate->IOP2))) { |
2026 | 2046 | if(i386_limit_check(cpustate,SS,offset,2) == 0) |
2027 | - PUSH16(cpustate, get_flags(cpustate) & 0xffff ); | |
2047 | + PUSH16(cpustate, (get_flags(cpustate) & 0xffff) | 0x0002 ); | |
2028 | 2048 | else |
2029 | 2049 | FAULT(FAULT_SS,0) |
2030 | 2050 | } else { |
@@ -1572,19 +1572,20 @@ static void I386OP(popfd)(i386_state *cpustate) // Opcode 0x9d | ||
1572 | 1572 | { |
1573 | 1573 | UINT32 value; |
1574 | 1574 | UINT32 current = get_flags(cpustate); |
1575 | + UINT32 expect_flags = 0xffffffff; | |
1575 | 1576 | UINT8 IOPL = (current >> 12) & 0x03; |
1577 | + //UINT32 mask = I386_EFLAGS_SZAPC | I386_EFLAGS_T | I386_EFLAGS_D | I386_EFLAGS_O | I386_EFLAGS_NT | I386_EFLAGS_AC | I386_EFLAGS_ID; | |
1576 | 1578 | UINT32 mask = 0x00257fd5; // VM, VIP and VIF cannot be set by POPF/POPFD |
1577 | 1579 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
1578 | 1580 | |
1579 | 1581 | // IOPL can only change if CPL is 0 |
1582 | +#if 1 | |
1580 | 1583 | if(cpustate->CPL != 0) { |
1581 | - //mask &= ~0x00003000; | |
1582 | 1584 | mask &= ~I386_EFLAGS_IOPL; |
1583 | 1585 | } |
1584 | 1586 | // IF can only change if CPL is at least as privileged as IOPL |
1585 | 1587 | if(cpustate->CPL > IOPL) { |
1586 | 1588 | mask &= ~I386_EFLAGS_IF; |
1587 | - //mask &= ~0x00000200; | |
1588 | 1589 | } |
1589 | 1590 | |
1590 | 1591 | if(V8086_MODE) |
@@ -1596,19 +1597,34 @@ static void I386OP(popfd)(i386_state *cpustate) // Opcode 0x9d | ||
1596 | 1597 | //set_flags(cpustate,0 ); // EXCEPTION |
1597 | 1598 | } |
1598 | 1599 | mask &= ~I386_EFLAGS_IOPL; // IOPL cannot be changed while in V8086 mode |
1599 | - //mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode | |
1600 | 1600 | } |
1601 | - | |
1601 | +#else | |
1602 | + if(!(PROTECTED_MODE)) { | |
1603 | + expect_flags = ~(I386_EFLAGS_RF | I386_EFLAGS_VIF | I386_EFLAGS_VIP); | |
1604 | + mask |= I386_EFLAGS_IF | I386_EFLAGS_IOP1 | I386_EFLAGS_IOP2 | I386_EFLAGS_RF | I386_EFLAGS_VIP | I386_EFLAGS_VIF; | |
1605 | + } else if(!(V8086_MODE)) { | |
1606 | + expect_flags = ~(I386_EFLAGS_RF); | |
1607 | + if(cpustate->CPL == 0) { | |
1608 | + expect_flags &= ~(I386_EFLAGS_VIP | I386_EFLAGS_VIF); | |
1609 | + mask |= I386_EFLAGS_IF | I386_EFLAGS_IOP1 | I386_EFLAGS_IOP2 | I386_EFLAGS_RF | I386_EFLAGS_VIP | I386_EFLAGS_VIF; | |
1610 | + } else if(cpustate->CPL <= IOPL) { | |
1611 | + expect_flags &= ~(I386_EFLAGS_VIP | I386_EFLAGS_VIF); | |
1612 | + mask |= I386_EFLAGS_IF | I386_EFLAGS_RF | I386_EFLAGS_VIP | I386_EFLAGS_VIF; | |
1613 | + } else { | |
1614 | + mask |= I386_EFLAGS_RF; | |
1615 | + } | |
1616 | + } else if(IOPL == 3) { | |
1617 | + mask |= I386_EFLAGS_IF; | |
1618 | + } else { | |
1619 | + FAULT(FAULT_GP, 0); | |
1620 | + set_flags(cpustate,current); // mask out reserved bits | |
1621 | + return; | |
1622 | + } | |
1623 | +#endif | |
1602 | 1624 | if(i386_limit_check(cpustate,SS,offset,4) == 0) |
1603 | 1625 | { |
1604 | 1626 | value = POP32(cpustate); |
1605 | - //value &= ~0x00010000; // RF will always return zero | |
1606 | - if(!V8086_MODE) { // RF maybe clear only not V86 mode | |
1607 | - value &= ~I386_EFLAGS_RF; | |
1608 | - if((cpustate->CPL == 0) || (cpustate->CPL <= IOPL)) { | |
1609 | - value &= ~(I386_EFLAGS_VIF | I386_EFLAGS_VIP); // RF will always return zero | |
1610 | - } | |
1611 | - } | |
1627 | + value = value & expect_flags; | |
1612 | 1628 | set_flags(cpustate,(current & ~mask) | (value & mask)); // mask out reserved bits |
1613 | 1629 | } |
1614 | 1630 | else |
@@ -1862,7 +1878,7 @@ static void I386OP(pushfd)(i386_state *cpustate) // Opcode 0x9c | ||
1862 | 1878 | offset = (REG16(SP) - 4) & 0xffff; |
1863 | 1879 | if(!PROTECTED_MODE || !V8086_MODE || ((cpustate->IOP1) && (cpustate->IOP2))) { |
1864 | 1880 | if(i386_limit_check(cpustate,SS,offset,4) == 0) |
1865 | - PUSH32(cpustate, get_flags(cpustate) & 0x00fcffff ); | |
1881 | + PUSH32(cpustate, (get_flags(cpustate) & 0x00fcffff) | 0x00000002 ); | |
1866 | 1882 | else |
1867 | 1883 | FAULT(FAULT_SS,0) |
1868 | 1884 | } else { |