mirror of
https://github.com/flyinghead/flycast.git
synced 2026-11-07 09:16:10 -10:00
addrspace: mask the shift count taken from the tagged pointer (#2574)
readConst, writeConst, readt and writet shift the 32-bit guest address by the whole tagged memInfo_ptr value (pointer | shift). Shifting a u32 by 32 or more is undefined, and GCC 16 targeting 32-bit ARM uses that: once the pointer is known to be non-null (iirf > 31) it drops the offset, so read32/write16 compile to a plain load/store at the region base. Every memory access then hits offset 0, the BIOS trampoline copied to 8C0000E0 is lost and the console never boots (black screen, no sound). Mask the shift with HANDLER_MAX, which is what x86 does in hardware and what the code intends. No change in behaviour where the old code worked. Co-authored-by: hitenmandalia <[email protected]> [ci skip]
This commit is contained in:
1 parent
38a3d83c77
commit
128e6ce29c
1 file changed
+20
-8
@@ -61,8 +61,11 @@ void *readConst(u32 addr, bool& ismem, u32 sz)
|
||||
else
|
||||
{
|
||||
ismem = true;
|
||||
addr <<= iirf;
|
||||
addr >>= iirf;
|
||||
// Only the low bits of iirf hold the mask shift. Shifting a 32-bit value by the
|
||||
// whole tagged pointer is undefined, and GCC 16 on 32-bit ARM drops the
|
||||
// address entirely (every access hits offset 0).
|
||||
addr <<= (iirf & HANDLER_MAX);
|
||||
addr >>= (iirf & HANDLER_MAX);
|
||||
|
||||
return &(((u8 *)ptr)[addr]);
|
||||
}
|
||||
@@ -94,8 +97,11 @@ void *writeConst(u32 addr, bool& ismem, u32 sz)
|
||||
else
|
||||
{
|
||||
ismem = true;
|
||||
addr <<= iirf;
|
||||
addr >>= iirf;
|
||||
// Only the low bits of iirf hold the mask shift. Shifting a 32-bit value by the
|
||||
// whole tagged pointer is undefined, and GCC 16 on 32-bit ARM drops the
|
||||
// address entirely (every access hits offset 0).
|
||||
addr <<= (iirf & HANDLER_MAX);
|
||||
addr >>= (iirf & HANDLER_MAX);
|
||||
|
||||
return &(((u8 *)ptr)[addr]);
|
||||
}
|
||||
@@ -112,8 +118,11 @@ T DYNACALL readt(u32 addr)
|
||||
|
||||
if (likely(ptr != nullptr))
|
||||
{
|
||||
addr <<= iirf;
|
||||
addr >>= iirf;
|
||||
// Only the low bits of iirf hold the mask shift. Shifting a 32-bit value by the
|
||||
// whole tagged pointer is undefined, and GCC 16 on 32-bit ARM drops the
|
||||
// address entirely (every access hits offset 0).
|
||||
addr <<= (iirf & HANDLER_MAX);
|
||||
addr >>= (iirf & HANDLER_MAX);
|
||||
|
||||
return *(T *)&((u8 *)ptr)[addr];
|
||||
}
|
||||
@@ -156,8 +165,11 @@ void DYNACALL writet(u32 addr, T data)
|
||||
|
||||
if (likely(ptr != nullptr))
|
||||
{
|
||||
addr <<= iirf;
|
||||
addr >>= iirf;
|
||||
// Only the low bits of iirf hold the mask shift. Shifting a 32-bit value by the
|
||||
// whole tagged pointer is undefined, and GCC 16 on 32-bit ARM drops the
|
||||
// address entirely (every access hits offset 0).
|
||||
addr <<= (iirf & HANDLER_MAX);
|
||||
addr >>= (iirf & HANDLER_MAX);
|
||||
|
||||
*(T *)&((u8 *)ptr)[addr] = data;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user