EDN Admin
Well-known member
Hi, all. I have written an x86 PC emulator in C, and its been developed using only gcc on Linux and MinGW on Windows as the compilers. It functions completely correctly when compiled with those however I must now port it over to MS Visual C++. Keep in mind
Ive never actually used Visual C++ much before, and Im fairly new to C/C++ in general. Ive only been seriously using it for 2 years or so. Dont go too hard on me.
Ive gotten it to the point that it compiles in MSVC and I can run the application, but for some reason my routines to emulate the flags calculations of the 8086 after it performs arithmetic/logical operations produce some incorrect results that cause all
manner of problems in the CPU emulation core. I am having trouble figuring out why MSVC produces different results for the same exact code.
As an example of the problems this causes in the emulation can be illustrated by these two screenshots. One is showing the emulator booting and running MS-DOS in the MSVC-compiled version, and the other in the gcc-compiled version. They are using the exact
same hard drive image file. (I had commented out the line that modified "SDL_app" window title, but otherwise the code was identical when compiled.)
<img src="http://social.microsoft.com/Forums/getfile/30462/" alt="
Ive tried both MSVC++ 2003 as well as MSVC++ 2010 Express, and they both exhibit the same issue. Ive tried disabling all optimizations, that makes no difference either. Here are my functions to calculate the emulated CPU flags. Is there some difference
between how gcc and MSVC would interpret the syntax that I am using? I know gcc has a number of extensions from standard C enabled by default, perhaps that is causing an issue? Although, I cant imagine what that might be, this is pretty straightforward code
I think:
<div style="color:black; background-color:white
<pre><span style="color:blue void flag_szp8(uint8_t <span style="color:blue value) {
<span style="color:blue if (!<span style="color:blue value) zf = 1; <span style="color:blue else zf = 0; <span style="color:green //set or clear zero flag
<span style="color:blue if (<span style="color:blue value & 0x80) sf = 1; <span style="color:blue else sf = 0; <span style="color:green //set or clear sign flag
pf = parity[<span style="color:blue value]; <span style="color:green //retrieve parity state from lookup table
}
<span style="color:blue void flag_szp16(uint16_t <span style="color:blue value) {
<span style="color:blue if (!<span style="color:blue value) zf = 1; <span style="color:blue else zf = 0; <span style="color:green //set or clear zero flag
<span style="color:blue if (<span style="color:blue value & 0x8000) sf = 1; <span style="color:blue else sf = 0; <span style="color:green //set or clear sign flag
pf = parity[<span style="color:blue value & 255]; <span style="color:green //retrieve parity state from lookup table
}
<span style="color:blue void flag_log8(uint8_t <span style="color:blue value) {
flag_szp8(<span style="color:blue value);
cf = 0; of = 0; <span style="color:green //bitwise logic ops always clear carry and overflow
}
<span style="color:blue void flag_log16(uint16_t <span style="color:blue value) {
flag_szp16(<span style="color:blue value);
cf = 0; of = 0; <span style="color:green //bitwise logic ops always clear carry and overflow
}
<span style="color:blue void flag_adc8(uint8_t v1, uint8_t v2, uint8_t v3) { <span style="color:green //v1 = destination operand, v2 = source operand, v3 = carry flag
uint16_t dst;
dst = (uint16_t)v1 + (uint16_t)v2 + (uint16_t)v3;
flag_szp8((uint8_t)dst);
<span style="color:blue if (((dst ^ v1) & (dst ^ v2) & 0x80) == 0x80) of = 1; <span style="color:blue else of = 0; <span style="color:green //set or clear overflow flag
<span style="color:blue if (dst & 0xFF00) cf = 1; <span style="color:blue else cf = 0; <span style="color:green //set or clear carry flag
<span style="color:blue if (((v1 ^ v2 ^ dst) & 0x10) == 0x10) af = 1; <span style="color:blue else af = 0; <span style="color:green //set or clear auxilliary flag
}
<span style="color:blue void flag_adc16(uint16_t v1, uint16_t v2, uint16_t v3) { <span style="color:green //v1 = destination operand, v2 = source operand, v3 = carry flag
uint32_t dst;
dst = (uint32_t)v1 + (uint32_t)v2 + (uint32_t)v3;
flag_szp16((uint16_t)dst);
<span style="color:blue if (dst & 0xFFFF0000) cf = 1; <span style="color:blue else cf = 0;
<span style="color:blue if ((((dst ^ v1) & (dst ^ v2)) & 0x8000) == 0x8000) of = 1; <span style="color:blue else of = 0;
<span style="color:blue if (((v1 ^ v2 ^ dst) & 0x10) == 0x10) af = 1; <span style="color:blue else af = 0;
}
<span style="color:blue void flag_add8(uint8_t v1, uint8_t v2) { <span style="color:green //v1 = destination operand, v2 = source operand
uint16_t dst;
dst = (uint16_t)v1 + (uint16_t)v2;
flag_szp8((uint8_t)dst);
<span style="color:blue if (dst & 0xFF00) cf = 1; <span style="color:blue else cf = 0;
<span style="color:blue if (((dst ^ v1) & (dst ^ v2) & 0x80) == 0x80) of = 1; <span style="color:blue else of = 0;
<span style="color:blue if (((v1 ^ v2 ^ dst) & 0x10) == 0x10) af = 1; <span style="color:blue else af = 0;
}
<span style="color:blue void flag_add16(uint16_t v1, uint16_t v2) { <span style="color:green //v1 = destination operand, v2 = source operand
uint32_t dst;
dst = (uint32_t)v1 + (uint32_t)v2;
flag_szp16((uint16_t)dst);
<span style="color:blue if (dst & 0xFFFF0000) cf = 1; <span style="color:blue else cf = 0;
<span style="color:blue if (((dst ^ v1) & (dst ^ v2) & 0x8000) == 0x8000) of = 1; <span style="color:blue else of = 0;
<span style="color:blue if (((v1 ^ v2 ^ dst) & 0x10) == 0x10) af = 1; <span style="color:blue else af = 0;
}
<span style="color:blue void flag_sbb8(uint8_t v1, uint8_t v2, uint8_t v3) { <span style="color:green //v1 = destination operand, v2 = source operand, v3 = carry flag
uint16_t dst;
v2 += v3;
dst = (uint16_t)v1 - (uint16_t)v2;
flag_szp8((uint8_t)dst);
<span style="color:blue if (dst & 0xFF00) cf = 1; <span style="color:blue else cf = 0;
<span style="color:blue if ((dst ^ v1) & (v1 ^ v2) & 0x80) of = 1; <span style="color:blue else of = 0;
<span style="color:blue if ((v1 ^ v2 ^ dst) & 0x10) af = 1; <span style="color:blue else af = 0;
}
<span style="color:blue void flag_sbb16(uint16_t v1, uint16_t v2, uint16_t v3) { <span style="color:green //v1 = destination operand, v2 = source operand, v3 = carry flag
uint32_t dst;
v2 += v3;
dst = (uint32_t)v1 - (uint32_t)v2;
flag_szp16((uint16_t)dst);
<span style="color:blue if (dst & 0xFFFF0000) cf = 1; <span style="color:blue else cf = 0;
<span style="color:blue if ((dst ^ v1) & (v1 ^ v2) & 0x8000) of = 1; <span style="color:blue else of = 0;
<span style="color:blue if ((v1 ^ v2 ^ dst) & 0x10) af = 1; <span style="color:blue else af = 0;
}
<span style="color:blue void flag_sub8(uint8_t v1, uint8_t v2) { <span style="color:green //v1 = destination operand, v2 = source operand
uint16_t dst;
dst = (uint16_t)v1 - (uint16_t)v2;
flag_szp8((uint8_t)dst);
<span style="color:blue if (dst & 0xFF00) cf = 1; <span style="color:blue else cf = 0;
<span style="color:blue if ((dst ^ v1) & (v1 ^ v2) & 0x80) of = 1; <span style="color:blue else of = 0;
<span style="color:blue if ((v1 ^ v2 ^ dst) & 0x10) af = 1; <span style="color:blue else af = 0;
}
<span style="color:blue void flag_sub16(uint16_t v1, uint16_t v2) { <span style="color:green //v1 = destination operand, v2 = source operand
uint32_t dst;
dst = (uint32_t)v1 - (uint32_t)v2;
flag_szp16((uint16_t)dst);
<span style="color:blue if (dst & 0xFFFF0000) cf = 1; <span style="color:blue else cf = 0;
<span style="color:blue if ((dst ^ v1) & (v1 ^ v2) & 0x8000) of = 1; <span style="color:blue else of = 0;
<span style="color:blue if ((v1 ^ v2 ^ dst) & 0x10) af = 1; <span style="color:blue else af = 0;
}
[/code]
<br/>
Any ideas from the experts here? Something tells me Im missing something that should be obvious, but am not picking up on it because I have almost zero experience with the Microsoft compilers.
I know the flags formulas Im trying to use are correct, because when compiled with gcc the emulator works correctly enough to run any 16-bit DOS software or play any old DOS games I throw at it. For example, Ultima VI: The False Prophet.
<img src="http://social.microsoft.com/Forums/getfile/30463/" alt="
Thank you!
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
View the full article
Ive never actually used Visual C++ much before, and Im fairly new to C/C++ in general. Ive only been seriously using it for 2 years or so. Dont go too hard on me.
Ive gotten it to the point that it compiles in MSVC and I can run the application, but for some reason my routines to emulate the flags calculations of the 8086 after it performs arithmetic/logical operations produce some incorrect results that cause all
manner of problems in the CPU emulation core. I am having trouble figuring out why MSVC produces different results for the same exact code.
As an example of the problems this causes in the emulation can be illustrated by these two screenshots. One is showing the emulator booting and running MS-DOS in the MSVC-compiled version, and the other in the gcc-compiled version. They are using the exact
same hard drive image file. (I had commented out the line that modified "SDL_app" window title, but otherwise the code was identical when compiled.)
<img src="http://social.microsoft.com/Forums/getfile/30462/" alt="
Ive tried both MSVC++ 2003 as well as MSVC++ 2010 Express, and they both exhibit the same issue. Ive tried disabling all optimizations, that makes no difference either. Here are my functions to calculate the emulated CPU flags. Is there some difference
between how gcc and MSVC would interpret the syntax that I am using? I know gcc has a number of extensions from standard C enabled by default, perhaps that is causing an issue? Although, I cant imagine what that might be, this is pretty straightforward code
I think:
<div style="color:black; background-color:white
<pre><span style="color:blue void flag_szp8(uint8_t <span style="color:blue value) {
<span style="color:blue if (!<span style="color:blue value) zf = 1; <span style="color:blue else zf = 0; <span style="color:green //set or clear zero flag
<span style="color:blue if (<span style="color:blue value & 0x80) sf = 1; <span style="color:blue else sf = 0; <span style="color:green //set or clear sign flag
pf = parity[<span style="color:blue value]; <span style="color:green //retrieve parity state from lookup table
}
<span style="color:blue void flag_szp16(uint16_t <span style="color:blue value) {
<span style="color:blue if (!<span style="color:blue value) zf = 1; <span style="color:blue else zf = 0; <span style="color:green //set or clear zero flag
<span style="color:blue if (<span style="color:blue value & 0x8000) sf = 1; <span style="color:blue else sf = 0; <span style="color:green //set or clear sign flag
pf = parity[<span style="color:blue value & 255]; <span style="color:green //retrieve parity state from lookup table
}
<span style="color:blue void flag_log8(uint8_t <span style="color:blue value) {
flag_szp8(<span style="color:blue value);
cf = 0; of = 0; <span style="color:green //bitwise logic ops always clear carry and overflow
}
<span style="color:blue void flag_log16(uint16_t <span style="color:blue value) {
flag_szp16(<span style="color:blue value);
cf = 0; of = 0; <span style="color:green //bitwise logic ops always clear carry and overflow
}
<span style="color:blue void flag_adc8(uint8_t v1, uint8_t v2, uint8_t v3) { <span style="color:green //v1 = destination operand, v2 = source operand, v3 = carry flag
uint16_t dst;
dst = (uint16_t)v1 + (uint16_t)v2 + (uint16_t)v3;
flag_szp8((uint8_t)dst);
<span style="color:blue if (((dst ^ v1) & (dst ^ v2) & 0x80) == 0x80) of = 1; <span style="color:blue else of = 0; <span style="color:green //set or clear overflow flag
<span style="color:blue if (dst & 0xFF00) cf = 1; <span style="color:blue else cf = 0; <span style="color:green //set or clear carry flag
<span style="color:blue if (((v1 ^ v2 ^ dst) & 0x10) == 0x10) af = 1; <span style="color:blue else af = 0; <span style="color:green //set or clear auxilliary flag
}
<span style="color:blue void flag_adc16(uint16_t v1, uint16_t v2, uint16_t v3) { <span style="color:green //v1 = destination operand, v2 = source operand, v3 = carry flag
uint32_t dst;
dst = (uint32_t)v1 + (uint32_t)v2 + (uint32_t)v3;
flag_szp16((uint16_t)dst);
<span style="color:blue if (dst & 0xFFFF0000) cf = 1; <span style="color:blue else cf = 0;
<span style="color:blue if ((((dst ^ v1) & (dst ^ v2)) & 0x8000) == 0x8000) of = 1; <span style="color:blue else of = 0;
<span style="color:blue if (((v1 ^ v2 ^ dst) & 0x10) == 0x10) af = 1; <span style="color:blue else af = 0;
}
<span style="color:blue void flag_add8(uint8_t v1, uint8_t v2) { <span style="color:green //v1 = destination operand, v2 = source operand
uint16_t dst;
dst = (uint16_t)v1 + (uint16_t)v2;
flag_szp8((uint8_t)dst);
<span style="color:blue if (dst & 0xFF00) cf = 1; <span style="color:blue else cf = 0;
<span style="color:blue if (((dst ^ v1) & (dst ^ v2) & 0x80) == 0x80) of = 1; <span style="color:blue else of = 0;
<span style="color:blue if (((v1 ^ v2 ^ dst) & 0x10) == 0x10) af = 1; <span style="color:blue else af = 0;
}
<span style="color:blue void flag_add16(uint16_t v1, uint16_t v2) { <span style="color:green //v1 = destination operand, v2 = source operand
uint32_t dst;
dst = (uint32_t)v1 + (uint32_t)v2;
flag_szp16((uint16_t)dst);
<span style="color:blue if (dst & 0xFFFF0000) cf = 1; <span style="color:blue else cf = 0;
<span style="color:blue if (((dst ^ v1) & (dst ^ v2) & 0x8000) == 0x8000) of = 1; <span style="color:blue else of = 0;
<span style="color:blue if (((v1 ^ v2 ^ dst) & 0x10) == 0x10) af = 1; <span style="color:blue else af = 0;
}
<span style="color:blue void flag_sbb8(uint8_t v1, uint8_t v2, uint8_t v3) { <span style="color:green //v1 = destination operand, v2 = source operand, v3 = carry flag
uint16_t dst;
v2 += v3;
dst = (uint16_t)v1 - (uint16_t)v2;
flag_szp8((uint8_t)dst);
<span style="color:blue if (dst & 0xFF00) cf = 1; <span style="color:blue else cf = 0;
<span style="color:blue if ((dst ^ v1) & (v1 ^ v2) & 0x80) of = 1; <span style="color:blue else of = 0;
<span style="color:blue if ((v1 ^ v2 ^ dst) & 0x10) af = 1; <span style="color:blue else af = 0;
}
<span style="color:blue void flag_sbb16(uint16_t v1, uint16_t v2, uint16_t v3) { <span style="color:green //v1 = destination operand, v2 = source operand, v3 = carry flag
uint32_t dst;
v2 += v3;
dst = (uint32_t)v1 - (uint32_t)v2;
flag_szp16((uint16_t)dst);
<span style="color:blue if (dst & 0xFFFF0000) cf = 1; <span style="color:blue else cf = 0;
<span style="color:blue if ((dst ^ v1) & (v1 ^ v2) & 0x8000) of = 1; <span style="color:blue else of = 0;
<span style="color:blue if ((v1 ^ v2 ^ dst) & 0x10) af = 1; <span style="color:blue else af = 0;
}
<span style="color:blue void flag_sub8(uint8_t v1, uint8_t v2) { <span style="color:green //v1 = destination operand, v2 = source operand
uint16_t dst;
dst = (uint16_t)v1 - (uint16_t)v2;
flag_szp8((uint8_t)dst);
<span style="color:blue if (dst & 0xFF00) cf = 1; <span style="color:blue else cf = 0;
<span style="color:blue if ((dst ^ v1) & (v1 ^ v2) & 0x80) of = 1; <span style="color:blue else of = 0;
<span style="color:blue if ((v1 ^ v2 ^ dst) & 0x10) af = 1; <span style="color:blue else af = 0;
}
<span style="color:blue void flag_sub16(uint16_t v1, uint16_t v2) { <span style="color:green //v1 = destination operand, v2 = source operand
uint32_t dst;
dst = (uint32_t)v1 - (uint32_t)v2;
flag_szp16((uint16_t)dst);
<span style="color:blue if (dst & 0xFFFF0000) cf = 1; <span style="color:blue else cf = 0;
<span style="color:blue if ((dst ^ v1) & (v1 ^ v2) & 0x8000) of = 1; <span style="color:blue else of = 0;
<span style="color:blue if ((v1 ^ v2 ^ dst) & 0x10) af = 1; <span style="color:blue else af = 0;
}
[/code]
<br/>
Any ideas from the experts here? Something tells me Im missing something that should be obvious, but am not picking up on it because I have almost zero experience with the Microsoft compilers.
I know the flags formulas Im trying to use are correct, because when compiled with gcc the emulator works correctly enough to run any 16-bit DOS software or play any old DOS games I throw at it. For example, Ultima VI: The False Prophet.
<img src="http://social.microsoft.com/Forums/getfile/30463/" alt="
Thank you!
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
View the full article