VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

I notice that various MS-DOS games crash with a DIV0 exception when starting(CheckIt Diagnostics 3.0 and WhatVGA(directly after displaying PCI bus devices detected)). This issue doesn't happen when running any V86 monitor(e.g. EMM386 or Windows 3.x/95), where they run without visible issues.
Anyone knows what might be the cause?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 1 of 9, by superfury

User metadata
Rank l33t++
Rank
l33t++

I've been thinking about http://www.os2museum.com/wp/will-the-real-rea … lease-stand-up/ .

UniPCemu handles the real and V86 mode(including IRETD to V86 mode) segment loading as following:

Sreg itself = value(no effect otherwise by this load)
descriptor base low(0xffff):mid(ff0000):high(ff000000) is set to (value<<4).
CS and V86: accessrights=93h, limit low=ffffh, noncallgateinfo=00h(D/B-bit, high 4 bits of limit and undefined bits are in said byte).
CS real mode&V86 mode: accessrights=93h.
SS: Update CPL according to SS descriptor and CPU mode(PM=SS.DPL, real mode 0, V86=3).

Is that correct behaviour? Especially V86 stuff?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 2 of 9, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmm... http://www.rcollins.org/ddj/Aug98/Aug98.html sheds a bit of light on the Pentium chip differences:

The real-mode code segment (CS) descriptor cache behavior has changed between generations of Intel processors. The role of the code segment-descriptor cache in real mode differs between the 80286, 80386, and 80486 and all later Intel microprocessors: The earlier microprocessors honor the real-mode segment access rights in real mode until a far control transfer occurs; later processors ignore any access rights in the CS descriptor cache irrespective of far control transfers. On the earlier processors, any far control transfer set the CS descriptor cache access rights to its real-mode compatible value as a readI-write data segment (value=0x93). Later processors leave the original value intact, but ignore its contents. Therefore, transitions from real to protected mode on the later processors immediately causes the behavior to revert to its stagnant CS descriptor-cache access rights value. On earlier processors, the CS limit is also restored to its real-mode compatible value (64 KB). Later processors leave the CS segment limit alone, making its behavior consistent with the other data segment registers.

