But there's still the problem of #GP and #SP in real mode. How can the software interrupt differentiate between a normal INT and a hardware interrupt/exception using an error code pushed on the stack in real mode? The stack values can be either with or without error code. So there's no way to differentiate between an IRQ with error code, an INT without error code and an exception(#GP for a segment with offset >0xFFFF), since the CS and IP on the stack can be any value, as well as the error code pushed on the stack. It also cannot be known by the SP pointer, since the SP before the INT(if any) isn't known(only in protected mode when loaded through the TSS).
So how can the software have an IRQ handler(with error code for IRQ, without error code for INT) and #GP handler at the same place? #GP because of a limit break(e.g. MOV 16-bit to address 0xFFFF) cannot be masked, so it's impossible to keep compatible with 808X software?
Edit: I've modified the real mode interrupt handling to not push the error code to the stack anymore(thus, 808X-compatible). It now also checks the IVT against the IDT limit and produces an INT 8(Instead of double fault as well) or triple fault(if the INT 8 fails as well).
Thus the 80286 interrupt problem is solved(using information on the table mentioned earlier). So the (un)real mode has almost no protection. Only the limit checks of segments and IDT(Used as 8086 IVT with base and limit in the IDTR used) still exists(With exceptions 08h(IVT limit) and 0Dh(Segment limit) being used only). There's also exception 09h, which is a ESC segment limit (instead of 0Dh), but since my emulation doesn't have a coprocessor(80287), this shouldn't need to be handled?
Is this correct?