One interesting thing to note: When running certain MS-DOS games(alley cat, ultima ii) in full screen, then switching to windows using alt-carriage return works fine, starting it from the MS-DOS prompt(perhaps graphics mode switching itself) in windowed mode inside 3.1(1) causes it to somehow crash saying an invalid instruction has been encountered and to please shut down Windows and reboot?
Any idea what the cause of that might be? Does that happen in your emulator as well?
Edit: I needed to apply the following filter(excluding certain instructions from the breakpoint) until none were triggering during executing Alley Cat inside the MS-DOS prompt inside a window(WFW 3.11):
(CPU.oldCPUmode==3) && ((!((CPU.lastopcode==0xE6) || (CPU.lastopcode==0xCF) || (CPU.lastopcode==0x9C) || (CPU.lastopcode==0x9D) || (CPU.lastopcode==0xFA) || (CPU.lastopcode==0xFB) || (CPU.lastopcode==0xCD) || (CPU.lastopcode==0xEC) || (CPU.lastopcode==0xEE) || (CPU.lastopcode==0xE4)) && (CPU.lastopcode0F==0)) || (CPU.lastopcode0F))
oldCPUmode being the CPU mode(0=real,1=protected,3=V86), lastopcode being the current opcode that's executing, lastopcode0F being a 1-bit flag that is set during 0F-prefixed instructions.
I saw the exceptions occurring in said order(and immediately excluded them from future triggers by adding them).
Why can't alley cat run inside the MS-DOS window(when ran from the command prompt this happens, but when in fullscreen it doesn't crash)?
Edit: Could it be that the default MS-DOS prompt PIF file needs some extra settings enabled to allow graphics inside the window to be used? It seems to default to only enable text mode(it's the only one crossed in the Advanced PIF settings, the default mode being text mode)?
Edit: Changing the mode to high graphics mode, then enabling all required features(all video modes available and Alt-Enter and Alt-tab key combination), it seems to run those games fine now(so far tested Alley cat, California Games seems to hang in VGA mode(it does show itself in Full screen, though)).
Edit: After terminating California Games using Ctrl-Alt-Del then pressing Enter on the BSOD to terminate the application, MS-DOS prompt no longer starts(it immediately gives the message that an invalid instruction had been executed)?
Edit: Trying to terminate Windows after that results in it trying to execute a GRP5 /7 instruction(probably instruction 0xFFFF)?
Just saw something interesting running Windows 3.0a in 386 enhanced mode(just before it crashes to the MS-DOS prompt): I see it's throwing a #GP(0) fault on accessing the DS segment, which is a descriptor loaded with a limit of 0? That seems kind of strange? It's base is 0x20(which is strange as well). It's trying to access DS: at privilege level 1. The value of DS is 0x17D. The GDTR is at 0x8010011C with a limit of 0x010F. The LDTR is 0x60, with a base of 0x80636000 and a limit of 0xFFF. So that seems to be valid as well?
Comparing it to the logs, I don't see said value occurring. Perhaps it's because it's a log of Windows 3.0 instead of 3.0a(which I'm using)?
Edit: Just made another disk image with Windows 3.0(not the a-update) installed on it. Now I've still got to test if it's working...
Edit: I also see it happening at plain vanilla Windows 3.0. So there's a problem somewhere that's causing said invalid segment to be loaded into DS? Some wrong calculation somehow(although all instructions are already tested in the test386.asm testsuite)? So perhaps stack mismanagement? Or something interrupt-related?
Edit: I see it loaded for the first time at 0105:56CF. DS is 0xBD at that point during execution. The opcode is 0x8EDB. So MOV DS,BX.
Just completed the Pentium emulation by implementing the few 0F opcodes that were added with it(0F30-0F32 and 0FC7, the P1+ tagged instructions at x86.refasm.net's coder32 edition). Now the only Pentium features left unimplemented are the VME extensions(PVI and the V86-mode extensions) and Machine Check Enable bits in CR4 and it's functionality(and CPUID reports 0 for them in it's leaf 1 results, so unsupported).
So that means that the basic minimum Pentium(with all known basic documented features(see CR4 register bits for it) but PVI, VME and FPU) is now feature complete(newer opcodes and all other bits and functionality in CR4 bits 2-4 are implemented now)? Or is there more needed for a minimum Pentium emulation?
It's so far untested, but a simple run and perhaps using jemm386 again(since it tries to use it by default, unlike EMM386 that's with MS-DOS and Windows 3.x) for the VME support should do the trick?
Edit: Hmmm... Strangely, on the Pentium CPU emulation, the MS-DOS prompt inside WFW 3.11 seems to hang the entire system when it starts(directly after displaying the message how to return to Windows etc.(and other information about shortcut keys), with the cursor on the next row?
Edit: Simple solution for that: just use the FreeDOS floppy disk image:D
Hmmm... The freeDOS boot image boots fine. Then, quitting the setup and returning to the MS-DOS prompt goes fine as well. Then I tried to run "jemm386 LOAD"(of course without quotes). I see in my debugger that it's actually using the V86 VME functionality of the Pentium emulation:D
Then I see something strange on the screen. I see it throwing exception 03, then 08, Then 09, Then 08 again. Perhaps that's telling me something about the emulation correctness?
Edit: The CPU then seems to be waiting in a HLT state, perhaps for an interrupt from the interrupt controller(The interrupt flag is enabled), but I don't see any interrupts being triggered?
Edit: The 80386 seems to still run fine.
Edit: So does the Pentium with "jemm386 LOAD NOVME" from MS-DOS 6.22.
Edit: And it also runs without NOVME on MS-DOS 6.22.
So the problem is FreeDOS itself?
Hmmm... Bochs' Pragma Linux seems to triple fault almost immediately on a stack fault loading SS using LSS(on what looks like a BIOS segment(0xfxxx) and with a very strange offset(0x9xxxxxxx)? That's at what seems to be the end of the initial loading dots(boot loader?)?
Just found some little bugs in the 0F00 instructions: it wasn't throwing an #UD for Virtual 8086 mode execution, just using the protected-mode rules when that's the case(getcpumode()==CPU_MODE_REAL must be getcpumode()!=CPU_MODE_PROTECTED).
So now it's properly #UD faulting in V86 mode.
Just tried running Doom on the Windows 3.11 MS=DOS box in windowed mode on the Pentium emulation. It seems to load until it starts the timer(the final step before graphics mode afaik?) at the bottom of the screen(or close), at which point everything seems to hang? Display doesn't change anymore and Windows is unresponsive? Ctrl+Alt+Del has no effect anymore.
Also, this is what happens booting Pragma Linux(just protected mode logged; from the Bochs website disks page):
Interestingly, I see that invalid SS value during the Linux boot(Pragma Linux from the Bochs' website) being written by a REP MOVSW instruction at 9020:01CA. DS is 1300h, ES is 400h, ESI and EDI are both 0x6AC? So it's copying that invalid value from 136AC to 46AC?
Edit: Loading that address, I see some read from the hard disk drive(primary master), which is my dynamic disk image containing various apps I use to test my emulator. It writes the value 0xB0FE to said location(0x136AC)?
Edit: Whoops, that's not the linux kernel booting. It's the MS-DOS one from my hard disk image.
Hmmm.... I see the DMA controller writing those values to those RAM locations at 136AC and 136AD? According to the DMA transfer that does that, it's the FDC channel(DMA controller #0, channel 2)? The FDC start position of the current transfer is 0x2600, so Cylinder 0, Head 1, Sector 2(It's a normal 1.44MB formatted disk, so 80 tracks, 2 heads and 18 sectors per track). So that's LBA 19? It's the 0xAD offset within the sector. Looking at the disk image using a hex editor, it's indeed 0xD8FA at that location? So perhaps it's loading the kernel from disk into memory(as one large block read), then tries to execute/boot it, but it fails?
Hmmm... Are there any other processor test suites I can run against my Pentium emulation(or 386DX/486SX emulation)? Like Checkit Diagnostics etc.?
Edit: Just gave OS/2 warp 4 a try again. It now seems to crash on an INT 70h(IRQ8, according to the second PIC's ICW2)? The IDTR is pointing to some memory (E30FBE with a limit of 3FFh) that's not in memory? Thus it's triple faulting. Anyone?
Edit: It's FFE30FBE for all LIDT loads until the crash. Then, suddenly, the FFh byte is cleared, but the rest is set?
That happens at 160:fff615a4. It points to SS:FEE4(SS has a limit of 48BB, base ffe0c744). That would result in a linear address of FFE1C628. That's at physical address 2A628(according to the paging TLB).
Edit: One interesting thing I see happening is that it keeps loading the IDTR with a sub-4GB base(FFxxxxxxh) or 0, back and forth. Probably switching between real mode BIOS and protected-mode OS(like Windows 3.x does as well). But just before the crashing interrupt, it suddenly switches to 00xxxxxxh(the xxxxxxh part is always E30FBE), which isn't paged in, thus triple faulting on the IRQ handler interrupt itself. So perhaps it's loading an invalid IDTR for some reason? Something incorrectly clearing the highest byte?
Just tried logging the 160 code segment instead of the whole thing. Then I, looking upwards from the invalid (L)IDT base being loaded, I arrive at some "0160:fff8c95b (F3A5)REP MOVSD" instruction, that's seemingly moving a block of memory? That instruction seems to overwrite said memory, writing data from another chunk of memory there? That happens at timestamp 03:02:22:82.02400.
Edit: Hmmm.... Looking at the REP MOVSW instruction it's running, it seems to somehow keep prefetching the very same block of memory at 160:fff8c95b into the prefetch buffer. That isn't supposed to happen during a REP instruction that's running? I also see no interrupts being raised, so the prefetch buffer isn't being cleared in that way.
The Pentium is in IPS clocking mode, so it keeps prefetching until the prefetch buffer is filled, but it isn't supposed to be cleared while the REP instruction is doing it's repeating, since it doesn't exactly jump to another location in memory?
So perhaps there's a prefetch issue right there?
Edit: It did have to do with the prefetch, as well as the REPeating instructions itself! The prefetch buffer was cleared and reset each time an REPeated instruction was doing one repeated action.
The REPeating instructions itself were essentially processing dummy instruction handlers from the second repeat and onwards(the first ran normally(like any other instruction, except with blocking option to prevent it from executing), the second one and onwards were executing without the execution phase handler being notified that a new instruction is to be started(loading the pointer to the current instruction handler, which is either an interrupt, instruction or task switch handler). Since the first instruction actually zeroes out said handler(since it's done it's work) after the last execution phase of the current action of the EU is finished(and the opcode is finished as well), any following phases(the rest of the repeated instruction, as there is no more instruction fetching and decoding after the first instruction) will cause it to effectively execute a NOP(since the pointer is zeroed, it counts execution as invalid, logs a warning that the EU has nothing to do(Literally "Warning: nothing to do?") and aborts handling the opcode, leaving the executed state set to 1, thus finishing the currently executing instruction with one cycle as it's duration(actually 0, but it's patched to 1 since a 0-cycle duration can't exist).
So, having solved that, those REP instructions should be a lot lighter to be emulated now, as well as properly using the PIQ.
Edit: Perhaps that also caused the bug in 8088 MPH? Since the STOSW instruction, when prefixed with REP, didn't fully execute(only the first one actually did. The rest were effectively NOP instructions).
Anyone knows what might cause the Compaq Deskpro 386 BIOS to become very slow during it's memory check of 99XX through 12000KB? I have 12MB of RAM installed(of which ~380K is made into a ROM(actually write-protected RAM) by the BIOS) in UniPCemu. The RAM between 640K-1M and any between 15M-16M and 3G-4G is remapped to the end of RAM, of which the final ~380K is mapped as mentioned above(the Compaq BIOS' shadow RAM, although the Compaq manuals might call it differently). Said RAM is controlled(remapped and Read-Only flags) by the register at memory location 80C00000(write-only register).
Edit: Just tried again running Pink Panther in Hocus Pocus Pink. Now, it displays a white window(about the size of the installer's window), after which Windows crashes and displays a message saying that it has insufficient memory to allocate and unable to load COMMAND.COM?
Installing Windows 95a on the 80386 emulation goes fine until just after the reboot. But eventually it still crashes on some unknown user-mode driver. I see exactly one page fault, at DS(30):CB1008? It happens directly after the B drive motor has spinned up(propably the floppy PDR driver), when it's trying to initialize the (second) IDE driver(the ESDI_506.PDR driver being loaded a second time)?
Edit: The first boot only throws exactly one page fault: at 30(DS):CB1008?
Cam anyone see what's going wrong? Or some fault that's supposed to happen that's missing?
Edit: Hmmm.... The page fault at the end, It's returning properly to real mode, then does it's thing, and returns to protected mode and executes a TSS-based hardware task switch back to the software that was originally interrupted? That happens at 00:05:30:44.06656.
Edit: The debugger acts a bit strange on the 66h 67h REP MOVSD when it returns to said task, loading the data that's been read for the application into memory. It keeps logging the task-switching JMP instruction for that one?
The PTE's page frame loaded for that memory address seems to be at 01A000.
Edit: Looking at the disassembly what's executing, I keep seeing task switching from 68->60->70(which transfers back to 68h again)?
Edit: It looks like while it's transferring the data for the application, an hardware interrupt arrives(interrupt 0x40 seems to be triggered, according to the descriptor's address substracted with the IDTR base address)?
Edit: Thus the TSS returns it to EIP=0x3C5.
Edit: The main (executable loading I think) loading loop ends at 0087:000003c9, with a POP ES instruction following the data load from the Paging part of the executable at 10001000 and onwards. That's at line 0087:000003c9. So the page faults until then are fine. That's at line 159884. So up until then, there isn't supposed to be anything wrong yet. So the problem should be somewhere in the remaining 28047 lines:
So it's calling the MS-DOS interrupt vector(int 21h). DS seems to point to 109F0 in the linear address space. EDI is set to 62A, so at 109F0+62A=1101A is the table with parameters for the return to the real mode handler of the INT21h vector?
So, according to the table:
00H(1101A) 4 DI or EDI
04H(1101E) 4 SI or ESI
08H(11022) 4 BP or EBP
0CH(11026) 4 reserved, should be zero
10H(1102A) 4 BX or EBX
14H(1102E) 4 DX or EDX
18H(11032) 4 CX or ECX
1CH(11036) 4 AX or EAX
20H(1103A) 2 CPU status flags
22H(1103C) 2 ES
24H(1104E) 2 DS
26H(11050) 2 FS
28H(11052) 2 GS
2AH(11054) 2 IP (reserved, ignored)
2CH(11056) 2 CS (reserved, ignored)
2EH(11058) 2 SP
30H(1105A) 2 SS
That's what should be loaded in memory at those locations?
Edit: It copies those values to the memory at 1b504(ES(33):20D4).
The real mode interrupt handler eventually switches to task 0x68? So the PM task is task 0x70. TSS 0x68 is some kind of intermediary step to real mode?
Edit: Task 0x68 is actually some task that executes the real mode code and returns to the PM task afterwards from it. It immediately after loading switches back to task 0x60. So 0x60 or 0x70 are both native protected-mode tasks?
Just found out something interesting: CWSDPMI being used by the testsuite seems to crash, depending on the interrupts that are occurring. If a timer interrupt gets in between while it's loading the executable(the DPMI-enabled program, in this case the testsuite), CWSDPMI double faults into oblivion(at the location the interrupt occurs).
But when no interrupt(IRQ0) occurs during loading the executable, the executable loads and runs properly.
This is the first logged output from UniPCemu running the testsuite:
Privateer seems to have changed a bit with the latest updates: it's now producing a tone, but still seems to be hanging (probably in a loop) somehow? The video still isn't updating past the first frame.