MMU: Get rid of pointer casts

These sort of casts invoke undefined behavior (u8, u16, u32, and u64 all have
completely different alignment requirements).
This commit is contained in:
Lioncash 2017-04-17 19:21:28 -04:00
parent 9cfc671c69
commit a58d5fa8ee
1 changed files with 37 additions and 19 deletions

View File

@ -211,26 +211,34 @@ static T ReadFromHardware(u32 em_address)
// Handle RAM; the masking intentionally discards bits (essentially creating // Handle RAM; the masking intentionally discards bits (essentially creating
// mirrors of memory). // mirrors of memory).
// TODO: Only the first REALRAM_SIZE is supposed to be backed by actual memory. // TODO: Only the first REALRAM_SIZE is supposed to be backed by actual memory.
return bswap((*(const T*)&Memory::m_pRAM[em_address & Memory::RAM_MASK])); T value;
std::memcpy(&value, &Memory::m_pRAM[em_address & Memory::RAM_MASK], sizeof(T));
return bswap(value);
} }
if (Memory::m_pEXRAM && (em_address >> 28) == 0x1 && if (Memory::m_pEXRAM && (em_address >> 28) == 0x1 &&
(em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE) (em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
{ {
return bswap((*(const T*)&Memory::m_pEXRAM[em_address & 0x0FFFFFFF])); T value;
std::memcpy(&value, &Memory::m_pEXRAM[em_address & 0x0FFFFFFF], sizeof(T));
return bswap(value);
} }
// Locked L1 technically doesn't have a fixed address, but games all use 0xE0000000. // Locked L1 technically doesn't have a fixed address, but games all use 0xE0000000.
if ((em_address >> 28) == 0xE && (em_address < (0xE0000000 + Memory::L1_CACHE_SIZE))) if ((em_address >> 28) == 0xE && (em_address < (0xE0000000 + Memory::L1_CACHE_SIZE)))
{ {
return bswap((*(const T*)&Memory::m_pL1Cache[em_address & 0x0FFFFFFF])); T value;
std::memcpy(&value, &Memory::m_pL1Cache[em_address & 0x0FFFFFFF], sizeof(T));
return bswap(value);
} }
// In Fake-VMEM mode, we need to map the memory somewhere into // In Fake-VMEM mode, we need to map the memory somewhere into
// physical memory for BAT translation to work; we currently use // physical memory for BAT translation to work; we currently use
// [0x7E000000, 0x80000000). // [0x7E000000, 0x80000000).
if (Memory::m_pFakeVMEM && ((em_address & 0xFE000000) == 0x7E000000)) if (Memory::m_pFakeVMEM && ((em_address & 0xFE000000) == 0x7E000000))
{ {
return bswap(*(T*)&Memory::m_pFakeVMEM[em_address & Memory::RAM_MASK]); T value;
std::memcpy(&value, &Memory::m_pFakeVMEM[em_address & Memory::RAM_MASK], sizeof(T));
return bswap(value);
} }
if (flag == FLAG_READ && (em_address & 0xF8000000) == 0x08000000) if (flag == FLAG_READ && (em_address & 0xF8000000) == 0x08000000)
@ -292,21 +300,24 @@ static void WriteToHardware(u32 em_address, const T data)
// Handle RAM; the masking intentionally discards bits (essentially creating // Handle RAM; the masking intentionally discards bits (essentially creating
// mirrors of memory). // mirrors of memory).
// TODO: Only the first REALRAM_SIZE is supposed to be backed by actual memory. // TODO: Only the first REALRAM_SIZE is supposed to be backed by actual memory.
*(T*)&Memory::m_pRAM[em_address & Memory::RAM_MASK] = bswap(data); const T swapped_data = bswap(data);
std::memcpy(&Memory::m_pRAM[em_address & Memory::RAM_MASK], &swapped_data, sizeof(T));
return; return;
} }
if (Memory::m_pEXRAM && (em_address >> 28) == 0x1 && if (Memory::m_pEXRAM && (em_address >> 28) == 0x1 &&
(em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE) (em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
{ {
*(T*)&Memory::m_pEXRAM[em_address & 0x0FFFFFFF] = bswap(data); const T swapped_data = bswap(data);
std::memcpy(&Memory::m_pEXRAM[em_address & 0x0FFFFFFF], &swapped_data, sizeof(T));
return; return;
} }
// Locked L1 technically doesn't have a fixed address, but games all use 0xE0000000. // Locked L1 technically doesn't have a fixed address, but games all use 0xE0000000.
if ((em_address >> 28 == 0xE) && (em_address < (0xE0000000 + Memory::L1_CACHE_SIZE))) if ((em_address >> 28 == 0xE) && (em_address < (0xE0000000 + Memory::L1_CACHE_SIZE)))
{ {
*(T*)&Memory::m_pL1Cache[em_address & 0x0FFFFFFF] = bswap(data); const T swapped_data = bswap(data);
std::memcpy(&Memory::m_pL1Cache[em_address & 0x0FFFFFFF], &swapped_data, sizeof(T));
return; return;
} }
@ -315,7 +326,8 @@ static void WriteToHardware(u32 em_address, const T data)
// [0x7E000000, 0x80000000). // [0x7E000000, 0x80000000).
if (Memory::m_pFakeVMEM && ((em_address & 0xFE000000) == 0x7E000000)) if (Memory::m_pFakeVMEM && ((em_address & 0xFE000000) == 0x7E000000))
{ {
*(T*)&Memory::m_pFakeVMEM[em_address & Memory::RAM_MASK] = bswap(data); const T swapped_data = bswap(data);
std::memcpy(&Memory::m_pFakeVMEM[em_address & Memory::RAM_MASK], &swapped_data, sizeof(T));
return; return;
} }
@ -399,7 +411,7 @@ TryReadInstResult TryReadInstruction(u32 address)
// TODO: Refactor this. This icache implementation is totally wrong if used with the fake vmem. // TODO: Refactor this. This icache implementation is totally wrong if used with the fake vmem.
if (Memory::m_pFakeVMEM && ((address & 0xFE000000) == 0x7E000000)) if (Memory::m_pFakeVMEM && ((address & 0xFE000000) == 0x7E000000))
{ {
hex = bswap(*(const u32*)&Memory::m_pFakeVMEM[address & Memory::FAKEVMEM_MASK]); hex = Common::swap32(&Memory::m_pFakeVMEM[address & Memory::FAKEVMEM_MASK]);
} }
else else
{ {
@ -666,7 +678,7 @@ void DMA_LCToMemory(const u32 memAddr, const u32 cacheAddr, const u32 numBlocks)
{ {
for (u32 i = 0; i < 32 * numBlocks; i += 4) for (u32 i = 0; i < 32 * numBlocks; i += 4)
{ {
u32 data = bswap(*(u32*)(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF))); const u32 data = Common::swap32(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF));
EFB_Write(data, memAddr + i); EFB_Write(data, memAddr + i);
} }
return; return;
@ -678,7 +690,7 @@ void DMA_LCToMemory(const u32 memAddr, const u32 cacheAddr, const u32 numBlocks)
{ {
for (u32 i = 0; i < 32 * numBlocks; i += 4) for (u32 i = 0; i < 32 * numBlocks; i += 4)
{ {
u32 data = bswap(*(u32*)(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF))); const u32 data = Common::swap32(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF));
Memory::mmio_mapping->Write(memAddr + i, data); Memory::mmio_mapping->Write(memAddr + i, data);
} }
return; return;
@ -703,8 +715,8 @@ void DMA_MemoryToLC(const u32 cacheAddr, const u32 memAddr, const u32 numBlocks)
{ {
for (u32 i = 0; i < 32 * numBlocks; i += 4) for (u32 i = 0; i < 32 * numBlocks; i += 4)
{ {
u32 data = EFB_Read(memAddr + i); const u32 data = Common::swap32(EFB_Read(memAddr + i));
*(u32*)(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF)) = bswap(data); std::memcpy(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF), &data, sizeof(u32));
} }
return; return;
} }
@ -715,8 +727,8 @@ void DMA_MemoryToLC(const u32 cacheAddr, const u32 memAddr, const u32 numBlocks)
{ {
for (u32 i = 0; i < 32 * numBlocks; i += 4) for (u32 i = 0; i < 32 * numBlocks; i += 4)
{ {
u32 data = Memory::mmio_mapping->Read<u32>(memAddr + i); const u32 data = Common::swap32(Memory::mmio_mapping->Read<u32>(memAddr + i));
*(u32*)(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF)) = bswap(data); std::memcpy(Memory::m_pL1Cache + ((cacheAddr + i) & 0x3FFFF), &data, sizeof(u32));
} }
return; return;
} }
@ -1073,7 +1085,7 @@ static TranslateAddressResult TranslatePageAddress(const u32 address, const XChe
// hash function no 1 "xor" .360 // hash function no 1 "xor" .360
u32 hash = (VSID ^ page_index); u32 hash = (VSID ^ page_index);
u32 pte1 = bswap((VSID << 7) | api | PTE1_V); u32 pte1 = Common::swap32((VSID << 7) | api | PTE1_V);
for (int hash_func = 0; hash_func < 2; hash_func++) for (int hash_func = 0; hash_func < 2; hash_func++)
{ {
@ -1089,10 +1101,13 @@ static TranslateAddressResult TranslatePageAddress(const u32 address, const XChe
for (int i = 0; i < 8; i++, pteg_addr += 8) for (int i = 0; i < 8; i++, pteg_addr += 8)
{ {
if (pte1 == *(u32*)&Memory::physical_base[pteg_addr]) u32 pteg;
std::memcpy(&pteg, &Memory::physical_base[pteg_addr], sizeof(u32));
if (pte1 == pteg)
{ {
UPTE2 PTE2; UPTE2 PTE2;
PTE2.Hex = bswap((*(u32*)&Memory::physical_base[pteg_addr + 4])); PTE2.Hex = Common::swap32(&Memory::physical_base[pteg_addr + 4]);
// set the access bits // set the access bits
switch (flag) switch (flag)
@ -1113,7 +1128,10 @@ static TranslateAddressResult TranslatePageAddress(const u32 address, const XChe
} }
if (!IsNoExceptionFlag(flag)) if (!IsNoExceptionFlag(flag))
*(u32*)&Memory::physical_base[pteg_addr + 4] = bswap(PTE2.Hex); {
const u32 swapped_pte2 = Common::swap32(PTE2.Hex);
std::memcpy(&Memory::physical_base[pteg_addr + 4], &swapped_pte2, sizeof(u32));
}
// We already updated the TLB entry if this was caused by a C bit. // We already updated the TLB entry if this was caused by a C bit.
if (res != TLB_UPDATE_C) if (res != TLB_UPDATE_C)