VOGONS


First post, by superfury

User metadata
Rank l33t++
Rank
l33t++

Is the overflow flag set/reset like any other shift instruction during a BT/BTS/BTC/BTR instruction? Or is it always left unchanged? UniPCemu currently affects both carry(according to the shift of requested bit + 1) and overflow flags(according to the very same shift, in exact the same way as the RCR instruction). Is that correct behaviour?

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

Reply 1 of 10, by danoon

User metadata
Rank Member
Rank
Member

It is a pain, but I wrote unit tests for the instructions (not 100% code coverage yet) and as part of that unit test, if it is run on msvc in a 32-bit build, I also verify that it works the same way on hardware. So for a standard ADD test I would call an macro that looks like this where op, a, c are passed in then I verify the result and flags. I would strongly recommend including actual hardware tests in your unit tests if possible. In this function I have an array of data then it will loop through testing different things

                __asm {                             \
__asm mov ebx, data \
__asm mov eax, [ebx].var1 \
__asm mov ecx, [ebx].var2 \
__asm mov edx, flags \
\
__asm push edx \
__asm popf \
\
__asm op a, c \
__asm mov result, eax \
\
__asm pushf \
__asm pop edx \
__asm mov flags, edx \
}

example data for 32-bit add

param1 is value 1
param2 is value 2
param3 is result
param4 is starting flags
param5 is sets CF results
param6 is sets OF results
static struct Data addd[] = {
allocData(100000, 200200, 300200, 0, false, false),
allocData(0xFFFFFFFF, 1, 0, 0, true, false),
allocData(1, 0xFFFFFFFF, 0, 0, true, false),
allocData(0, 0, 0, 0, false, false),
allocData(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0, true, false),
allocData(0x40000000, 0x40000000, 0x80000000, 0, false, true), // overflow indicates that the sign changed
endData()
};

http://www.boxedwine.org/

Reply 2 of 10, by superfury

User metadata
Rank l33t++
Rank
l33t++

Well, according to test386.asm's undefined flag tests, it's supposed to set both CF and OF accordingly. Otherwise, it crashes.

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

Reply 3 of 10, by danoon

User metadata
Rank Member
Rank
Member

I was able to get Win 95/98/2k/XP to boot in jDosbox and I did not set OF for BT/BTS/BTR/BTC

For boxedwine I have some hardware tests for those, but I didn't set or check for OF. Just for fun I set the starting condition to have OF on and off, and using BTS with my 4 sets of data did not result in OF changing. This was on a core i7.

http://www.boxedwine.org/

Reply 4 of 10, by superfury

User metadata
Rank l33t++
Rank
l33t++

Well, according to test386.asm it does affect the Overflow flag on a 80386sx(during it's undocumented flags POST E0 check). Said check will fail on e.g. Bochs and apparently succeed on a 80386.

Edit: test386.asm source code confirms that(apparently verified against a real 80386sx):

bt386FlagsTest: ; BT, BTC, BTR, BTS ; undefined flags: ; OF: same as RCR with CF=0 […]
Show full quote

bt386FlagsTest:
; BT, BTC, BTR, BTS
; undefined flags:
; OF: same as RCR with CF=0

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

Reply 5 of 10, by danoon

User metadata
Rank Member
Rank
Member

If it is undefined I guess its not surprising it could behave differently on different chips. That is too bad that there is software that depends on undefined behavior.

http://www.boxedwine.org/

Reply 6 of 10, by peterferrie

User metadata
Rank Oldbie
Rank
Oldbie

There are no undefined flags, only undocumented ones.
Yes, OF is set up to the Pentium 2 according to some rules.
Pentium 2 and later don't touch it.
It's set according to the result of ROL of 32 - bit_to_test.

Reply 7 of 10, by danoon

User metadata
Rank Member
Rank
Member
peterferrie wrote:
There are no undefined flags, only undocumented ones. Yes, OF is set up to the Pentium 2 according to some rules. Pentium 2 and […]
Show full quote

There are no undefined flags, only undocumented ones.
Yes, OF is set up to the Pentium 2 according to some rules.
Pentium 2 and later don't touch it.
It's set according to the result of ROL of 32 - bit_to_test.

Thank you for clearing that up. It is hard to discover those things without having old hardware to test on.

http://www.boxedwine.org/

Reply 8 of 10, by superfury

User metadata
Rank l33t++
Rank
l33t++
peterferrie wrote:
There are no undefined flags, only undocumented ones. Yes, OF is set up to the Pentium 2 according to some rules. Pentium 2 and […]
Show full quote

There are no undefined flags, only undocumented ones.
Yes, OF is set up to the Pentium 2 according to some rules.
Pentium 2 and later don't touch it.
It's set according to the result of ROL of 32 - bit_to_test.

You say ROL of 32 - bit to test. But isn't it RCR with CF=0 instead of ROL of 32 - bit to test? Shifting right until shifting out the bit(thus RCR val,(bit&0x(1)F)+1)? That also makes sense with the result. If you try to do it with RCL, won't you get strange results? Or is RCL 32/16-b the same as RCR b?

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

Reply 9 of 10, by peterferrie

User metadata
Rank Oldbie
Rank
Oldbie

You might get the proper result with RCR/CF=0 but I never tried it.
However, they're not the same - RCR with CF=0 introduces a zero-bit where there wasn't one before. If you ROL (not RCL) an 8-bit number by 8 bits, then carry receives a copy of bit 0. If you RCR the same with CF=0, you don't get the same result.

Reply 10 of 10, by superfury

User metadata
Rank l33t++
Rank
l33t++

What I mean is RCL x vs RCR operandsize-x.

Also, UniPCemu does RCR n+1 with all BT instructions(as a 16/32-bit RCR). The results of OF/CF are set accordingly.

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