Closed LinoMastro closed 10 months ago
It does seem that logical instructions (at least AND, OR, and TEST) clear AF on actual hardware, so I went ahead and added a call to clearAF() in the setLogicResult() function. Fingers crossed that this doesn't have any unexpected side-effects. I'm going to push this to the website shortly -- you should see the displayed pcx86 version as 2.22 when it's available.
Thanks for the fast response.
The new 2.22 version with https://github.com/jeffpar/pcjs/commit/5a85a07a46a20694159415d5981def37e24c2d8b is now live and it seems to have fixed the problem for me.
The pcx86 CPU emulation doesn't seem to handle the AF bit in the flags correctly, at least in some cases involving logical operations and the DAA instruction.
Here's a small test case, which can be compiled with NASM to a COM file for DOS:
I expect the first DAA to set the AF flag to 1, then the AND instruction to set it to zero and the second DAA to set AL to 1. Then the example above calls DOS to print "1". But when running in PCjs the program above prints "7" instead, because the AF flag is still set to 1 when the second DAA is executed.
There's some x86 documentation that states that the AF flag is undefined after an AND instruction but on real hardware (at least on my recent AMD CPU running in 16-bit mode) and in other emulators (dosbox, PCem and QEMU) the behavior of AND in the example above is to clear AF, resulting in a "1" output.
There's also a second related test case which is even weirder (note that the first two instructions are different here):
Again in this case I expect the output to be "1" and indeed if running this second program directly from the DOS prompt in PCjs it does print "1", but when I single-step through the code the behavior changes and again it prints "7". This happens with both MS-DOS debug.exe and PCjs builtin debugger.
I'm not sure why for the second example the bug only appears in debuggers. Maybe when running directly the ADD instruction fails to set the AF flag to 1, hiding the fact that then AND fails to clear AF? Just speculating, I checked the pcx86 code but I don't fully understand flag handling.
I can reproduce the issue on an emulated IBM PC AT machine running MS-DOS 6.22. I did my tests with https://www.pcjs.org/software/pcx86/sys/dos/microsoft/6.22/