VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

Is there any better documentation on the 80386DX/SX than what the programmer's reference manual(https://pdos.csail.mit.edu/6.828/2006/readings/i386/toc.htm) provides?

There seems to be a bug in my x86 emulation somewhere, but I can't seem to find it.

The documentation's exact behaviour on different kinds of faults seems kind of murky. It tells for some conditions when they occur, but not in what order they occur? Are there things on the 80386 itself missing in that documentation?

Anyone?

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

Reply 1 of 15, by crazyc

User metadata
Rank Member
Rank
Member

The original 386 reference manual is a mess with lots of errors, relying on it is a mistake. The Pentium manual or even the modern ia32 manuals include a lot of extra information not relevant to the 386 but are much more accurate for what is relevant.

Reply 2 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just have been thinking: is the Nested Task(in the EFLAGS register) flag effective as in protected mode in V86 mode? Can it IRET(D) back to the calling task? UniPCemu currently stays in V86 mode because the V86 check comes first.

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

Reply 3 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

OK. Just have been reading the Pentium programmer's reference manual for a bit.

For alignment check exceptions, it says:

An alignment-check exception is generated for unaligned memory operations in user mode (privilege level 3), provided both AM and […]
Show full quote

An alignment-check exception is generated for unaligned memory operations in user
mode (privilege level 3), provided both AM and AC are set. Memory operations at
supervisor mode (privilege levels 0, 1, and 2), or memory operations which default to
supervisor mode, do not generate this exception.

What is meant by "memory operations which default to
supervisor mode"?

