20 November 2012, 18:49 | #1 | ||
Competition Moderator
Join Date: Feb 2008
Location: Germany
Posts: 4,756
|
UAE4All 68020-emulation fix
Not long ago finkel made fullspeed emulation of many AGA games on Pandora possible with his own 68020-emulation.
It contains an error (probably tiny) in at least one of its calculation functions (he's suspecting MUL or DIV, see quote below). The expectation of the AnUAE4All-developer cashing in on his work destroyed any motivation for him to fix this issue. But now lubomyr has ported UAE4All 2.0 to Android which eliminated the potential threat of anyone earning money from finkel's work since lubomyr is not going to sell it for money. The bug makes Slam Tilt and Roadkill unplayable (and other games as well). If it was fixed I'm sure they'd fully work. Here's a report of the bug and finkel's response from the Pandora boards: Quote:
Last edited by john4p; 21 November 2012 at 08:26. |
||
20 November 2012, 19:44 | #2 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,507
|
Attachment is mostly useless because all logic is in other files.
I quickly tested RoadKill AGA and it does use MULL (opcodes 0x4c00 and 0x4c3c) |
20 November 2012, 21:33 | #3 |
Competition Moderator
Join Date: Feb 2008
Location: Germany
Posts: 4,756
|
Thanks for the quick reply! I'll have a look tomorrow morning and upload the main logic to this.
|
21 November 2012, 07:55 | #4 | |
Competition Moderator
Join Date: Feb 2008
Location: Germany
Posts: 4,756
|
EDIT: Disregard this post - it's nonsense.
I've now attached the famec.cpp which #includes the famec_opcodes.h. Quote:
Here's one of the MULU opcodes in famec_opcodes.h: Code:
/* MULU */ OPCODE(0xC0C0) { u32 res; u32 src; src = DREGu16((Opcode >> 0) & 7); res = DREGu16((Opcode >> 9) & 7); res *= src; flag_N = res >> 24; flag_NotZ = res; flag_V = flag_C = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef FAME_ACCURATE_TIMING /* count bits set in the memory operand */ io_cycle_counter -= bitset_count(src & 0xFFFF) * 2; RET(38) #else RET(16 + 38) #endif } Code:
/* MULS */ OPCODE(0xC1C0) { u32 res; u32 src; src = (s32)DREGs16((Opcode >> 0) & 7); res = (s32)DREGs16((Opcode >> 9) & 7); res = ((s32)res) * ((s32)src); flag_N = res >> 24; flag_NotZ = res; flag_V = flag_C = 0; DREGu32((Opcode >> 9) & 7) = res; #ifdef FAME_ACCURATE_TIMING /* count bits set in the memory operand */ io_cycle_counter -= bitset_count(src ^ (src << 1)) * 2; RET(38) #else RET(8 + 38) #endif } (I'll test what happens if I just use the same code for MULL as MULU.) Last edited by john4p; 21 November 2012 at 08:18. |
|
21 November 2012, 08:09 | #5 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,507
|
They are not missing. Search using opcode values.
|
21 November 2012, 08:13 | #6 |
Competition Moderator
Join Date: Feb 2008
Location: Germany
Posts: 4,756
|
Sorry - the post above is completely wrong: I've searched in the famec_opcodes.h from the old uae4all1.
Now in finkel's 68020-including famec_opcodes.h I've found that opcodes 0x4c00 and 0x4c3c are defined: Code:
// MULS/MULU.L Dn - Long Format, 68020+ OPCODE(0x4C00) { u32 adr, res; u32 src, dst; #ifdef M68020_000_ILLEGAL_INTRUCTION_EX if (prefs_cpu_model < M68020) EXECUTE_EXCEPTION(M68K_ILLEGAL_INSTRUCTION_EX) #endif FETCH_WORD(res) src = DREGu32((Opcode /*>> 0*/) & 7); MULL(src, res); #ifdef USE_CYCLONE_TIMING RET(54) #else RET(50) #endif } [...] // MULS/MULU.L <xx>.W, <xx>.L - Long Format, 68020+ OPCODE(0x4C3C) { u32 adr, res; u32 src, dst; #ifdef M68020_000_ILLEGAL_INTRUCTION_EX if (prefs_cpu_model < M68020) EXECUTE_EXCEPTION(M68K_ILLEGAL_INSTRUCTION_EX) #endif FETCH_WORD(res) FETCH_LONG(src) MULL(src, res); #ifdef USE_CYCLONE_TIMING RET(54) #else RET(50) #endif } Code:
static void MULL(u32 src, u16 extra) { if (extra & 0x800) { /* signed variant */ s64 a; a = (s32)src * (s32)DREG((extra >> 12) /*& 7*/); flag_V = 0; flag_C = 0; flag_NotZ = (a != 0); if (extra & 0x400) { /* 32 x 32 -> 64 */ DREG(extra & 7) = (u32)(a >> 32); flag_N = (a >> 56); } else if ((a & UVAL64 (0xffffffff80000000)) != 0 && (a & UVAL64 (0xffffffff80000000)) != UVAL64 (0xffffffff80000000)) { flag_V = M68K_SR_V; } else /* 32 x 32 -> 32 */ flag_N = (a >> 24); DREG((extra >> 12) /*& 7*/) = (u32)a; } else { /* unsigned */ u64 a; a = src * DREG((extra >> 12) /*& 7*/); flag_V = 0; flag_C = 0; flag_NotZ = (a != 0); flag_N = (a >> 56); if (extra & 0x400) { /* 32 x 32 -> 64 */ DREG(extra & 7) = (u32)(a >> 32); flag_N = (a >> 56); } else if ((a & UVAL64 (0xffffffff00000000)) != 0) { flag_V = M68K_SR_V; } else /* 32 x 32 -> 32 */ flag_N = (a >> 24); DREG((extra >> 12) /*& 7*/) = (u32)a; } } |
21 November 2012, 08:35 | #7 | |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,507
|
Quote:
a = (u64)src * DREG(... should fix it. Same bug in signed multiplication. Compare with UAE code, it is nearly identical. |
|
21 November 2012, 08:38 | #8 |
Competition Moderator
Join Date: Feb 2008
Location: Germany
Posts: 4,756
|
That was fast - thanks! I'll try this.
|
21 November 2012, 09:43 | #9 |
Competition Moderator
Join Date: Feb 2008
Location: Germany
Posts: 4,756
|
Roadkill works now - thanks a bunch, Toni!
Unfortunately in Slam Tilt the score counter is still messed up. Only shows "00", "909,090,909,090", "404,040,404,040" or "202,020,202,020". I'll try to change DIVL, too, to match its WinUAE-counterpart. Maybe that'll help. |
21 November 2012, 10:34 | #10 |
Competition Moderator
Join Date: Feb 2008
Location: Germany
Posts: 4,756
|
Changed everything in MULL and DIVL to be exactly as in WinUAE. Sadly this didn't fix Slam Tilt's score counter (btw., I've now seen every "x0x,0x0,x0x,0x0"-combination with x being a single digit > 0).
Any idea what could cause this problem? |
21 November 2012, 16:31 | #11 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,507
|
Slam Tilt uses both MULL and DIVL (div by 1000000, mul by 1000000, div by 100000 and so on.. Not very optimal way to do integer to number string conversion).
I don't see anything obviously wrong in attached DIVL code. |
21 November 2012, 16:51 | #12 |
Competition Moderator
Join Date: Feb 2008
Location: Germany
Posts: 4,756
|
Okay, thanks a lot for your checking and the informations. If the MULL and DIVL code is correct now maybe the definition of one of the opcodes in famec_opcodes.h which uses MULL and/or DIVL is wrong?
|
22 November 2012, 13:37 | #13 |
Competition Moderator
Join Date: Feb 2008
Location: Germany
Posts: 4,756
|
I've now also tried the code for MULL and DIVL which only uses u32 and s32 variables (no u64 and s64), but that didn't fix the Slam Tilt issue, either. So I'm sure the functions MULL and DIVL are correct now.
Looked which mul-&div-opcodes Slam Tilt utilizes during gameplay. They were 0x4c00, 0x4c18, 0x4c28, 0x4c40, 0x4c50, 0x4c3c and 0x4c7c. Since Roadkill works correctly we can probably exclude 0x4c00 and 0x4c3c for being erroneous. Here are now the remaining five opcode-definitions in finkel's improved fame/c-version: Code:
// MULS/MULU.L (An)+ - Long Format, 68020+ OPCODE(0x4C18) { u32 adr, res; u32 src, dst; FETCH_WORD(res) adr = AREG((Opcode /*>> 0*/) & 7); AREG((Opcode /*>> 0*/) & 7) += 4; PRE_IO READ_LONG_F(adr, src) POST_IO MULL(src, res); RET(50) } Code:
// MULS/MULU.L (d16,An) - Long Format, 68020+ OPCODE(0x4C28) { u32 adr, res; u32 src, dst; FETCH_WORD(res) FETCH_SWORD(adr) adr += AREG((Opcode /*>> 0*/) & 7); PRE_IO READ_LONG_F(adr, src) POST_IO MULL(src, res); RET(50) } Code:
// DIVSL/DIVUL.L Dn - Long Format, 68020+ OPCODE(0x4C40) { u32 adr, res; u32 src, dst; u8 areg; FETCH_WORD(res); src = DREGu32((Opcode /*>> 0*/) & 7); if (src == 0) { execute_exception(M68K_ZERO_DIVIDE_EX); RET(10) } DIVL(src, res); RET(90) } Code:
// DIVSL/DIVUL.L (An) - Long Format, 68020+ OPCODE(0x4C50) { u32 adr, res; u32 src, dst; FETCH_WORD(res) adr = AREG((Opcode /*>> 0*/) & 7); PRE_IO READ_LONG_F(adr, src) POST_IO if (src == 0) { execute_exception(M68K_ZERO_DIVIDE_EX); RET(10) } DIVL(src, res); RET(50) } Code:
// DIVSL/DIVUL.L <xx>.W / <xx>.L - Long Format, 68020+ OPCODE(0x4C7C) { u32 adr, res; u32 src, dst; FETCH_WORD(res) FETCH_LONG(src) if (src == 0) { execute_exception(M68K_ZERO_DIVIDE_EX); RET(10) } DIVL(src, res); RET(50) } Here are the defines of the macros used (from famec.cpp): Code:
#define READ_LONG_F(A, D) \ D = Read_Word((A)) & 0xFFFF; \ D |= Read_Word((A) + 2) << 16; #define FETCH_WORD(A) \ (A) = *PC++; #define FETCH_SWORD(A) \ (A) = (s32)(s16)(*PC++); #define FETCH_LONG(A) \ (A) = PC[1] | (PC[0] << 16); \ PC += 2; #define RET(A) \ io_cycle_counter -= (A); \ if (io_cycle_counter <= 0) goto famec_Exec_End; \ goto famec_Exec; Also u32, s32, u64 and s64 are defined as follows in famec.cpp (I use g++ 4.3.3 to build on the Pandora which has an ARM Cortex A8 CPU): Code:
#define u32 unsigned int #define s32 signed int #define u64 unsigned long long #define s64 long long Last edited by john4p; 22 November 2012 at 14:01. |
22 November 2012, 19:50 | #14 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,507
|
Looks ok.
SlamTilt uses also BFEXTU and BFINS. (68020+ bit field instructions, rarely used) Very messy code, difficult to check.. |
22 November 2012, 20:53 | #15 |
Competition Moderator
Join Date: Feb 2008
Location: Germany
Posts: 4,756
|
Thanks again for your repeated examination of the code and the additional info.
I'll do some random trial&error manipulations of BFEXTU and BFINS tomorrow. If that doesn't help then I'll just accept that I have to play Slam Tilt on the laptop. |
23 November 2012, 20:50 | #16 |
Competition Moderator
Join Date: Feb 2008
Location: Germany
Posts: 4,756
|
The "random trial&error manipulations" didn't lead to any success.
Found that out of the BFEXTU- and BFINS-opcodes Slam Tilt seems to only use 0xe9e8 (BFEXTU (d16,An) - 68020+) and 0xefc0 (BFINS Dn - 68020+). When I messed with 0xe9e8 the table loaded but the screen turned grey as soon as I pressed F1 to start a game. When I changed something in 0xefc0 (like removing the comment from BF_MASK) the table also loaded but when I pressed F1 the ball instantly dropped off the screen (just fell through the bottom) before I could push it into play. Please have a final look at the two opcode definitions. Maybe you see an ovious error: Code:
// BFEXTU (d16,An) - 68020+ OPCODE(0xE9E8) { u32 adr, res; u32 src, dst; u32 mask, width; s32 offset; u32 bf0, bf1; FETCH_WORD(res) FETCH_SWORD(adr) adr += AREG((Opcode /*>> 0*/) & 7); BF_GET_PARM(res, offset, width) BF_MEM_GET(&adr, &dst, &offset, width, &bf0, &bf1); BF_SET_FLAGS(dst, width) DREG((res >> 12) /*& 7*/) = dst; RET(12) } Code:
// BFINS Dn - 68020+ OPCODE(0xEFC0) { u32 adr, res; u32 src, dst; u32 mask, offset, width; FETCH_WORD(res) dst = DREG((Opcode /*>> 0*/) & 7); src = DREG((res >> 12) /*& 7*/); BF_GET_PARM(res, offset, width) offset &= 0x1F; BF_SET_FLAGS(src, width) mask = ((u32)0xFFFFFFFF << (32 - width)) >> offset; // BF_MASK(mask, offset, width) // BF_SHIFT_UP(mask, offset, width) BF_SHIFT_UP(src, offset, width) DREG((Opcode /*>> 0*/) & 7) = (dst & ~mask) | (src & mask); RET(8) } |
17 January 2014, 08:18 | #17 |
Competition Moderator
Join Date: Feb 2008
Location: Germany
Posts: 4,756
|
The Slam Tilt issue has finally been resolved: TomB found out that an "incremented register was not written back to m68kcontext in UNPK" and fixed this.
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
68020 33 MHz | Leandro Jardim | support.WinUAE | 2 | 02 January 2012 19:21 |
Questions about 68020 CE | Maren | support.WinUAE | 11 | 09 December 2009 21:01 |
68020 and cycle-exact | FOL | support.WinUAE | 4 | 23 July 2007 22:10 |
Barfly misidentifies 68020 under emulation | DJ Mike | support.WinUAE | 10 | 02 March 2007 06:08 |
IDE fix and CD32 emulation on UAE!! | ElectroBlaster | support.WinUAE | 4 | 27 March 2002 04:07 |
|
|