- --
Viewing Issue Advanced Details
[ Jump to Notes ]
ID | Category [?] | Severity [?] | Reproducibility | Date Submitted | Last Update |
---|---|---|---|---|---|
01056 | Core | Typo | Have not tried | Feb 9, 2008, 04:16 | Jul 15, 2010, 16:25 |
Tester | -Misc Reporters- | View Status | Public | Platform | |
Assigned To | Resolution | Fixed | OS | ||
Status [?] | Resolved | Driver | |||
Version | 0.57 | Fixed in Version | 0.66 | Build | |
Fixed in Git Commit | Github Pull Request # | ||||
Summary | 01056: V30 core. | ||||
Description |
-Tomasz: Hey .. maybe I'm wrong (as usual) - when tested Cygne with NEC v30 cpu core found something weird. Maybe bug, maybe (probably) just a difference between x86 cpus and Nec ones (I have no detailed infos about nec cpus). Problem is with Neg opcode and Carry flag. Value of Carry after NEG is opposite to value calculated by x86 core. Inside bandai wonderswan is 80186 clone, probably designed by NEC. But carry in NEG must be calculated like in plain x86. for example: prefix 0xf6 , opcode & 0x38 = 0x18 => NEG I.CarryVal=(tmp==0); should be (at least for x86 and wonderswan ) I.CarryVal=(tmp!=0); carry should be set if tmp isn't 0 ( if 0 , then neg (sub 0,tmp) = 0-0 , no carry.. all other values (non-zeros) -> carry is set ) ------------------------------------------------------------------------------------------------------------------------------------ -Stephh: First, I checked the NEG operand with a REAL 80x86 debugger, I mean DEBUG.EXE included in DOS 6.22 (who told that DOS was history ? :p) and it confirms that the carry is set ONLY if value != 0 ... Then I looked at the MAME CPU cores which have similarities : - 80x86 (src/cpu/i86 folder) - NEC V30 (src/cpu/nec folder) - V60 (src/cpu/v60 folder) 1) 80x86 From the source files, you can see that Peter Trauner (MESS Dev) has worked on the CPU core ... In src/cpu/i86/instr86.c, we have the NEG instruction : [BEGIN] static void PREFIX86(_f6pre)(void) { /* Opcode 0xf6 */ unsigned ModRM = FETCH; unsigned tmp = (unsigned)GetRMByte(ModRM); unsigned tmp2; switch (ModRM & 0x38) { ... case 0x18: /* NEG Eb */ ICOUNT -= (ModRM >= 0xc0) ? cycles.negnot_r8 : cycles.negnot_m8; tmp2=0; SUBB(tmp2,tmp); PutbackRMByte(ModRM,tmp2); break; ... } } [END] And in src/cpu/i86/i86.h, we have the macros (split in multiple lines for easier reading) : [BEGIN] #define SUBB(dst,src) \ { unsigned res=dst-src; \ SetCFB(res); \ SetOFB_Sub(res,src,dst); \ SetAF(res,src,dst); \ SetSZPF_Byte(res); \ dst=(BYTE)res; \ } #define SetCFB(x) (I.CarryVal = (x) & 0x100) [END] If you follow the code, you'll be given this ('tmp' being the value you want to NEG) : tmp == 0 => I.CarryVal = 0 tmp != 0 => I.CarryVal = 1 2) V60 From the source files, you can see that Farfetch'd and R. Belmont have worked on the CPU core ... In src/cpu/v60/op12.c, we have the NEG instruction : [BEGIN] UINT32 opNEGB(void) /* TRUSTED (C too!)*/ { UINT8 tmpb; F12DecodeFirstOperand(ReadAM,0); tmpb = (INT8)(f12Op1&0xFF); modWriteValB = 0; SUBB(modWriteValB, (INT8)tmpb); F12WriteSecondOperand(0); F12END(); } [END] And in src/cpu/v60/v60.c, we have the macros (split in multiple lines for easier reading) : [BEGIN] #define SUBB(dst, src) \ { unsigned res=(dst)-(src); \ SetCFB(res); \ SetOFB_Sub(res,src,dst); \ SetSZPF_Byte(res); \ dst=(UINT8)res; \ } #define SetCFB(x) {_CY = ((x) & 0x100) ? 1 : 0; } [END] If you follow the code, you'll be given this ('tmp' being the value you want to NEG) : tmp == 0 => _CY = 0 tmp != 0 => _CY = 1 You might have noticed that the 'SUBB' macro is 99.99% the same as in the 80x86 core (only additional parenthesis around 'dst' and 'src') and also for the 'SetCFB' macro (the carry is stored in other variable) ... 3) Nec V30 From the source files, you can see that Bryan McPhail ("Mish") has worked on the CPU core ... In src/cpu/nec/nec.c, we have the NEG instruction (split in multiple lines for easier reading) : [BEGIN] OP( 0xf6, i_f6pre ) { UINT32 tmp; UINT32 uresult,uresult2; INT32 result,result2; GetModRM; tmp = GetRMByte(ModRM); switch (ModRM & 0x38) { ... case 0x18: /* NEG */ I.CarryVal=(tmp==0); tmp=(~tmp)+1; SetSZPF_Byte(tmp); PutbackRMByte(ModRM,tmp&0xff); nec_ICount-=(ModRM >=0xc0 )?2:16; break; ... } } [END] And in src/cpu/nec/nec.h, we have the macros (split in multiple lines for easier reading) : [BEGIN] #define SUBB \ { UINT32 res=dst-src; \ SetCFB(res); \ SetOFB_Sub(res,src,dst); \ SetAF(res,src,dst); \ SetSZPF_Byte(res); \ dst=(BYTE)res; \ } #define SetCFB(x) (I.CarryVal = (x) & 0x100) [END] Here the 'SUBB' and 'SetCFB' macros are 100% the same as in the 80x86 core ... But for an obscure reason, the 'OP( 0xf6, i_f6pre )' does NOT call the 'SUBB' macro ! So, if you follow the code, you'll be given this ('tmp' being the value you want to NEG) : tmp == 0 => I.CarryVal = 1 tmp != 0 => I.CarryVal = 0 And I can't guess that to be true: I know that the NEC V30 core had (has?) some bugs ! Do you remember the bug for 'bbmanw' about the wrong score being given at the end of level? It was in fact a CPU core bug that was also caused by a BAD carry flag on the 'DAA' instr. |
||||
Steps To Reproduce | |||||
Additional Information | Posted by Tomasz Slanina / stephh | ||||
Github Commit | |||||
Flags | |||||
Regression Version | |||||
Affected Sets / Systems | |||||
Attached Files
|
|||||
Relationships
There are no relationship linked to this issue. |
Notes
1
No.06377
AWJ Developer
Jul 15, 2010, 16:25
|
This bug was fixed by Bryan McPhail in 0.66 (!) Closing, 7 years late. |
---|