Edit: Hmmm... Reading further, are the sign/zero/parity flags updated when the masked count of a shift/rotate instruction is zero(&0x1F(dword), &0xF(word) or &0x7(byte))? Or are they, like the carry flag and overflow flag, left alone?
Edit: OK. Searching further, I found (https://c9x.me/x86/html/file_module_x86_id_285.html) out that those flags are also unaffected for any zero-shift counts.

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

Reply 4 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

Hmmm... Reading the Pentium programmer's reference manual 23.2.24 "Bus hold"...
It mentions that the bus hold(like DMA transfers requesting control of the bus) is acnowledged between parts of an unaligned operand, like a 80[3/4]86 does.
So, does that mean that the bus isn't released to other bus masters between (byte(8088)/word(8086,80286) misaligned) transfers on the older CPU's?
Reenigne? What do you know about this?

UniPCemu currently releases the bus to DMA after each byte/word/dword transfer on all CPUs. So on a 8088/8086/80286+, a DMA transfer can occur between the two bytes being transferred in a word memory read/write. Should this bus release be prevented on these CPUs?

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

Reply 5 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just sniffed out another bug: when performing task switching using a task gate descriptor in the IDT(also with task gates in the GDT/LDT), it would use the privilege checks normally when using a gated task switch when performing the task switch itself. The caller(the GDT/LDT descriptor parsing and IDT task gate parsing) would properly call the task switching state handler, which would start up the task switching process. But when the old task was switched out(if there was an old task), when loading the new task's descriptor into the register, it would check the normal CPL vs RPL vs DPL checks and fault if they didn't match properly (according to data register privilege rules) instead of ignoring those privilege level checks(as they're already done in their calling gates(from the IDT or GDT/LDT respectively)) and need to be ignored during said loading/marking busy step.

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

Reply 6 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

Still typical that all found documentation on x86 mentions the segmentation part of checks, but completely omits any information on the paging half(other than describing paging on the paging unit itself)? They never talk about the paging checks being made during specific microprocessor processes(e.g. during interrupts/exceptions, task switching, descriptor loading)? The only points of reference relating to those I've actually got is other emulators?

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

Reply 7 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just implemented the Bochs way of handling descriptors during TSS task switching. When the commit point is reached, it will clear all to be loaded segment descriptors, setting SS Access rights to the initial CPL to use(all other bits are cleared, since it's still an 'invalid' descriptor to use otherwise). Then any steps after that will normally load the descriptors into the registers as documented(CS, SS, remaining registers, in that order). And after each of said register is loaded, the commit function is called again to solidify the register being changed and prevent it from changing back to uninitialized when faulting(otherwise it would set them to the initial TSS loaded value, which was a NULL descriptor(although SS loaded with the initial CPL(CS.RPL) before anything is known).
And it now sets the initial SS.DPL to the correct value used CPL when reloading said value, which it didn't before. Before this change, it would revert to the start of the loading of the task switch, which would have all old descriptor values still stored in them(which obviously isn't correct).

So now, when a fault occurs during loading any selector into a register during a task switch, it will have the previously loaded selectors and descriptors applied in the fault handler(so faulting on CS only has LDT, on SS has CS and LDT loaded, on data segments have the previous data segments, CS and LDT loaded). Of course this mainly affects stuff like different privileged fault handlers, which need the descriptors and selectors in a valid state to return to(using a normal IRET(D)).

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

Reply 8 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

I see something strange in the Pentium documentation: on the part of the RETF instruction description of the steps taken when returning to a lower privilege level(table 12-2), it says the RPL and DPL checks are after the present check, but the RET instruction itself(on page 25-270) says it happens before said check(like the 80386 documentation says as well)? Which one is correct?

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

Reply 9 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

Is loading conforming code into a data segment always allowed, regardless of CPL? So MOV DS,conformingcodesegment won't check for MAX(RPL,CPL)<=CPL to not error out because that condition is broken(like JMPing/CALLing it)?

So when DPL is 1, CPL is 0 and a MOV DS,20h is executed, it will not fault because MAX(RPL(=0),CPL(=0))<DPL(=1)? Or will it fault after all like a RETF/JMP/CALL does?

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

Reply 10 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just tried Windows 3.1 with the current code on the 7100 cycle(7.1MHz) 80286 AT architecture. All went fine until I tried to run the MS-DOS prompt(dir was working), then alt-tab out of it back into windows(OK), then trying to open the control panel made Windows 3.1 hang fully(or doesn't respond anymore)?

Edit: Ah. Interesting. The CPU's EU is hanging on a RETF trying the BIU to pop IP from the stack, the BIU is in T1(the first cycle of the BIU) with requestready being 0 because it's faulting... That's not supposed to happen in that case(it should become ready at that point again). Simply because the prefetching unit marks it as being not ready! It's only supposed to do that when actually not faulting(starting an actual request), otherwise it's a transfer that will never terminate or run, hanging the BIU!

It also seems like Windows 3.1 won't always multitask it seems? I click different application windows, but they won't activate until the other window is finished? Or is that a mechanic of Windows 3.x?

The same kind of thing happens when I run the clock program and solitaire at the same time? When I press the new game option, the clock program stops updating until the solitair program has finished it's card drawing animation it seems?

Edit: Running various applications at the same time, somehow control.exe seems to crash itself with general protection faults now? This in turn gives an error message which, when closed, closes Windows 3.1 entirely? All other software I ran at the same time(MS-DOS prompt, which was closed before that, Control panel, Clock and Paintbrush were opened) seemed to run fine, until I switched back to the control panel application?

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

Reply 11 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just found a little 'bug' in the conforming code segment privilege handling. When a jump/call/load is made to load CS with a segment selector for the conforming code segment, the RPL would be used to lower the privilege level used is having less privilege than CPL. Instead, it should use the CPL and ignore the RPL specified instead(the RPL has no effect in this case, according to the 80386 programmer's reference manual).

So RPL could lower the privilege of a JMP/CALL(that was applied without a gate only) check(with conforming code segments) instead of being ignored like it should.

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

Reply 12 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

I just saw something interesting in Windows 3.1: when running various programs in it(sound MCI setup(the prebuffer setting) in the control panel, file manager), when starting said sections up, I see the CPU #GP(E0) faulting because it's trying to RETF to kernel mode(to segment E0h from CPL 3). I saw the same kind of behaviour when starting up the Windows 95 RTM setup!
Perhaps it's something that's connected there? A common component that's failing(if it's a failure) in both Windows 3.x OSes? Doesn't 95's MINI.CAB use 3.x at it's setup?

Edit: After opening up a lot of those programs(file manager, clock and the control panel) and MS-DOS (alt-tabbing out in the middle of a dir command), I encountered the stack fault again after opening the control panel a few more times(double clicking on it). At 11BF:262B. It's opcode C0h. The modr/m byte is 02h. The stack limit value is 32CFh. It's a expand up segment. SP is 25B4h. The offset that's faulting is 405B.

The full opcode is C0 02 8A. So that's ROL [BP+SI],8A. BP=3FC0, so it's already out of range. SI=9B. So combined they're way out of range of the stack segment? The offset is calculated correctly, but incorrectly used?

So there's at least still a problem with the 80286- instruction set or the 16-bit protected-mode programming?

Edit: After reinstalling Windows, running a lots of applications seems to work fine, until I once again go into the sound settings for the MCI Sound driver(pressing the setup button and OK in the dialog that pops up for the 4 second default prebuffer setting). Then once closing it, the stack fault pops up once again, this time on offset 14C1B masked to 16-bit, so 4C1Bh. The exception happens at 11BF:144F. CS has a limit of 298F. Weirdly enough, both CS and SS have the same segment descriptor base and limit values, except one being a code segment(access rights FBh) and the other has a data segment(type F3h). In all other aspects, the two seem identical, weirdly enough?
The full opcode that's faulting is C0 AA C0 C8 01.
That's supposed to be SHR BP+SI-3740h? BP=7F80, SI=3FB.

Edit: This time, it reports SOL(Solitaire itself) as the cause of the Stack Fault?

Something's definitely wrong there...

Edit: Interestingly, the two MS-DOS prompts I started up before the crash are still in memory and paused. I also see (using mem.exe /D /P) that some program called dswap.exe, WIN data and program blocks are still in memory? So Windows 3.1 didn't expect to be closed like that(mostly the GUI it seems)?

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

Reply 13 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just finished reading the Pentium Programmer's Reference Manual chapter 12. Other than modifiying conforming code segments to ignore the privilege level during data move instructions(moving it into a data segment register), everything is already implemented. So other than that nothing new is mentioned.

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

Reply 14 of 15, by pan069

User metadata
Rank Oldbie
Rank
Oldbie

I remember Lance Leventhal's 80386 programming guide was pretty good. But then again, it's been about 30 years or so since I actually read it. My memory might be foggy. 😀

https://archive.org/details/lanceleventhals80000leve

Reply 15 of 15, by superfury

User metadata
Rank l33t++
Rank
l33t++

Just tried booting OS/2 warp 4 setup from it's install floppy disks(1&2). Interestingly, just like NT4, it crashes because it can't use/find/read it's boot device(the floppy/hdd).

Edit: It literally says: "OS/2 is unable to operate your hard disk or diskette drive.".
So both definitely have issues with their storage media?

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