@R.Belmont: it is documented (somehow) in
src\devices\cpu\i86\i86.txt
The section reads:
early 8086/8088 revisions bug
-----------------------------
(copyright 1978 on package)
mov sreg, does not disable IRQ until next operation is executed <---
(The last sentence is garbled and broken in my version, so it should be corrected)
Here is my proposition for a patch (please review):
LINE 145:
/* Dispatch IRQ */
if ( m_pending_irq && (m_no_interrupt == 0) )
{
if ( m_pending_irq & NMI_IRQ )
{
interrupt(I8086_NMI_INT_VECTOR);
m_pending_irq &= ~NMI_IRQ;
}
else if ( m_IF )
{
/* the actual vector is retrieved after pushing flags */
/* and clearing the IF */
interrupt(-1);
}
}
/* Trap should allow one instruction to be executed.
CPUID.ASM (by Bob Smith, 1985) suggests that in situations where m_no_interrupt is 1,
(directly after POP SS / MOV_SREG), single step IRQs don't fire.
*/
if (m_fire_trap )
{
if ( (m_fire_trap >= 2) && (m_no_interrupt == 0) )
{
m_fire_trap = 0; // reset trap flag upon entry
interrupt(1);
}
else
{
m_fire_trap++;
}
}
/* No interrupt allowed between last instruction and this one */
if ( m_no_interrupt )
{
m_no_interrupt--;
}
}
...
~ LINE 696 (already corrected):
case 0x17: // i_pop_ss
m_sregs[SS] = POP();
CLK(POP_SEG);
m_no_interrupt = 1;
break;
...
~ LINE 1406:
case 0x8e: // i_mov_sregw
m_modrm = fetch();
m_src = GetRMWord();
m_sregs[(m_modrm & 0x18) >> 3] = m_src; // confirmed on hw: modrm bit 5 ignored
CLKM(MOV_SR,MOV_SM);
m_no_interrupt = 1; // Disable IRQ after load segment register. Let's not emulate CPU bugs.
break;
Source and binary for CPUID.COM may be downloaded from the links above for testing purposes.