From the 80286 to the Pentium, all Intel processors derive their current privilege level (CPL) from the SS access rights. The CPL is loaded from the SS descriptor table entry when the SS register is loaded. The undocumented LOADALL instruction (or system-management mode RSM instruction) can be used to manipulate the SS descriptor-cache access rights, thereby directly manipulating the CPL of the microprocessors. (See http://www.x86.org/articles/loadall/ for a description of LOADALL.) The Pentium Pro behaves differently: Once the CPL is loaded into the Pentium Pro, it is not internally derived from the SS access rights. The Pentium Pro retains a separate CPL register. Through the system-management mode RSM instruction, you can directly manipulate the CPL of the Pentium Pro, though not by manipulating the SS access rights value. (I will discuss the Pentium Pro SMM state save map and all of the secrets contained therein in a future column.)

Said behaviour in UniPCemu uses 80386-compatible handling in all cases(even the Pentium)!
Still, no explanation on V86 mode, though.

Edit: So, reload(for CS) descriptor limit, access rights, G and D/B only for CS before Pentium, and for all loads(including CS) in V86 mode.
And, when calculating precalcs, assume 64K limit, 1MB roof(unused essentially), present, expand up, normal base(only one using descriptor values) and 0x93 access rights in CS in Pentium real mode. Normal descriptor-based behaviour in Protected and V86 mode(including Pentium), as well as real mode up to and including the 80486 chips.

Would that be correct behaviour?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 3 of 9, by superfury

User metadata
Rank l33t++
Rank
l33t++

So, I've implemented it as follows:
- CS before Pentium and all registers in V86 mode reload access rights(0x93), limit low(0xffff) and remainder byte(granularity, limit high and Default/Big, becoming 0x00).
- Precalcs all use the descriptor values, except topdown, not present and access rights exceptions(read/write/execute permissions) on Pentium's real mode.
- Switching to/from real mode recalculates CS precalcs to activate(real->PM) or deactivate(PM->real) the access rights byte affecting the precalcs(0x93 assumed in real mode, used normally in protected mode). This happens when loading CR0 with a new PM bit(MOV CR0,reg and LMSW).

So the limit behaves normally always, access rights unmodified on Pentium+(modified before Pentium), Pentium+ in real mode ignores Access Rights(assuming 0x93) in real mode precalcs, used normally on 80486-. Limit, roof and base are used normal always.

Furthermore, Pentium+ doesn't reload Access Rights byte, limit low word and limit high/DB/G byte when loading CS in real mode. They are reloaded on 80486-.

Would that be correct? Although Pentium CPU reset loads CS Access Rights with 0x93 on Init, but honoured on Reset(having no effect on precalcs).

Those precalcs are used with all limit/type checks and also with special instructions(e.g. LSL, LAR, VERR, VERW), but since they run in protected mode, those precalcs match the descriptor anyways(LSL is the only one affected by the precalcs specifically, since it uses said precalc value instead of calculating it itself).

Last edited by superfury on 2020-01-02, 09:17. Edited 1 time in total.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 4 of 9, by superfury

User metadata
Rank l33t++
Rank
l33t++

So, if I understand this correctly, on Pre-Pentium CPUs, loading CS in real mode(using a far jump) will still yank EIP down to it's IP value, but the limit remains 4GB?

Also, any tricks previously done using the CS Access Rights byte in real mode have been made unusable(since it enforces CS to be a normal data segment in a more 8086-compatible real mode)? So tricks like R/O Code Segments in real mode won't work anymore?

One interesting thing there is, that the Pentium, if I understand this correctly, leaves the D-bit alone(along with the Granularity bit), thus keeping code 32-bit? But that would have the issue of messing up BIOS interrupts? Hmmm....

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 6 of 9, by superfury

User metadata
Rank l33t++
Rank
l33t++

I just noticed another 8086+ bug while testing the new optimizations on the VGA's packed shift mode running Ultima II on the Compaq Deskpro 386 Pentium in real mode:
When I try while on the first 'island' through it's portal(a very small island with some non-functional gate and a leave portal at the center of the bottom(about 7x7 tiles accross) that keeps appearing and disappearing as you walk around the island) near the start of the game, I noticed something weird. When trying to use magic(I was trying the 'M' and 'C' keys there as far as I can remember), eventually it asks me for a target, which I can't supply(no foes), and eventually the game hangs trying to input some keyboard I/O into it(as in, it suddenly(directly after the keystroke) stops animating the purple/red water).

Anyone?
Edit: I did have only 4HP? Perhaps that's part of it?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 7 of 9, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmm... Just found one little missing line-break when checking the 80386+ 32-bit opcode extensions(the 32-bit versions of the 80(1)86 opcodes). All other instructions seemed to run without issues(on the 80386 32-bit extensions side).

So if there's an issue with the instruction execution, it should be in the 8086 or 80186 core(seeing as the 80286 only adds 0F opcodes).
And I doubt that the crashing applications(WhatVGA and CheckIt Diagnostics 3.0) use any 80286+ opcodes when starting up, before making the screen blue for the different startup tests(or detecting hardware for WhatVGA)?

I saw not a single error otherwise in the 80386+ 80(1)86 opcode execution(all 8086 and 80186 opcodes' 32-bit variants).
Edit: Almost checked all 8086+/80186+ 8/16-bit opcodes as well. So far no errors observed(looking from Visual Studio's debugger debugging UniPCemu).
So only a few potentional 80(1)86 errors left(as well as all potentional 80286+/80386+ 0F opcodes and 80486+/Pentium ones). Hmmm...(so far checked until the BIOS has asked for and gotten the F1 key to continue to boot(in UniPCemu's case: starting INT19 to start the XT-IDE Universal BIOS(F8 for using Plop for CD booting) I'm using atm).

Otherwise, if nothing shows up after those, the issue must be somewhere in the miscellaneous CPU behaviour itself(e.g. exceptions/interrupts/far code segment transfers itself etc.)? But I've already checked those extensively in the past? Those can be found in the various non-'opcodes*_*.c' files, e.g. stack management(cpu_stack.c), interrrupts(protection.c and cpu_interrupts.c), multitasking.c(probably not, since it doesn't use TSS multitasking?) and various protection mechanisms(protection.c).

Anyone?
Edit: So far checked all 8086-80186 8/16-bit and 32-bit extensions opcodes(not the 80386+ only ones yet). No issues have been found so far(gotten until MS-DOS 6.22 prompt and past the boot menu I have in the test image. Also executed a DIR command for a bit of extra opcodes. Still no issues found yet.
Edit: OK. Ran CheckIt, but other than a single JG jump that didn't happen until then(opcode 7F), nothing shows up there either, but it still crashes. Hmmm...
Edit: Added 80486/80586 opcodes and extensions. Still nothing.
Edit: Added 80286 opcodes. Hmmm... SALC? FPU DBh opcode? FNINIT... FPU D9h opcode. FNSTCW... That's it for the 80286+ opcodes.
That just leaves the 80386+ 0F opcodes?
Edit: A few more of those(MOVZX, 0F84 JZ 16-bit), but nothing more of those. So another dead end there 🙁

Now, where is the cause? The only other place where such a strange real-mode bug could appear is in the different mechanics of the CPU itself, which only contain the segment-related logic itself(far jumps/calls and protected mode-like semantics and interrupts in real mode)?
Edit: More 286+/386+ opcodes validated with the CD-ROM drivers activated.

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 8 of 9, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmm... Tried daggerfall. It runs a new game until after the opening scene, then crashes with a

CauseWay Error 09: Unrecoverable internal exception, program terminated.

Exception: 0D, Error code: 016C
EAX=000018BD EBXC=8A503021 ECX=00000000 EDX=00000000 ESI=00004341
EDI=000006ED EBP=0000075D ESP=000006 4 EIP=000018 B EFL=00003044

CS=00A3 DS=0083 ES=00D3 FS=0073 GS=0063 SS=008B

CR0=E0000011 CR2=8A50E580 CR3=00116000 TR=0023

SystemFlags=00000000

That didn't happen before?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io

Reply 9 of 9, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmm... Just noticed something trying to run The Games: Winter Challenge on the Pentium's real mode.

When I start the game, I see an INT3 being executed(opcode CCh)? Why would it try to invoke some debugger? Or is it using it as some kind of anti-debugger trick?

Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io