5701 lines
193 KiB
C++
5701 lines
193 KiB
C++
/****************************************************************************
|
|
* *
|
|
* Project64 - A Nintendo 64 emulator. *
|
|
* http://www.pj64-emu.com/ *
|
|
* Copyright (C) 2012 Project64. All rights reserved. *
|
|
* *
|
|
* License: *
|
|
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
|
* *
|
|
****************************************************************************/
|
|
#include "stdafx.h"
|
|
#include "MemoryVirtualMem.h"
|
|
#include <Project64-core/N64System/SystemGlobals.h>
|
|
#include <Project64-core/N64System/N64RomClass.h>
|
|
#include <Project64-core/N64System/N64Class.h>
|
|
#include <Project64-core/N64System/Recompiler/x86CodeLog.h>
|
|
#include <Project64-core/N64System/Mips/OpcodeName.h>
|
|
#include <Windows.h>
|
|
|
|
uint32_t RegModValue;
|
|
|
|
uint8_t * CMipsMemoryVM::m_Reserve1 = NULL;
|
|
uint8_t * CMipsMemoryVM::m_Reserve2 = NULL;
|
|
uint32_t CMipsMemoryVM::m_MemLookupAddress = 0;
|
|
MIPS_DWORD CMipsMemoryVM::m_MemLookupValue;
|
|
bool CMipsMemoryVM::m_MemLookupValid = true;
|
|
|
|
CMipsMemoryVM::CMipsMemoryVM(CMipsMemory_CallBack * CallBack, bool SavesReadOnly) :
|
|
|
|
CPifRam(SavesReadOnly),
|
|
CFlashram(SavesReadOnly),
|
|
CSram(SavesReadOnly),
|
|
CDMA(*this, *this),
|
|
m_CBClass(CallBack),
|
|
m_RomMapped(false),
|
|
m_Rom(NULL),
|
|
m_RomSize(0),
|
|
m_RomWrittenTo(false),
|
|
m_RomWroteValue(0),
|
|
m_HalfLine(0),
|
|
m_HalfLineCheck(false),
|
|
m_FieldSerration(0),
|
|
m_TempValue(0),
|
|
m_TLB_ReadMap(NULL),
|
|
m_TLB_WriteMap(NULL)
|
|
{
|
|
g_Settings->RegisterChangeCB(Game_RDRamSize, this, (CSettings::SettingChangedFunc)RdramChanged);
|
|
m_RDRAM = NULL;
|
|
m_DMEM = NULL;
|
|
m_IMEM = NULL;
|
|
}
|
|
|
|
uint32_t swap32by8(uint32_t word)
|
|
{
|
|
const uint32_t swapped =
|
|
#if defined(_MSC_VER)
|
|
_byteswap_ulong(word)
|
|
#elif defined(__GNUC__)
|
|
__builtin_bswap32(word)
|
|
#else
|
|
(word & 0x000000FFul) << 24
|
|
| (word & 0x0000FF00ul) << 8
|
|
| (word & 0x00FF0000ul) >> 8
|
|
| (word & 0xFF000000ul) >> 24
|
|
#endif
|
|
;
|
|
return (swapped & 0xFFFFFFFFul);
|
|
}
|
|
|
|
CMipsMemoryVM::~CMipsMemoryVM()
|
|
{
|
|
g_Settings->UnregisterChangeCB(Game_RDRamSize, this, (CSettings::SettingChangedFunc)RdramChanged);
|
|
FreeMemory();
|
|
}
|
|
|
|
void CMipsMemoryVM::Reset(bool /*EraseMemory*/)
|
|
{
|
|
if (m_TLB_ReadMap)
|
|
{
|
|
size_t address;
|
|
|
|
memset(m_TLB_ReadMap, 0, 0xFFFFF * sizeof(size_t));
|
|
memset(m_TLB_WriteMap, 0, 0xFFFFF * sizeof(size_t));
|
|
for (address = 0x80000000; address < 0xC0000000; address += 0x1000)
|
|
{
|
|
m_TLB_ReadMap[address >> 12] = ((size_t)m_RDRAM + (address & 0x1FFFFFFF)) - address;
|
|
m_TLB_WriteMap[address >> 12] = ((size_t)m_RDRAM + (address & 0x1FFFFFFF)) - address;
|
|
}
|
|
|
|
if (g_Settings->LoadDword(Rdb_TLB_VAddrStart) != 0)
|
|
{
|
|
size_t Start = g_Settings->LoadDword(Rdb_TLB_VAddrStart); //0x7F000000;
|
|
size_t Len = g_Settings->LoadDword(Rdb_TLB_VAddrLen); //0x01000000;
|
|
size_t PAddr = g_Settings->LoadDword(Rdb_TLB_PAddrStart); //0x10034b30;
|
|
size_t End = Start + Len;
|
|
for (address = Start; address < End; address += 0x1000)
|
|
{
|
|
m_TLB_ReadMap[address >> 12] = ((size_t)m_RDRAM + (address - Start + PAddr)) - address;
|
|
m_TLB_WriteMap[address >> 12] = ((size_t)m_RDRAM + (address - Start + PAddr)) - address;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::ReserveMemory()
|
|
{
|
|
m_Reserve1 = (uint8_t *)VirtualAlloc(NULL, 0x20000000, MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE);
|
|
if (g_Settings->LoadBool(Debugger_Enabled))
|
|
{
|
|
m_Reserve2 = (uint8_t *)VirtualAlloc(NULL, 0x20000000, MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE);
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::FreeReservedMemory()
|
|
{
|
|
if (m_Reserve1)
|
|
{
|
|
VirtualFree(m_Reserve1, 0, MEM_RELEASE);
|
|
m_Reserve1 = NULL;
|
|
}
|
|
if (m_Reserve2)
|
|
{
|
|
VirtualFree(m_Reserve2, 0, MEM_RELEASE);
|
|
m_Reserve2 = NULL;
|
|
}
|
|
}
|
|
|
|
bool CMipsMemoryVM::Initialize()
|
|
{
|
|
if (m_RDRAM != NULL)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (m_Reserve1)
|
|
{
|
|
m_RDRAM = m_Reserve1; m_Reserve1 = NULL;
|
|
}
|
|
if (m_RDRAM == NULL && m_Reserve2)
|
|
{
|
|
m_RDRAM = m_Reserve2; m_Reserve2 = NULL;
|
|
}
|
|
if (m_RDRAM == NULL)
|
|
{
|
|
m_RDRAM = (uint8_t *)VirtualAlloc(NULL, 0x20000000, MEM_RESERVE | MEM_TOP_DOWN, PAGE_READWRITE);
|
|
}
|
|
if (m_RDRAM == NULL)
|
|
{
|
|
WriteTrace(TraceN64System, TraceError, "Failed to Reserve RDRAM (Size: 0x%X)", 0x20000000);
|
|
FreeMemory();
|
|
return false;
|
|
}
|
|
|
|
m_AllocatedRdramSize = g_Settings->LoadDword(Game_RDRamSize);
|
|
if (VirtualAlloc(m_RDRAM, m_AllocatedRdramSize, MEM_COMMIT, PAGE_READWRITE) == NULL)
|
|
{
|
|
WriteTrace(TraceN64System, TraceError, "Failed to Allocate RDRAM (Size: 0x%X)", m_AllocatedRdramSize);
|
|
FreeMemory();
|
|
return false;
|
|
}
|
|
|
|
if (VirtualAlloc(m_RDRAM + 0x04000000, 0x2000, MEM_COMMIT, PAGE_READWRITE) == NULL)
|
|
{
|
|
WriteTrace(TraceN64System, TraceError, "Failed to Allocate DMEM/IMEM (Size: 0x%X)", 0x2000);
|
|
FreeMemory();
|
|
return false;
|
|
}
|
|
|
|
m_DMEM = (uint8_t *)(m_RDRAM + 0x04000000);
|
|
m_IMEM = (uint8_t *)(m_RDRAM + 0x04001000);
|
|
|
|
if (g_Settings->LoadBool(Game_LoadRomToMemory))
|
|
{
|
|
m_RomMapped = true;
|
|
m_Rom = m_RDRAM + 0x10000000;
|
|
m_RomSize = g_Rom->GetRomSize();
|
|
if (VirtualAlloc(m_Rom, g_Rom->GetRomSize(), MEM_COMMIT, PAGE_READWRITE) == NULL)
|
|
{
|
|
WriteTrace(TraceN64System, TraceError, "Failed to Allocate Rom (Size: 0x%X)", g_Rom->GetRomSize());
|
|
FreeMemory();
|
|
return false;
|
|
}
|
|
memcpy(m_Rom, g_Rom->GetRomAddress(), g_Rom->GetRomSize());
|
|
|
|
DWORD OldProtect;
|
|
VirtualProtect(m_Rom, g_Rom->GetRomSize(), PAGE_READONLY, &OldProtect);
|
|
}
|
|
else
|
|
{
|
|
m_RomMapped = false;
|
|
m_Rom = g_Rom->GetRomAddress();
|
|
m_RomSize = g_Rom->GetRomSize();
|
|
}
|
|
CPifRam::Reset();
|
|
|
|
m_TLB_ReadMap = (size_t *)VirtualAlloc(
|
|
NULL,
|
|
0xFFFFF * sizeof(size_t),
|
|
MEM_RESERVE | MEM_COMMIT,
|
|
PAGE_READWRITE
|
|
);
|
|
if (m_TLB_ReadMap == NULL)
|
|
{
|
|
WriteTrace(TraceN64System, TraceError, "Failed to Allocate m_TLB_ReadMap (Size: 0x%X)", 0xFFFFF * sizeof(size_t));
|
|
FreeMemory();
|
|
return false;
|
|
}
|
|
|
|
m_TLB_WriteMap = (size_t *)VirtualAlloc(
|
|
NULL,
|
|
0xFFFFF * sizeof(size_t),
|
|
MEM_RESERVE | MEM_COMMIT,
|
|
PAGE_READWRITE
|
|
);
|
|
if (m_TLB_WriteMap == NULL)
|
|
{
|
|
WriteTrace(TraceN64System, TraceError, "Failed to Allocate m_TLB_WriteMap (Size: 0x%X)", 0xFFFFF * sizeof(size_t));
|
|
FreeMemory();
|
|
return false;
|
|
}
|
|
Reset(false);
|
|
return true;
|
|
}
|
|
|
|
void CMipsMemoryVM::FreeMemory()
|
|
{
|
|
if (m_RDRAM)
|
|
{
|
|
if (VirtualFree(m_RDRAM, 0x20000000, MEM_DECOMMIT) != 0)
|
|
{
|
|
if (m_Reserve1 == NULL)
|
|
{
|
|
m_Reserve1 = m_RDRAM;
|
|
}
|
|
else if (m_Reserve2 == NULL)
|
|
{
|
|
m_Reserve2 = m_RDRAM;
|
|
}
|
|
else
|
|
{
|
|
VirtualFree(m_RDRAM, 0, MEM_RELEASE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
VirtualFree(m_RDRAM, 0, MEM_RELEASE);
|
|
}
|
|
m_RDRAM = NULL;
|
|
m_IMEM = NULL;
|
|
m_DMEM = NULL;
|
|
}
|
|
if (m_TLB_ReadMap)
|
|
{
|
|
VirtualFree(m_TLB_ReadMap, 0, MEM_RELEASE);
|
|
m_TLB_ReadMap = NULL;
|
|
}
|
|
if (m_TLB_WriteMap)
|
|
{
|
|
VirtualFree(m_TLB_WriteMap, 0, MEM_RELEASE);
|
|
m_TLB_WriteMap = NULL;
|
|
}
|
|
CPifRam::Reset();
|
|
}
|
|
|
|
uint8_t * CMipsMemoryVM::Rdram()
|
|
{
|
|
return m_RDRAM;
|
|
}
|
|
|
|
uint32_t CMipsMemoryVM::RdramSize()
|
|
{
|
|
return m_AllocatedRdramSize;
|
|
}
|
|
|
|
uint8_t * CMipsMemoryVM::Dmem()
|
|
{
|
|
return m_DMEM;
|
|
}
|
|
|
|
uint8_t * CMipsMemoryVM::Imem()
|
|
{
|
|
return m_IMEM;
|
|
}
|
|
|
|
uint8_t * CMipsMemoryVM::PifRam()
|
|
{
|
|
return m_PifRam;
|
|
}
|
|
|
|
bool CMipsMemoryVM::LB_VAddr(uint32_t VAddr, uint8_t& Value)
|
|
{
|
|
if (m_TLB_ReadMap[VAddr >> 12] == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Value = *(uint8_t*)(m_TLB_ReadMap[VAddr >> 12] + (VAddr ^ 3));
|
|
return true;
|
|
}
|
|
|
|
bool CMipsMemoryVM::LH_VAddr(uint32_t VAddr, uint16_t& Value)
|
|
{
|
|
if (m_TLB_ReadMap[VAddr >> 12] == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Value = *(uint16_t*)(m_TLB_ReadMap[VAddr >> 12] + (VAddr ^ 2));
|
|
return true;
|
|
}
|
|
|
|
bool CMipsMemoryVM::LW_VAddr(uint32_t VAddr, uint32_t& Value)
|
|
{
|
|
if (VAddr >= 0xA3F00000 && VAddr < 0xC0000000)
|
|
{
|
|
if ((VAddr & 0xFFFFE000ul) != 0xA4000000ul) // !(A4000000 <= addr < A4002000)
|
|
{
|
|
VAddr &= 0x1FFFFFFF;
|
|
LW_NonMemory(VAddr, &Value);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
uint8_t* BaseAddress = (uint8_t*)m_TLB_ReadMap[VAddr >> 12];
|
|
if (BaseAddress == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Value = *(uint32_t*)(BaseAddress + VAddr);
|
|
|
|
// if (LookUpMode == FuncFind_ChangeMemory)
|
|
// {
|
|
// g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
// if ( (Command.Hex >> 16) == 0x7C7C)
|
|
// {
|
|
// Command.Hex = OrigMem[(Command.Hex & 0xFFFF)].OriginalValue;
|
|
// }
|
|
// }
|
|
return true;
|
|
}
|
|
|
|
bool CMipsMemoryVM::LD_VAddr(uint32_t VAddr, uint64_t& Value)
|
|
{
|
|
if (m_TLB_ReadMap[VAddr >> 12] == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
*((uint32_t*)(&Value) + 1) = *(uint32_t*)(m_TLB_ReadMap[VAddr >> 12] + VAddr);
|
|
*((uint32_t*)(&Value) + 0) = *(uint32_t*)(m_TLB_ReadMap[VAddr >> 12] + VAddr + 4);
|
|
return true;
|
|
}
|
|
|
|
bool CMipsMemoryVM::LB_PAddr(uint32_t PAddr, uint8_t& Value)
|
|
{
|
|
if (PAddr < RdramSize())
|
|
{
|
|
Value = *(uint8_t*)(m_RDRAM + (PAddr ^ 3));
|
|
return true;
|
|
}
|
|
|
|
if (PAddr > 0x18000000)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
return false;
|
|
}
|
|
|
|
bool CMipsMemoryVM::LH_PAddr(uint32_t PAddr, uint16_t& Value)
|
|
{
|
|
if (PAddr < RdramSize())
|
|
{
|
|
Value = *(uint16_t*)(m_RDRAM + (PAddr ^ 2));
|
|
return true;
|
|
}
|
|
|
|
if (PAddr > 0x18000000)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
return false;
|
|
}
|
|
|
|
bool CMipsMemoryVM::LW_PAddr(uint32_t PAddr, uint32_t& Value)
|
|
{
|
|
if (PAddr < RdramSize())
|
|
{
|
|
Value = *(uint32_t*)(m_RDRAM + PAddr);
|
|
return true;
|
|
}
|
|
|
|
if (PAddr > 0x18000000)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
return false;
|
|
}
|
|
|
|
bool CMipsMemoryVM::LD_PAddr(uint32_t PAddr, uint64_t& Value)
|
|
{
|
|
if (PAddr < RdramSize())
|
|
{
|
|
*((uint32_t*)(&Value) + 1) = *(uint32_t*)(m_RDRAM + PAddr);
|
|
*((uint32_t*)(&Value) + 0) = *(uint32_t*)(m_RDRAM + PAddr + 4);
|
|
return true;
|
|
}
|
|
|
|
if (PAddr > 0x18000000)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
return false;
|
|
}
|
|
|
|
bool CMipsMemoryVM::SB_VAddr(uint32_t VAddr, uint8_t Value)
|
|
{
|
|
if (m_TLB_WriteMap[VAddr >> 12] == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
*(uint8_t*)(m_TLB_WriteMap[VAddr >> 12] + (VAddr ^ 3)) = Value;
|
|
return true;
|
|
}
|
|
|
|
bool CMipsMemoryVM::SH_VAddr(uint32_t VAddr, uint16_t Value)
|
|
{
|
|
if (m_TLB_WriteMap[VAddr >> 12] == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
*(uint16_t*)(m_TLB_WriteMap[VAddr >> 12] + (VAddr ^ 2)) = Value;
|
|
return true;
|
|
}
|
|
|
|
bool CMipsMemoryVM::SW_VAddr(uint32_t VAddr, uint32_t Value)
|
|
{
|
|
if (VAddr >= 0xA3F00000 && VAddr < 0xC0000000)
|
|
{
|
|
if (VAddr < 0xA4000000 || VAddr >= 0xA4002000)
|
|
{
|
|
VAddr &= 0x1FFFFFFF;
|
|
SW_NonMemory(VAddr, Value);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (m_TLB_WriteMap[VAddr >> 12] == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
*(uint32_t*)(m_TLB_WriteMap[VAddr >> 12] + VAddr) = Value;
|
|
return true;
|
|
}
|
|
|
|
bool CMipsMemoryVM::SD_VAddr(uint32_t VAddr, uint64_t Value)
|
|
{
|
|
if (m_TLB_WriteMap[VAddr >> 12] == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
*(uint32_t*)(m_TLB_WriteMap[VAddr >> 12] + VAddr + 0) = *((uint32_t*)(&Value) + 1);
|
|
*(uint32_t*)(m_TLB_WriteMap[VAddr >> 12] + VAddr + 4) = *((uint32_t*)(&Value));
|
|
return true;
|
|
}
|
|
|
|
bool CMipsMemoryVM::SB_PAddr(uint32_t PAddr, uint8_t Value)
|
|
{
|
|
if (PAddr < RdramSize())
|
|
{
|
|
*(uint8_t*)(m_RDRAM + (PAddr ^ 3)) = Value;
|
|
return true;
|
|
}
|
|
|
|
if (PAddr > 0x18000000)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
return false;
|
|
}
|
|
|
|
bool CMipsMemoryVM::SH_PAddr(uint32_t PAddr, uint16_t Value)
|
|
{
|
|
if (PAddr < RdramSize())
|
|
{
|
|
*(uint16_t*)(m_RDRAM + (PAddr ^ 2)) = Value;
|
|
return true;
|
|
}
|
|
|
|
if (PAddr > 0x18000000)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
return false;
|
|
}
|
|
|
|
bool CMipsMemoryVM::SW_PAddr(uint32_t PAddr, uint32_t Value)
|
|
{
|
|
if (PAddr < RdramSize())
|
|
{
|
|
*(uint32_t*)(m_RDRAM + PAddr) = Value;
|
|
return true;
|
|
}
|
|
|
|
if (PAddr > 0x18000000)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
return false;
|
|
}
|
|
|
|
bool CMipsMemoryVM::SD_PAddr(uint32_t PAddr, uint64_t Value)
|
|
{
|
|
if (PAddr < RdramSize())
|
|
{
|
|
*(uint32_t*)(m_RDRAM + PAddr + 0) = *((uint32_t*)(&Value) + 1);
|
|
*(uint32_t*)(m_RDRAM + PAddr + 4) = *((uint32_t*)(&Value));
|
|
return true;
|
|
}
|
|
|
|
if (PAddr > 0x18000000)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
return false;
|
|
}
|
|
|
|
bool CMipsMemoryVM::ValidVaddr(uint32_t VAddr) const
|
|
{
|
|
return m_TLB_ReadMap[VAddr >> 12] != 0;
|
|
}
|
|
|
|
bool CMipsMemoryVM::VAddrToRealAddr(uint32_t VAddr, void * &RealAddress) const
|
|
{
|
|
if (m_TLB_ReadMap[VAddr >> 12] == 0)
|
|
{
|
|
return false;
|
|
}
|
|
RealAddress = (uint8_t *)(m_TLB_ReadMap[VAddr >> 12] + VAddr);
|
|
return true;
|
|
}
|
|
|
|
bool CMipsMemoryVM::TranslateVaddr(uint32_t VAddr, uint32_t &PAddr) const
|
|
{
|
|
//Change the Virtual address to a Physical Address
|
|
if (m_TLB_ReadMap[VAddr >> 12] == 0)
|
|
{
|
|
return false;
|
|
}
|
|
PAddr = (uint32_t)((uint8_t *)(m_TLB_ReadMap[VAddr >> 12] + VAddr) - m_RDRAM);
|
|
return true;
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LB(x86Reg Reg, uint32_t VAddr, bool SignExtend)
|
|
{
|
|
uint32_t PAddr;
|
|
char VarName[100];
|
|
|
|
if (VAddr < 0x80000000 || VAddr >= 0xC0000000)
|
|
{
|
|
if (!g_System->bUseTlb())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
return;
|
|
}
|
|
|
|
x86Reg TlbMappReg = Map_TempReg(x86_Any, -1, false);
|
|
MoveConstToX86reg(VAddr >> 12, TlbMappReg);
|
|
x86Reg AddrReg = Map_TempReg(x86_Any, -1, false);
|
|
MoveConstToX86reg(VAddr, AddrReg);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TlbMappReg, TlbMappReg, 4);
|
|
CompileReadTLBMiss(AddrReg, TlbMappReg);
|
|
if (SignExtend)
|
|
{
|
|
MoveSxByteX86regPointerToX86reg(AddrReg, TlbMappReg, Reg);
|
|
}
|
|
else
|
|
{
|
|
MoveZxByteX86regPointerToX86reg(AddrReg, TlbMappReg, Reg);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!TranslateVaddr(VAddr, PAddr))
|
|
{
|
|
MoveConstToX86reg(0, Reg);
|
|
CPU_Message("Compile_LB\nFailed to translate address %08X", VAddr);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
return;
|
|
}
|
|
|
|
switch (PAddr & 0xFFF00000)
|
|
{
|
|
case 0x00000000:
|
|
case 0x00100000:
|
|
case 0x00200000:
|
|
case 0x00300000:
|
|
case 0x00400000:
|
|
case 0x00500000:
|
|
case 0x00600000:
|
|
case 0x00700000:
|
|
case 0x10000000:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
if (SignExtend)
|
|
{
|
|
MoveSxVariableToX86regByte(PAddr + m_RDRAM, VarName, Reg);
|
|
}
|
|
else
|
|
{
|
|
MoveZxVariableToX86regByte(PAddr + m_RDRAM, VarName, Reg);
|
|
}
|
|
break;
|
|
default:
|
|
MoveConstToX86reg(0, Reg);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to compile address: %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LH(x86Reg Reg, uint32_t VAddr, bool SignExtend)
|
|
{
|
|
char VarName[100];
|
|
uint32_t PAddr;
|
|
|
|
if (VAddr < 0x80000000 || VAddr >= 0xC0000000)
|
|
{
|
|
if (!g_System->bUseTlb())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
return;
|
|
}
|
|
|
|
x86Reg TlbMappReg = Map_TempReg(x86_Any, -1, false);
|
|
MoveConstToX86reg(VAddr >> 12, TlbMappReg);
|
|
x86Reg AddrReg = Map_TempReg(x86_Any, -1, false);
|
|
MoveConstToX86reg(VAddr, AddrReg);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TlbMappReg, TlbMappReg, 4);
|
|
CompileReadTLBMiss(AddrReg, TlbMappReg);
|
|
if (SignExtend)
|
|
{
|
|
MoveSxHalfX86regPointerToX86reg(AddrReg, TlbMappReg, Reg);
|
|
}
|
|
else
|
|
{
|
|
MoveZxHalfX86regPointerToX86reg(AddrReg, TlbMappReg, Reg);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!TranslateVaddr(VAddr, PAddr))
|
|
{
|
|
MoveConstToX86reg(0, Reg);
|
|
CPU_Message("Compile_LH\nFailed to translate address %08X", VAddr);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
return;
|
|
}
|
|
|
|
switch (PAddr & 0xFFF00000)
|
|
{
|
|
case 0x00000000:
|
|
case 0x00100000:
|
|
case 0x00200000:
|
|
case 0x00300000:
|
|
case 0x00400000:
|
|
case 0x00500000:
|
|
case 0x00600000:
|
|
case 0x00700000:
|
|
case 0x10000000:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
if (SignExtend)
|
|
{
|
|
MoveSxVariableToX86regHalf(PAddr + m_RDRAM, VarName, Reg);
|
|
}
|
|
else
|
|
{
|
|
MoveZxVariableToX86regHalf(PAddr + m_RDRAM, VarName, Reg);
|
|
}
|
|
break;
|
|
default:
|
|
MoveConstToX86reg(0, Reg);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to compile address: %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LW(x86Reg Reg, uint32_t VAddr)
|
|
{
|
|
char VarName[100];
|
|
uint32_t PAddr;
|
|
|
|
m_RegWorkingSet.SetX86Protected(Reg, true);
|
|
if (VAddr < 0x80000000 || VAddr >= 0xC0000000)
|
|
{
|
|
if (!g_System->bUseTlb())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
return;
|
|
}
|
|
|
|
x86Reg TlbMappReg = Map_TempReg(x86_Any, -1, false);
|
|
MoveConstToX86reg(VAddr >> 12, TlbMappReg);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TlbMappReg, TlbMappReg, 4);
|
|
CompileReadTLBMiss(VAddr, TlbMappReg);
|
|
AddConstToX86Reg(TlbMappReg, VAddr);
|
|
MoveX86PointerToX86reg(Reg, TlbMappReg);
|
|
}
|
|
else
|
|
{
|
|
if (!TranslateVaddr(VAddr, PAddr))
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
|
|
switch (PAddr & 0xFFF00000)
|
|
{
|
|
case 0x00000000:
|
|
case 0x00100000:
|
|
case 0x00200000:
|
|
case 0x00300000:
|
|
case 0x00400000:
|
|
case 0x00500000:
|
|
case 0x00600000:
|
|
case 0x00700000:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveVariableToX86reg(PAddr + m_RDRAM, VarName, Reg);
|
|
break;
|
|
case 0x04000000:
|
|
if (PAddr < 0x04002000)
|
|
{
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveVariableToX86reg(PAddr + m_RDRAM, VarName, Reg);
|
|
break;
|
|
}
|
|
switch (PAddr)
|
|
{
|
|
case 0x04040010: MoveVariableToX86reg(&g_Reg->SP_STATUS_REG, "SP_STATUS_REG", Reg); break;
|
|
case 0x04040014: MoveVariableToX86reg(&g_Reg->SP_DMA_FULL_REG, "SP_DMA_FULL_REG", Reg); break;
|
|
case 0x04040018: MoveVariableToX86reg(&g_Reg->SP_DMA_BUSY_REG, "SP_DMA_BUSY_REG", Reg); break;
|
|
case 0x0404001C:
|
|
MoveVariableToX86reg(&g_Reg->SP_SEMAPHORE_REG, "SP_SEMAPHORE_REG", Reg);
|
|
MoveConstToVariable(1, &g_Reg->SP_SEMAPHORE_REG, "SP_SEMAPHORE_REG");
|
|
break;
|
|
case 0x04080000: MoveVariableToX86reg(&g_Reg->SP_PC_REG, "SP_PC_REG", Reg); break;
|
|
default:
|
|
MoveConstToX86reg(0, Reg);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address: %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04100000:
|
|
{
|
|
static uint32_t TempValue = 0;
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
PushImm32("TempValue", (uint32_t)&TempValue);
|
|
PushImm32(PAddr);
|
|
MoveConstToX86reg((ULONG)((CMipsMemoryVM *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CMipsMemoryVM::LW_NonMemory), "CMipsMemoryVM::LW_NonMemory");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
MoveVariableToX86reg(&TempValue, "TempValue", Reg);
|
|
}
|
|
break;
|
|
case 0x04300000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04300000: MoveVariableToX86reg(&g_Reg->MI_MODE_REG, "MI_MODE_REG", Reg); break;
|
|
case 0x04300004: MoveVariableToX86reg(&g_Reg->MI_VERSION_REG, "MI_VERSION_REG", Reg); break;
|
|
case 0x04300008: MoveVariableToX86reg(&g_Reg->MI_INTR_REG, "MI_INTR_REG", Reg); break;
|
|
case 0x0430000C: MoveVariableToX86reg(&g_Reg->MI_INTR_MASK_REG, "MI_INTR_MASK_REG", Reg); break;
|
|
default:
|
|
MoveConstToX86reg(0, Reg);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory)) { g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address: %08X", VAddr).ToUTF16().c_str()); }
|
|
}
|
|
break;
|
|
case 0x04400000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04400010:
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)this, x86_ECX);
|
|
Call_Direct(AddressOf(&CMipsMemoryVM::UpdateHalfLine), "CMipsMemoryVM::UpdateHalfLine");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
MoveVariableToX86reg(&m_HalfLine, "m_HalfLine", Reg);
|
|
break;
|
|
default:
|
|
MoveConstToX86reg(0, Reg);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address: %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04500000: /* AI registers */
|
|
switch (PAddr)
|
|
{
|
|
case 0x04500004:
|
|
if (g_System->bFixedAudio())
|
|
{
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)g_Audio, x86_ECX);
|
|
Call_Direct(AddressOf(&CAudio::GetLength), "CAudio::GetLength");
|
|
MoveX86regToVariable(x86_EAX, &m_TempValue, "m_TempValue");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
MoveVariableToX86reg(&m_TempValue, "m_TempValue", Reg);
|
|
}
|
|
else
|
|
{
|
|
if (g_Plugins->Audio()->AiReadLength != NULL)
|
|
{
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
Call_Direct(g_Plugins->Audio()->AiReadLength, "AiReadLength");
|
|
MoveX86regToVariable(x86_EAX, &m_TempValue, "m_TempValue");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
MoveVariableToX86reg(&m_TempValue, "m_TempValue", Reg);
|
|
}
|
|
else
|
|
{
|
|
MoveConstToX86reg(0, Reg);
|
|
}
|
|
}
|
|
break;
|
|
case 0x0450000C:
|
|
if (g_System->bFixedAudio())
|
|
{
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)g_Audio, x86_ECX);
|
|
Call_Direct(AddressOf(&CAudio::GetStatus), "GetStatus");
|
|
MoveX86regToVariable(x86_EAX, &m_TempValue, "m_TempValue");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
MoveVariableToX86reg(&m_TempValue, "m_TempValue", Reg);
|
|
}
|
|
else
|
|
{
|
|
MoveVariableToX86reg(&g_Reg->AI_STATUS_REG, "AI_STATUS_REG", Reg);
|
|
}
|
|
break;
|
|
default:
|
|
MoveConstToX86reg(0, Reg);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address: %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04600000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04600010: MoveVariableToX86reg(&g_Reg->PI_STATUS_REG, "PI_STATUS_REG", Reg); break;
|
|
case 0x04600014: MoveVariableToX86reg(&g_Reg->PI_DOMAIN1_REG, "PI_DOMAIN1_REG", Reg); break;
|
|
case 0x04600018: MoveVariableToX86reg(&g_Reg->PI_BSD_DOM1_PWD_REG, "PI_BSD_DOM1_PWD_REG", Reg); break;
|
|
case 0x0460001C: MoveVariableToX86reg(&g_Reg->PI_BSD_DOM1_PGS_REG, "PI_BSD_DOM1_PGS_REG", Reg); break;
|
|
case 0x04600020: MoveVariableToX86reg(&g_Reg->PI_BSD_DOM1_RLS_REG, "PI_BSD_DOM1_RLS_REG", Reg); break;
|
|
case 0x04600024: MoveVariableToX86reg(&g_Reg->PI_DOMAIN2_REG, "PI_DOMAIN2_REG", Reg); break;
|
|
case 0x04600028: MoveVariableToX86reg(&g_Reg->PI_BSD_DOM2_PWD_REG, "PI_BSD_DOM2_PWD_REG", Reg); break;
|
|
case 0x0460002C: MoveVariableToX86reg(&g_Reg->PI_BSD_DOM2_PGS_REG, "PI_BSD_DOM2_PGS_REG", Reg); break;
|
|
case 0x04600030: MoveVariableToX86reg(&g_Reg->PI_BSD_DOM2_RLS_REG, "PI_BSD_DOM2_RLS_REG", Reg); break;
|
|
default:
|
|
MoveConstToX86reg(0, Reg);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address: %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04700000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x0470000C: MoveVariableToX86reg(&g_Reg->RI_SELECT_REG, "RI_SELECT_REG", Reg); break;
|
|
case 0x04700010: MoveVariableToX86reg(&g_Reg->RI_REFRESH_REG, "RI_REFRESH_REG", Reg); break;
|
|
default:
|
|
MoveConstToX86reg(0, Reg);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address: %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04800000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04800018: MoveVariableToX86reg(&g_Reg->SI_STATUS_REG, "SI_STATUS_REG", Reg); break;
|
|
default:
|
|
MoveConstToX86reg(0, Reg);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address: %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x1FC00000:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveVariableToX86reg(PAddr + m_RDRAM, VarName, Reg);
|
|
break;
|
|
default:
|
|
if ((PAddr & 0xF0000000) == 0x10000000 && (PAddr - 0x10000000) < m_RomSize)
|
|
{
|
|
// read from rom
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveVariableToX86reg(PAddr + m_RDRAM, VarName, Reg);
|
|
}
|
|
else
|
|
{
|
|
MoveConstToX86reg(((PAddr & 0xFFFF) << 16) | (PAddr & 0xFFFF), Reg);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
CPU_Message(__FUNCTION__ "\nFailed to translate address: %08X", VAddr);
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address: %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SB_Const(uint8_t Value, uint32_t VAddr)
|
|
{
|
|
char VarName[100];
|
|
uint32_t PAddr;
|
|
|
|
if (VAddr < 0x80000000 || VAddr >= 0xC0000000)
|
|
{
|
|
x86Reg TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
x86Reg TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveConstToX86reg(VAddr, TempReg1);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_WriteMap, "m_TLB_WriteMap", TempReg2, TempReg2, 4);
|
|
CompileWriteTLBMiss(TempReg1, TempReg2);
|
|
MoveConstByteToX86regPointer(Value, TempReg1, TempReg2);
|
|
return;
|
|
}
|
|
|
|
if (!TranslateVaddr(VAddr, PAddr))
|
|
{
|
|
CPU_Message("Compile_SB\nFailed to translate address: %08X", VAddr);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory)) { g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address: %08X", VAddr).ToUTF16().c_str()); }
|
|
return;
|
|
}
|
|
|
|
switch (PAddr & 0xFFF00000)
|
|
{
|
|
case 0x00000000:
|
|
case 0x00100000:
|
|
case 0x00200000:
|
|
case 0x00300000:
|
|
case 0x00400000:
|
|
case 0x00500000:
|
|
case 0x00600000:
|
|
case 0x00700000:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveConstByteToVariable(Value, PAddr + m_RDRAM, VarName);
|
|
break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store %02X in %08X?", Value, VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SB_Register(x86Reg Reg, uint32_t VAddr)
|
|
{
|
|
char VarName[100];
|
|
uint32_t PAddr;
|
|
|
|
if (VAddr < 0x80000000 || VAddr >= 0xC0000000)
|
|
{
|
|
m_RegWorkingSet.SetX86Protected(Reg, true);
|
|
|
|
x86Reg TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
x86Reg TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveConstToX86reg(VAddr, TempReg1);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_WriteMap, "m_TLB_WriteMap", TempReg2, TempReg2, 4);
|
|
CompileWriteTLBMiss(TempReg1, TempReg2);
|
|
MoveX86regByteToX86regPointer(Reg, TempReg1, TempReg2);
|
|
return;
|
|
}
|
|
|
|
if (!TranslateVaddr(VAddr, PAddr))
|
|
{
|
|
CPU_Message("Compile_SB\nFailed to translate address: %08X", VAddr);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address: %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
return;
|
|
}
|
|
|
|
switch (PAddr & 0xFFF00000)
|
|
{
|
|
case 0x00000000:
|
|
case 0x00100000:
|
|
case 0x00200000:
|
|
case 0x00300000:
|
|
case 0x00400000:
|
|
case 0x00500000:
|
|
case 0x00600000:
|
|
case 0x00700000:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveX86regByteToVariable(Reg, PAddr + m_RDRAM, VarName);
|
|
break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store in %08X?", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SH_Const(uint16_t Value, uint32_t VAddr)
|
|
{
|
|
char VarName[100];
|
|
uint32_t PAddr;
|
|
|
|
if (VAddr < 0x80000000 || VAddr >= 0xC0000000)
|
|
{
|
|
x86Reg TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
x86Reg TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveConstToX86reg(VAddr, TempReg1);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_WriteMap, "m_TLB_WriteMap", TempReg2, TempReg2, 4);
|
|
CompileWriteTLBMiss(TempReg1, TempReg2);
|
|
MoveConstHalfToX86regPointer(Value, TempReg1, TempReg2);
|
|
return;
|
|
}
|
|
|
|
if (!TranslateVaddr(VAddr, PAddr)) {
|
|
CPU_Message("Compile_SH\nFailed to translate address: %08X", VAddr);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address: %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
return;
|
|
}
|
|
|
|
switch (PAddr & 0xFFF00000)
|
|
{
|
|
case 0x00000000:
|
|
case 0x00100000:
|
|
case 0x00200000:
|
|
case 0x00300000:
|
|
case 0x00400000:
|
|
case 0x00500000:
|
|
case 0x00600000:
|
|
case 0x00700000:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveConstHalfToVariable(Value, PAddr + m_RDRAM, VarName);
|
|
break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store %04X in %08X?", Value, VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SH_Register(x86Reg Reg, uint32_t VAddr)
|
|
{
|
|
char VarName[100];
|
|
uint32_t PAddr;
|
|
|
|
if (VAddr < 0x80000000 || VAddr >= 0xC0000000)
|
|
{
|
|
m_RegWorkingSet.SetX86Protected(Reg, true);
|
|
|
|
x86Reg TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
x86Reg TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveConstToX86reg(VAddr, TempReg1);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_WriteMap, "m_TLB_WriteMap", TempReg2, TempReg2, 4);
|
|
CompileWriteTLBMiss(TempReg1, TempReg2);
|
|
MoveX86regHalfToX86regPointer(Reg, TempReg1, TempReg2);
|
|
return;
|
|
}
|
|
|
|
if (!TranslateVaddr(VAddr, PAddr)) {
|
|
CPU_Message("Compile_SH\nFailed to translate address: %08X", VAddr);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address: %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
return;
|
|
}
|
|
|
|
switch (PAddr & 0xFFF00000)
|
|
{
|
|
case 0x00000000:
|
|
case 0x00100000:
|
|
case 0x00200000:
|
|
case 0x00300000:
|
|
case 0x00400000:
|
|
case 0x00500000:
|
|
case 0x00600000:
|
|
case 0x00700000:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveX86regHalfToVariable(Reg, PAddr + m_RDRAM, VarName);
|
|
break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store in %08X?", PAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SW_Const(uint32_t Value, uint32_t VAddr)
|
|
{
|
|
char VarName[100];
|
|
uint8_t * Jump;
|
|
uint32_t PAddr;
|
|
|
|
if (VAddr < 0x80000000 || VAddr >= 0xC0000000)
|
|
{
|
|
x86Reg TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
x86Reg TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveConstToX86reg(VAddr, TempReg1);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_WriteMap, "m_TLB_WriteMap", TempReg2, TempReg2, 4);
|
|
CompileWriteTLBMiss(TempReg1, TempReg2);
|
|
MoveConstToX86regPointer(Value, TempReg1, TempReg2);
|
|
return;
|
|
}
|
|
|
|
if (!TranslateVaddr(VAddr, PAddr))
|
|
{
|
|
CPU_Message("Compile_SW\nFailed to translate address: %08X", VAddr);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address: %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
return;
|
|
}
|
|
|
|
switch (PAddr & 0xFFF00000)
|
|
{
|
|
case 0x00000000:
|
|
case 0x00100000:
|
|
case 0x00200000:
|
|
case 0x00300000:
|
|
case 0x00400000:
|
|
case 0x00500000:
|
|
case 0x00600000:
|
|
case 0x00700000:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveConstToVariable(Value, PAddr + m_RDRAM, VarName);
|
|
break;
|
|
case 0x03F00000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x03F00000: MoveConstToVariable(Value, &g_Reg->RDRAM_CONFIG_REG, "RDRAM_CONFIG_REG"); break;
|
|
case 0x03F00004: MoveConstToVariable(Value, &g_Reg->RDRAM_DEVICE_ID_REG, "RDRAM_DEVICE_ID_REG"); break;
|
|
case 0x03F00008: MoveConstToVariable(Value, &g_Reg->RDRAM_DELAY_REG, "RDRAM_DELAY_REG"); break;
|
|
case 0x03F0000C: MoveConstToVariable(Value, &g_Reg->RDRAM_MODE_REG, "RDRAM_MODE_REG"); break;
|
|
case 0x03F00010: MoveConstToVariable(Value, &g_Reg->RDRAM_REF_INTERVAL_REG, "RDRAM_REF_INTERVAL_REG"); break;
|
|
case 0x03F00014: MoveConstToVariable(Value, &g_Reg->RDRAM_REF_ROW_REG, "RDRAM_REF_ROW_REG"); break;
|
|
case 0x03F00018: MoveConstToVariable(Value, &g_Reg->RDRAM_RAS_INTERVAL_REG, "RDRAM_RAS_INTERVAL_REG"); break;
|
|
case 0x03F0001C: MoveConstToVariable(Value, &g_Reg->RDRAM_MIN_INTERVAL_REG, "RDRAM_MIN_INTERVAL_REG"); break;
|
|
case 0x03F00020: MoveConstToVariable(Value, &g_Reg->RDRAM_ADDR_SELECT_REG, "RDRAM_ADDR_SELECT_REG"); break;
|
|
case 0x03F00024: MoveConstToVariable(Value, &g_Reg->RDRAM_DEVICE_MANUF_REG, "RDRAM_DEVICE_MANUF_REG"); break;
|
|
case 0x03F04004: break;
|
|
case 0x03F08004: break;
|
|
case 0x03F80004: break;
|
|
case 0x03F80008: break;
|
|
case 0x03F8000C: break;
|
|
case 0x03F80014: break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store %08X in %08X?", Value, VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04000000:
|
|
if (PAddr < 0x04002000)
|
|
{
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveConstToVariable(Value, PAddr + m_RDRAM, VarName);
|
|
break;
|
|
}
|
|
switch (PAddr)
|
|
{
|
|
case 0x04040000: MoveConstToVariable(Value, &g_Reg->SP_MEM_ADDR_REG, "SP_MEM_ADDR_REG"); break;
|
|
case 0x04040004: MoveConstToVariable(Value, &g_Reg->SP_DRAM_ADDR_REG, "SP_DRAM_ADDR_REG"); break;
|
|
case 0x04040008:
|
|
MoveConstToVariable(Value, &g_Reg->SP_RD_LEN_REG, "SP_RD_LEN_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((ULONG)((CDMA *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CDMA::SP_DMA_READ), "CDMA::SP_DMA_READ");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04040010:
|
|
{
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
PushImm32(Value);
|
|
PushImm32(PAddr);
|
|
MoveConstToX86reg((ULONG)((CMipsMemoryVM *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CMipsMemoryVM::SW_NonMemory), "CMipsMemoryVM::SW_NonMemory");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
}
|
|
break;
|
|
case 0x0404001C: MoveConstToVariable(0, &g_Reg->SP_SEMAPHORE_REG, "SP_SEMAPHORE_REG"); break;
|
|
case 0x04080000: MoveConstToVariable(Value & 0xFFC, &g_Reg->SP_PC_REG, "SP_PC_REG"); break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store %08X in %08X?", Value, VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04100000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x0410000C:
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
PushImm32(Value);
|
|
PushImm32(PAddr);
|
|
MoveConstToX86reg((ULONG)((CMipsMemoryVM *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CMipsMemoryVM::SW_NonMemory), "CMipsMemoryVM::SW_NonMemory");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store %08X in %08X?", Value, VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04300000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04300000:
|
|
{
|
|
uint32_t ModValue;
|
|
ModValue = 0x7F;
|
|
if ((Value & MI_CLR_INIT) != 0)
|
|
{
|
|
ModValue |= MI_MODE_INIT;
|
|
}
|
|
if ((Value & MI_CLR_EBUS) != 0)
|
|
{
|
|
ModValue |= MI_MODE_EBUS;
|
|
}
|
|
if ((Value & MI_CLR_RDRAM) != 0)
|
|
{
|
|
ModValue |= MI_MODE_RDRAM;
|
|
}
|
|
if (ModValue != 0)
|
|
{
|
|
AndConstToVariable(~ModValue, &g_Reg->MI_MODE_REG, "MI_MODE_REG");
|
|
}
|
|
|
|
ModValue = (Value & 0x7F);
|
|
if ((Value & MI_SET_INIT) != 0)
|
|
{
|
|
ModValue |= MI_MODE_INIT;
|
|
}
|
|
if ((Value & MI_SET_EBUS) != 0)
|
|
{
|
|
ModValue |= MI_MODE_EBUS;
|
|
}
|
|
if ((Value & MI_SET_RDRAM) != 0)
|
|
{
|
|
ModValue |= MI_MODE_RDRAM;
|
|
}
|
|
if (ModValue != 0) {
|
|
OrConstToVariable(ModValue, &g_Reg->MI_MODE_REG, "MI_MODE_REG");
|
|
}
|
|
if ((Value & MI_CLR_DP_INTR) != 0)
|
|
{
|
|
AndConstToVariable((uint32_t)~MI_INTR_DP, &g_Reg->MI_INTR_REG, "MI_INTR_REG");
|
|
AndConstToVariable((uint32_t)~MI_INTR_DP, &g_Reg->m_GfxIntrReg, "m_GfxIntrReg");
|
|
}
|
|
}
|
|
break;
|
|
case 0x0430000C:
|
|
{
|
|
uint32_t ModValue;
|
|
ModValue = 0;
|
|
if ((Value & MI_INTR_MASK_CLR_SP) != 0)
|
|
{
|
|
ModValue |= MI_INTR_MASK_SP;
|
|
}
|
|
if ((Value & MI_INTR_MASK_CLR_SI) != 0)
|
|
{
|
|
ModValue |= MI_INTR_MASK_SI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_CLR_AI) != 0)
|
|
{
|
|
ModValue |= MI_INTR_MASK_AI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_CLR_VI) != 0)
|
|
{
|
|
ModValue |= MI_INTR_MASK_VI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_CLR_PI) != 0)
|
|
{
|
|
ModValue |= MI_INTR_MASK_PI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_CLR_DP) != 0)
|
|
{
|
|
ModValue |= MI_INTR_MASK_DP;
|
|
}
|
|
if (ModValue != 0)
|
|
{
|
|
AndConstToVariable(~ModValue, &g_Reg->MI_INTR_MASK_REG, "MI_INTR_MASK_REG");
|
|
}
|
|
|
|
ModValue = 0;
|
|
if ((Value & MI_INTR_MASK_SET_SP) != 0)
|
|
{
|
|
ModValue |= MI_INTR_MASK_SP;
|
|
}
|
|
if ((Value & MI_INTR_MASK_SET_SI) != 0)
|
|
{
|
|
ModValue |= MI_INTR_MASK_SI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_SET_AI) != 0)
|
|
{
|
|
ModValue |= MI_INTR_MASK_AI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_SET_VI) != 0)
|
|
{
|
|
ModValue |= MI_INTR_MASK_VI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_SET_PI) != 0)
|
|
{
|
|
ModValue |= MI_INTR_MASK_PI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_SET_DP) != 0)
|
|
{
|
|
ModValue |= MI_INTR_MASK_DP;
|
|
}
|
|
if (ModValue != 0)
|
|
{
|
|
OrConstToVariable(ModValue, &g_Reg->MI_INTR_MASK_REG, "MI_INTR_MASK_REG");
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store %08X in %08X?", Value, VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04400000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04400000:
|
|
if (g_Plugins->Gfx()->ViStatusChanged != NULL)
|
|
{
|
|
CompConstToVariable(Value, &g_Reg->VI_STATUS_REG, "VI_STATUS_REG");
|
|
JeLabel8("Continue", 0);
|
|
Jump = m_RecompPos - 1;
|
|
MoveConstToVariable(Value, &g_Reg->VI_STATUS_REG, "VI_STATUS_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
Call_Direct(g_Plugins->Gfx()->ViStatusChanged, "ViStatusChanged");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
CPU_Message("");
|
|
CPU_Message(" Continue:");
|
|
SetJump8(Jump, m_RecompPos);
|
|
}
|
|
break;
|
|
case 0x04400004: MoveConstToVariable((Value & 0xFFFFFF), &g_Reg->VI_ORIGIN_REG, "VI_ORIGIN_REG"); break;
|
|
case 0x04400008:
|
|
if (g_Plugins->Gfx()->ViWidthChanged != NULL)
|
|
{
|
|
CompConstToVariable(Value, &g_Reg->VI_WIDTH_REG, "VI_WIDTH_REG");
|
|
JeLabel8("Continue", 0);
|
|
Jump = m_RecompPos - 1;
|
|
MoveConstToVariable(Value, &g_Reg->VI_WIDTH_REG, "VI_WIDTH_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
Call_Direct(g_Plugins->Gfx()->ViWidthChanged, "ViWidthChanged");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
CPU_Message("");
|
|
CPU_Message(" Continue:");
|
|
SetJump8(Jump, m_RecompPos);
|
|
}
|
|
break;
|
|
case 0x0440000C: MoveConstToVariable(Value, &g_Reg->VI_INTR_REG, "VI_INTR_REG"); break;
|
|
case 0x04400010:
|
|
AndConstToVariable((uint32_t)~MI_INTR_VI, &g_Reg->MI_INTR_REG, "MI_INTR_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)g_Reg, x86_ECX);
|
|
Call_Direct(AddressOf(&CRegisters::CheckInterrupts), "CRegisters::CheckInterrupts");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04400014: MoveConstToVariable(Value, &g_Reg->VI_BURST_REG, "VI_BURST_REG"); break;
|
|
case 0x04400018: MoveConstToVariable(Value, &g_Reg->VI_V_SYNC_REG, "VI_V_SYNC_REG"); break;
|
|
case 0x0440001C: MoveConstToVariable(Value, &g_Reg->VI_H_SYNC_REG, "VI_H_SYNC_REG"); break;
|
|
case 0x04400020: MoveConstToVariable(Value, &g_Reg->VI_LEAP_REG, "VI_LEAP_REG"); break;
|
|
case 0x04400024: MoveConstToVariable(Value, &g_Reg->VI_H_START_REG, "VI_H_START_REG"); break;
|
|
case 0x04400028: MoveConstToVariable(Value, &g_Reg->VI_V_START_REG, "VI_V_START_REG"); break;
|
|
case 0x0440002C: MoveConstToVariable(Value, &g_Reg->VI_V_BURST_REG, "VI_V_BURST_REG"); break;
|
|
case 0x04400030: MoveConstToVariable(Value, &g_Reg->VI_X_SCALE_REG, "VI_X_SCALE_REG"); break;
|
|
case 0x04400034: MoveConstToVariable(Value, &g_Reg->VI_Y_SCALE_REG, "VI_Y_SCALE_REG"); break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store %08X in %08X?", Value, VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04500000: /* AI registers */
|
|
switch (PAddr)
|
|
{
|
|
case 0x04500000: MoveConstToVariable(Value, &g_Reg->AI_DRAM_ADDR_REG, "AI_DRAM_ADDR_REG"); break;
|
|
case 0x04500004:
|
|
MoveConstToVariable(Value, &g_Reg->AI_LEN_REG, "AI_LEN_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
if (g_System->bFixedAudio())
|
|
{
|
|
X86BreakPoint(__FILE__, __LINE__);
|
|
MoveConstToX86reg((uint32_t)g_Audio, x86_ECX);
|
|
Call_Direct(AddressOf(&CAudio::LenChanged), "LenChanged");
|
|
}
|
|
else
|
|
{
|
|
Call_Direct(g_Plugins->Audio()->AiLenChanged, "AiLenChanged");
|
|
}
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04500008: MoveConstToVariable((Value & 1), &g_Reg->AI_CONTROL_REG, "AI_CONTROL_REG"); break;
|
|
case 0x0450000C:
|
|
/* Clear Interrupt */;
|
|
AndConstToVariable((uint32_t)~MI_INTR_AI, &g_Reg->MI_INTR_REG, "MI_INTR_REG");
|
|
AndConstToVariable((uint32_t)~MI_INTR_AI, &g_Reg->m_AudioIntrReg, "m_AudioIntrReg");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)g_Reg, x86_ECX);
|
|
Call_Direct(AddressOf(&CRegisters::CheckInterrupts), "CRegisters::CheckInterrupts");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04500010:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveConstToVariable(Value, PAddr + m_RDRAM, VarName);
|
|
break;
|
|
case 0x04500014: MoveConstToVariable(Value, &g_Reg->AI_BITRATE_REG, "AI_BITRATE_REG"); break;
|
|
default:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveConstToVariable(Value, PAddr + m_RDRAM, VarName);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store %08X in %08X?", Value, VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04600000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04600000: MoveConstToVariable(Value, &g_Reg->PI_DRAM_ADDR_REG, "PI_DRAM_ADDR_REG"); break;
|
|
case 0x04600004: MoveConstToVariable(Value, &g_Reg->PI_CART_ADDR_REG, "PI_CART_ADDR_REG"); break;
|
|
case 0x04600008:
|
|
MoveConstToVariable(Value, &g_Reg->PI_RD_LEN_REG, "PI_RD_LEN_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((ULONG)((CDMA *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CDMA::PI_DMA_READ), "CDMA::PI_DMA_READ");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x0460000C:
|
|
MoveConstToVariable(Value, &g_Reg->PI_WR_LEN_REG, "PI_WR_LEN_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((ULONG)((CDMA *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CDMA::PI_DMA_WRITE), "CDMA::PI_DMA_WRITE");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04600010:
|
|
if ((Value & PI_CLR_INTR) != 0)
|
|
{
|
|
AndConstToVariable((uint32_t)~MI_INTR_PI, &g_Reg->MI_INTR_REG, "MI_INTR_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)g_Reg, x86_ECX);
|
|
Call_Direct(AddressOf(&CRegisters::CheckInterrupts), "CRegisters::CheckInterrupts");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
}
|
|
break;
|
|
case 0x04600014: MoveConstToVariable((Value & 0xFF), &g_Reg->PI_DOMAIN1_REG, "PI_DOMAIN1_REG"); break;
|
|
case 0x04600018: MoveConstToVariable((Value & 0xFF), &g_Reg->PI_BSD_DOM1_PWD_REG, "PI_BSD_DOM1_PWD_REG"); break;
|
|
case 0x0460001C: MoveConstToVariable((Value & 0xFF), &g_Reg->PI_BSD_DOM1_PGS_REG, "PI_BSD_DOM1_PGS_REG"); break;
|
|
case 0x04600020: MoveConstToVariable((Value & 0xFF), &g_Reg->PI_BSD_DOM1_RLS_REG, "PI_BSD_DOM1_RLS_REG"); break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store %08X in %08X?", Value, VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04700000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04700000: MoveConstToVariable(Value, &g_Reg->RI_MODE_REG, "RI_MODE_REG"); break;
|
|
case 0x04700004: MoveConstToVariable(Value, &g_Reg->RI_CONFIG_REG, "RI_CONFIG_REG"); break;
|
|
case 0x04700008: MoveConstToVariable(Value, &g_Reg->RI_CURRENT_LOAD_REG, "RI_CURRENT_LOAD_REG"); break;
|
|
case 0x0470000C: MoveConstToVariable(Value, &g_Reg->RI_SELECT_REG, "RI_SELECT_REG"); break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store %08X in %08X?", Value, VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04800000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04800000: MoveConstToVariable(Value, &g_Reg->SI_DRAM_ADDR_REG, "SI_DRAM_ADDR_REG"); break;
|
|
case 0x04800004:
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
MoveConstToVariable(Value, &g_Reg->SI_PIF_ADDR_RD64B_REG, "SI_PIF_ADDR_RD64B_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)((CPifRam *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CPifRam::SI_DMA_READ), "CPifRam::SI_DMA_READ");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04800010:
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
MoveConstToVariable(Value, &g_Reg->SI_PIF_ADDR_WR64B_REG, "SI_PIF_ADDR_WR64B_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)((CPifRam *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CPifRam::SI_DMA_WRITE), "CPifRam::SI_DMA_WRITE");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04800018:
|
|
AndConstToVariable((uint32_t)~MI_INTR_SI, &g_Reg->MI_INTR_REG, "MI_INTR_REG");
|
|
AndConstToVariable((uint32_t)~SI_STATUS_INTERRUPT, &g_Reg->SI_STATUS_REG, "SI_STATUS_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)g_Reg, x86_ECX);
|
|
Call_Direct(AddressOf(&CRegisters::CheckInterrupts), "CRegisters::CheckInterrupts");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store %08X in %08X?", Value, VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x1fc00000:
|
|
{
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
PushImm32(Value);
|
|
PushImm32(PAddr);
|
|
MoveConstToX86reg((ULONG)((CMipsMemoryVM *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CMipsMemoryVM::SW_NonMemory), "CMipsMemoryVM::SW_NonMemory");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
}
|
|
break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store %08X in %08X?", Value, VAddr).ToUTF16().c_str());
|
|
}
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
PushImm32(Value);
|
|
PushImm32(PAddr);
|
|
MoveConstToX86reg((ULONG)((CMipsMemoryVM *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CMipsMemoryVM::SW_NonMemory), "CMipsMemoryVM::SW_NonMemory");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SW_Register(x86Reg Reg, uint32_t VAddr)
|
|
{
|
|
if (VAddr < 0x80000000 || VAddr >= 0xC0000000)
|
|
{
|
|
m_RegWorkingSet.SetX86Protected(Reg, true);
|
|
|
|
x86Reg TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
x86Reg TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveConstToX86reg(VAddr, TempReg1);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_WriteMap, "m_TLB_WriteMap", TempReg2, TempReg2, 4);
|
|
CompileWriteTLBMiss(TempReg1, TempReg2);
|
|
MoveX86regToX86regPointer(Reg, TempReg1, TempReg2);
|
|
return;
|
|
}
|
|
|
|
char VarName[100];
|
|
uint8_t * Jump;
|
|
uint32_t PAddr;
|
|
|
|
if (!TranslateVaddr(VAddr, PAddr))
|
|
{
|
|
CPU_Message("Compile_SW_Register\nFailed to translate address: %08X", VAddr);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\nFailed to translate address: %08X", VAddr).ToUTF16().c_str());
|
|
}
|
|
return;
|
|
}
|
|
|
|
switch (PAddr & 0xFFF00000)
|
|
{
|
|
case 0x00000000:
|
|
case 0x00100000:
|
|
case 0x00200000:
|
|
case 0x00300000:
|
|
case 0x00400000:
|
|
case 0x00500000:
|
|
case 0x00600000:
|
|
case 0x00700000:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveX86regToVariable(Reg, PAddr + m_RDRAM, VarName);
|
|
break;
|
|
case 0x04000000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04040000: MoveX86regToVariable(Reg, &g_Reg->SP_MEM_ADDR_REG, "SP_MEM_ADDR_REG"); break;
|
|
case 0x04040004: MoveX86regToVariable(Reg, &g_Reg->SP_DRAM_ADDR_REG, "SP_DRAM_ADDR_REG"); break;
|
|
case 0x04040008:
|
|
MoveX86regToVariable(Reg, &g_Reg->SP_RD_LEN_REG, "SP_RD_LEN_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((ULONG)((CDMA *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CDMA::SP_DMA_READ), "CDMA::SP_DMA_READ");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x0404000C:
|
|
MoveX86regToVariable(Reg, &g_Reg->SP_WR_LEN_REG, "SP_WR_LEN_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((ULONG)((CDMA *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CDMA::SP_DMA_WRITE), "CDMA::SP_DMA_WRITE");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04040010:
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
MoveX86regToVariable(Reg, &RegModValue, "RegModValue");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
Call_Direct(ChangeSpStatus, "ChangeSpStatus");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x0404001C: MoveConstToVariable(0, &g_Reg->SP_SEMAPHORE_REG, "SP_SEMAPHORE_REG"); break;
|
|
case 0x04080000:
|
|
MoveX86regToVariable(Reg, &g_Reg->SP_PC_REG, "SP_PC_REG");
|
|
AndConstToVariable(0xFFC, &g_Reg->SP_PC_REG, "SP_PC_REG");
|
|
break;
|
|
default:
|
|
if (PAddr < 0x04002000)
|
|
{
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveX86regToVariable(Reg, PAddr + m_RDRAM, VarName);
|
|
}
|
|
else
|
|
{
|
|
CPU_Message(" Should be moving %s in to %08X ?!?", x86_Name(Reg), VAddr);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store in %08X?", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 0x04100000:
|
|
if (PAddr == 0x0410000C)
|
|
{
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
}
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
Push(Reg);
|
|
PushImm32(PAddr);
|
|
MoveConstToX86reg((ULONG)((CMipsMemoryVM *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CMipsMemoryVM::SW_NonMemory), "CMipsMemoryVM::SW_NonMemory");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04300000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04300000:
|
|
MoveX86regToVariable(Reg, &RegModValue, "RegModValue");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
Call_Direct(ChangeMiIntrMask, "ChangeMiModeReg");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x0430000C:
|
|
MoveX86regToVariable(Reg, &RegModValue, "RegModValue");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
Call_Direct(ChangeMiIntrMask, "ChangeMiIntrMask");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
default:
|
|
CPU_Message(" Should be moving %s in to %08X ?!?", x86_Name(Reg), VAddr);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store in %08X?", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04400000:
|
|
switch (PAddr) {
|
|
case 0x04400000:
|
|
if (g_Plugins->Gfx()->ViStatusChanged != NULL)
|
|
{
|
|
CompX86regToVariable(Reg, &g_Reg->VI_STATUS_REG, "VI_STATUS_REG");
|
|
JeLabel8("Continue", 0);
|
|
Jump = m_RecompPos - 1;
|
|
MoveX86regToVariable(Reg, &g_Reg->VI_STATUS_REG, "VI_STATUS_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
Call_Direct(g_Plugins->Gfx()->ViStatusChanged, "ViStatusChanged");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
CPU_Message("");
|
|
CPU_Message(" Continue:");
|
|
SetJump8(Jump, m_RecompPos);
|
|
}
|
|
break;
|
|
case 0x04400004:
|
|
MoveX86regToVariable(Reg, &g_Reg->VI_ORIGIN_REG, "VI_ORIGIN_REG");
|
|
AndConstToVariable(0xFFFFFF, &g_Reg->VI_ORIGIN_REG, "VI_ORIGIN_REG");
|
|
break;
|
|
case 0x04400008:
|
|
if (g_Plugins->Gfx()->ViWidthChanged != NULL)
|
|
{
|
|
CompX86regToVariable(Reg, &g_Reg->VI_WIDTH_REG, "VI_WIDTH_REG");
|
|
JeLabel8("Continue", 0);
|
|
Jump = m_RecompPos - 1;
|
|
MoveX86regToVariable(Reg, &g_Reg->VI_WIDTH_REG, "VI_WIDTH_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
Call_Direct(g_Plugins->Gfx()->ViWidthChanged, "ViWidthChanged");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
CPU_Message("");
|
|
CPU_Message(" Continue:");
|
|
SetJump8(Jump, m_RecompPos);
|
|
}
|
|
break;
|
|
case 0x0440000C: MoveX86regToVariable(Reg, &g_Reg->VI_INTR_REG, "VI_INTR_REG"); break;
|
|
case 0x04400010:
|
|
AndConstToVariable((uint32_t)~MI_INTR_VI, &g_Reg->MI_INTR_REG, "MI_INTR_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)g_Reg, x86_ECX);
|
|
Call_Direct(AddressOf(&CRegisters::CheckInterrupts), "CRegisters::CheckInterrupts");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04400014: MoveX86regToVariable(Reg, &g_Reg->VI_BURST_REG, "VI_BURST_REG"); break;
|
|
case 0x04400018: MoveX86regToVariable(Reg, &g_Reg->VI_V_SYNC_REG, "VI_V_SYNC_REG"); break;
|
|
case 0x0440001C: MoveX86regToVariable(Reg, &g_Reg->VI_H_SYNC_REG, "VI_H_SYNC_REG"); break;
|
|
case 0x04400020: MoveX86regToVariable(Reg, &g_Reg->VI_LEAP_REG, "VI_LEAP_REG"); break;
|
|
case 0x04400024: MoveX86regToVariable(Reg, &g_Reg->VI_H_START_REG, "VI_H_START_REG"); break;
|
|
case 0x04400028: MoveX86regToVariable(Reg, &g_Reg->VI_V_START_REG, "VI_V_START_REG"); break;
|
|
case 0x0440002C: MoveX86regToVariable(Reg, &g_Reg->VI_V_BURST_REG, "VI_V_BURST_REG"); break;
|
|
case 0x04400030: MoveX86regToVariable(Reg, &g_Reg->VI_X_SCALE_REG, "VI_X_SCALE_REG"); break;
|
|
case 0x04400034: MoveX86regToVariable(Reg, &g_Reg->VI_Y_SCALE_REG, "VI_Y_SCALE_REG"); break;
|
|
default:
|
|
CPU_Message(" Should be moving %s in to %08X ?!?", x86_Name(Reg), VAddr);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store in %08X?", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04500000: /* AI registers */
|
|
switch (PAddr) {
|
|
case 0x04500000: MoveX86regToVariable(Reg, &g_Reg->AI_DRAM_ADDR_REG, "AI_DRAM_ADDR_REG"); break;
|
|
case 0x04500004:
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
MoveX86regToVariable(Reg, &g_Reg->AI_LEN_REG, "AI_LEN_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
if (g_System->bFixedAudio())
|
|
{
|
|
MoveConstToX86reg((uint32_t)g_Audio, x86_ECX);
|
|
Call_Direct(AddressOf(&CAudio::LenChanged), "LenChanged");
|
|
}
|
|
else
|
|
{
|
|
Call_Direct(g_Plugins->Audio()->AiLenChanged, "g_Plugins->Audio()->LenChanged");
|
|
}
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04500008:
|
|
MoveX86regToVariable(Reg, &g_Reg->AI_CONTROL_REG, "AI_CONTROL_REG");
|
|
AndConstToVariable(1, &g_Reg->AI_CONTROL_REG, "AI_CONTROL_REG");
|
|
case 0x0450000C:
|
|
/* Clear Interrupt */;
|
|
AndConstToVariable((uint32_t)~MI_INTR_AI, &g_Reg->MI_INTR_REG, "MI_INTR_REG");
|
|
AndConstToVariable((uint32_t)~MI_INTR_AI, &g_Reg->m_AudioIntrReg, "m_AudioIntrReg");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)g_Reg, x86_ECX);
|
|
Call_Direct(AddressOf(&CRegisters::CheckInterrupts), "CRegisters::CheckInterrupts");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04500010:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveX86regToVariable(Reg, PAddr + m_RDRAM, VarName);
|
|
break;
|
|
case 0x04500014: MoveX86regToVariable(Reg, &g_Reg->AI_BITRATE_REG, "AI_BITRATE_REG"); break;
|
|
default:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveX86regToVariable(Reg, PAddr + m_RDRAM, VarName);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store in %08X?", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04600000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04600000: MoveX86regToVariable(Reg, &g_Reg->PI_DRAM_ADDR_REG, "PI_DRAM_ADDR_REG"); break;
|
|
case 0x04600004: MoveX86regToVariable(Reg, &g_Reg->PI_CART_ADDR_REG, "PI_CART_ADDR_REG"); break;
|
|
case 0x04600008:
|
|
MoveX86regToVariable(Reg, &g_Reg->PI_RD_LEN_REG, "PI_RD_LEN_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((ULONG)((CDMA *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CDMA::PI_DMA_READ), "CDMA::PI_DMA_READ");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x0460000C:
|
|
MoveX86regToVariable(Reg, &g_Reg->PI_WR_LEN_REG, "PI_WR_LEN_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((ULONG)((CDMA *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CDMA::PI_DMA_WRITE), "CDMA::PI_DMA_WRITE");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04600010:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store in %08X?", VAddr).ToUTF16().c_str());
|
|
}
|
|
AndConstToVariable((uint32_t)~MI_INTR_PI, &g_Reg->MI_INTR_REG, "MI_INTR_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)g_Reg, x86_ECX);
|
|
Call_Direct(AddressOf(&CRegisters::CheckInterrupts), "CRegisters::CheckInterrupts");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04600014:
|
|
MoveX86regToVariable(Reg, &g_Reg->PI_DOMAIN1_REG, "PI_DOMAIN1_REG");
|
|
AndConstToVariable(0xFF, &g_Reg->PI_DOMAIN1_REG, "PI_DOMAIN1_REG");
|
|
break;
|
|
case 0x04600018:
|
|
MoveX86regToVariable(Reg, &g_Reg->PI_BSD_DOM1_PWD_REG, "PI_BSD_DOM1_PWD_REG");
|
|
AndConstToVariable(0xFF, &g_Reg->PI_BSD_DOM1_PWD_REG, "PI_BSD_DOM1_PWD_REG");
|
|
break;
|
|
case 0x0460001C:
|
|
MoveX86regToVariable(Reg, &g_Reg->PI_BSD_DOM1_PGS_REG, "PI_BSD_DOM1_PGS_REG");
|
|
AndConstToVariable(0xFF, &g_Reg->PI_BSD_DOM1_PGS_REG, "PI_BSD_DOM1_PGS_REG");
|
|
break;
|
|
case 0x04600020:
|
|
MoveX86regToVariable(Reg, &g_Reg->PI_BSD_DOM1_RLS_REG, "PI_BSD_DOM1_RLS_REG");
|
|
AndConstToVariable(0xFF, &g_Reg->PI_BSD_DOM1_RLS_REG, "PI_BSD_DOM1_RLS_REG");
|
|
break;
|
|
default:
|
|
CPU_Message(" Should be moving %s in to %08X ?!?", x86_Name(Reg), VAddr);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store in %08X?", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04700000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04700010: MoveX86regToVariable(Reg, &g_Reg->RI_REFRESH_REG, "RI_REFRESH_REG"); break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store in %08X?", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x04800000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04800000: MoveX86regToVariable(Reg, &g_Reg->SI_DRAM_ADDR_REG, "SI_DRAM_ADDR_REG"); break;
|
|
case 0x04800004:
|
|
MoveX86regToVariable(Reg, &g_Reg->SI_PIF_ADDR_RD64B_REG, "SI_PIF_ADDR_RD64B_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)((CPifRam *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CPifRam::SI_DMA_READ), "CPifRam::SI_DMA_READ");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04800010:
|
|
MoveX86regToVariable(Reg, &g_Reg->SI_PIF_ADDR_WR64B_REG, "SI_PIF_ADDR_WR64B_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)((CPifRam *)this), x86_ECX);
|
|
Call_Direct(AddressOf(&CPifRam::SI_DMA_WRITE), "CPifRam::SI_DMA_WRITE");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
case 0x04800018:
|
|
AndConstToVariable((uint32_t)~MI_INTR_SI, &g_Reg->MI_INTR_REG, "MI_INTR_REG");
|
|
AndConstToVariable((uint32_t)~SI_STATUS_INTERRUPT, &g_Reg->SI_STATUS_REG, "SI_STATUS_REG");
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToX86reg((uint32_t)g_Reg, x86_ECX);
|
|
Call_Direct(AddressOf(&CRegisters::CheckInterrupts), "CRegisters::CheckInterrupts");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
break;
|
|
default:
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store in %08X?", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
break;
|
|
case 0x1FC00000:
|
|
sprintf(VarName, "m_RDRAM + %X", PAddr);
|
|
MoveX86regToVariable(Reg, PAddr + m_RDRAM, VarName);
|
|
break;
|
|
default:
|
|
CPU_Message(" Should be moving %s in to %08X ?!?", x86_Name(Reg), VAddr);
|
|
if (g_Settings->LoadBool(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f(__FUNCTION__ "\ntrying to store in %08X?", VAddr).ToUTF16().c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::ResetMemoryStack()
|
|
{
|
|
x86Reg Reg, TempReg;
|
|
|
|
int32_t MipsReg = 29;
|
|
CPU_Message(" ResetMemoryStack");
|
|
Reg = Get_MemoryStack();
|
|
if (Reg == x86_Unknown)
|
|
{
|
|
Reg = Map_TempReg(x86_Any, MipsReg, false);
|
|
}
|
|
else
|
|
{
|
|
if (IsUnknown(MipsReg))
|
|
{
|
|
MoveVariableToX86reg(&_GPR[MipsReg].UW[0], CRegName::GPR_Lo[MipsReg], Reg);
|
|
}
|
|
else if (IsMapped(MipsReg))
|
|
{
|
|
MoveX86RegToX86Reg(GetMipsRegMapLo(MipsReg), Reg);
|
|
}
|
|
else
|
|
{
|
|
MoveConstToX86reg(GetMipsRegLo(MipsReg), Reg);
|
|
}
|
|
}
|
|
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(Reg, TempReg);
|
|
ShiftRightUnsignImmed(TempReg, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TempReg, TempReg, 4);
|
|
AddX86RegToX86Reg(Reg, TempReg);
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(Reg, 0x1FFFFFFF);
|
|
AddConstToX86Reg(Reg, (uint32_t)m_RDRAM);
|
|
}
|
|
MoveX86regToVariable(Reg, &(g_Recompiler->MemoryStackPos()), "MemoryStack");
|
|
}
|
|
|
|
int32_t CMipsMemoryVM::MemoryFilter(uint32_t dwExptCode, void * lpExceptionPointer)
|
|
{
|
|
#if defined(_M_IX86) && defined(_WIN32)
|
|
// to do: Remove the _M_IX86 criteria. This can compile on 64-bit Windows.
|
|
#ifndef _WIN64
|
|
DWORD * Reg;
|
|
// We need this to fix 32-bit Windows builds,
|
|
// because Project64 currently uses uint32_t all the time instead of int32_t.
|
|
#else
|
|
size_t * Reg;
|
|
#endif
|
|
|
|
if (dwExptCode != EXCEPTION_ACCESS_VIOLATION)
|
|
{
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
//convert the pointer since we are not having win32 structures in headers
|
|
LPEXCEPTION_POINTERS lpEP = (LPEXCEPTION_POINTERS)lpExceptionPointer;
|
|
|
|
uint32_t MemAddress = (char *)lpEP->ExceptionRecord->ExceptionInformation[1] - (char *)g_MMU->Rdram();
|
|
if ((int32_t)(MemAddress) < 0 || MemAddress > 0x1FFFFFFF)
|
|
{
|
|
// if (bHaveDebugger())
|
|
// {
|
|
// g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
// }
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
uint8_t * TypePos = (uint8_t *)lpEP->ContextRecord->Eip;
|
|
EXCEPTION_RECORD exRec = *lpEP->ExceptionRecord;
|
|
|
|
Reg = NULL;
|
|
if (*TypePos == 0xF3 && (*(TypePos + 1) == 0xA4 || *(TypePos + 1) == 0xA5))
|
|
{
|
|
uint32_t Start = (lpEP->ContextRecord->Edi - (uint32_t)m_RDRAM);
|
|
uint32_t End = Start + lpEP->ContextRecord->Ecx;
|
|
if ((int32_t)Start < 0)
|
|
{
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
#ifdef CFB_READ
|
|
uint32_t count, OldProtect;
|
|
if (Start >= CFBStart && End < CFBEnd)
|
|
{
|
|
for ( count = Start; count < End; count += 0x1000 )
|
|
{
|
|
VirtualProtect(m_RDRAM+count,4,PAGE_READONLY, &OldProtect);
|
|
if (FrameBufferRead)
|
|
{
|
|
FrameBufferRead(count & ~0xFFF);
|
|
}
|
|
}
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
}
|
|
#endif
|
|
if (End < RdramSize())
|
|
{
|
|
for (uint32_t count = (Start & ~0xFFF); count < End; count += 0x1000)
|
|
{
|
|
g_Recompiler->ClearRecompCode_Phys(count, 0x1000, CRecompiler::Remove_ProtectedMem);
|
|
}
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
}
|
|
if (Start >= 0x04000000 && End < 0x04002000)
|
|
{
|
|
g_Recompiler->ClearRecompCode_Phys(Start & ~0xFFF, 0x1000, CRecompiler::Remove_ProtectedMem);
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
}
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
uint8_t * ReadPos;
|
|
if (*TypePos == 0x0F && *(TypePos + 1) == 0xB6)
|
|
{
|
|
ReadPos = TypePos + 2;
|
|
}
|
|
else if (*TypePos == 0x0F && *(TypePos + 1) == 0xB7)
|
|
{
|
|
ReadPos = TypePos + 2;
|
|
}
|
|
else if (*TypePos == 0x0F && *(TypePos + 1) == 0xBE)
|
|
{
|
|
ReadPos = TypePos + 2;
|
|
}
|
|
else if (*TypePos == 0x0F && *(TypePos + 1) == 0xBF)
|
|
{
|
|
ReadPos = TypePos + 2;
|
|
}
|
|
else if (*TypePos == 0x66)
|
|
{
|
|
ReadPos = TypePos + 2;
|
|
}
|
|
else
|
|
{
|
|
ReadPos = TypePos + 1;
|
|
}
|
|
|
|
switch (*ReadPos & 0x38)
|
|
{
|
|
case 0x00: Reg = &(lpEP->ContextRecord->Eax); break;
|
|
case 0x08: Reg = &(lpEP->ContextRecord->Ecx); break;
|
|
case 0x10: Reg = &(lpEP->ContextRecord->Edx); break;
|
|
case 0x18: Reg = &(lpEP->ContextRecord->Ebx); break;
|
|
case 0x20: Reg = &(lpEP->ContextRecord->Esp); break;
|
|
case 0x28: Reg = &(lpEP->ContextRecord->Ebp); break;
|
|
case 0x30: Reg = &(lpEP->ContextRecord->Esi); break;
|
|
case 0x38: Reg = &(lpEP->ContextRecord->Edi); break;
|
|
}
|
|
|
|
switch ((*ReadPos & 0xC7))
|
|
{
|
|
case 0: ReadPos += 1; break;
|
|
case 1: ReadPos += 1; break;
|
|
case 2: ReadPos += 1; break;
|
|
case 3: ReadPos += 1; break;
|
|
case 4:
|
|
ReadPos += 1;
|
|
switch ((*ReadPos & 0xC7))
|
|
{
|
|
case 0: ReadPos += 1; break;
|
|
case 1: ReadPos += 1; break;
|
|
case 2: ReadPos += 1; break;
|
|
case 3: ReadPos += 1; break;
|
|
case 6: ReadPos += 1; break;
|
|
case 7: ReadPos += 1; break;
|
|
case 0x80: ReadPos += 1; break;
|
|
default:
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
break;
|
|
case 5: ReadPos += 5; break;
|
|
case 6: ReadPos += 1; break;
|
|
case 7: ReadPos += 1; break;
|
|
case 0x40: ReadPos += 2; break;
|
|
case 0x41: ReadPos += 2; break;
|
|
case 0x42: ReadPos += 2; break;
|
|
case 0x43: ReadPos += 2; break;
|
|
case 0x44: ReadPos += 3; break;
|
|
case 0x46: ReadPos += 2; break;
|
|
case 0x47: ReadPos += 2; break;
|
|
case 0x80: ReadPos += 5; break;
|
|
case 0x81: ReadPos += 5; break;
|
|
case 0x82: ReadPos += 5; break;
|
|
case 0x83: ReadPos += 5; break;
|
|
case 0x86: ReadPos += 5; break;
|
|
case 0x87: ReadPos += 5; break;
|
|
default:
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
if (Reg == NULL)
|
|
{
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
switch (*TypePos)
|
|
{
|
|
case 0x0F:
|
|
switch (*(TypePos + 1))
|
|
{
|
|
case 0xB6:
|
|
if (!LB_NonMemory(MemAddress, (uint32_t *)Reg, false))
|
|
{
|
|
if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f("Failed to load byte\n\nMIPS Address: %08X\nX86 Address: %08X",
|
|
(char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM,
|
|
(uint8_t *)lpEP->ContextRecord->Eip).ToUTF16().c_str());
|
|
}
|
|
}
|
|
lpEP->ContextRecord->Eip = (uint32_t)ReadPos;
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
case 0xB7:
|
|
if (!LH_NonMemory(MemAddress, (uint32_t *)Reg, false))
|
|
{
|
|
if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f("Failed to load half word\n\nMIPS Address: %08X\nX86 Address: %08X",
|
|
(char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM,
|
|
(uint8_t *)lpEP->ContextRecord->Eip).ToUTF16().c_str());
|
|
}
|
|
}
|
|
lpEP->ContextRecord->Eip = (uint32_t)ReadPos;
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
case 0xBE:
|
|
if (!LB_NonMemory(MemAddress, (uint32_t *)Reg, true))
|
|
{
|
|
if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f("Failed to load byte\n\nMIPS Address: %08X\nX86 Address: %08X",
|
|
(char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM,
|
|
(uint8_t *)lpEP->ContextRecord->Eip).ToUTF16().c_str());
|
|
}
|
|
}
|
|
lpEP->ContextRecord->Eip = (uint32_t)ReadPos;
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
case 0xBF:
|
|
if (!LH_NonMemory(MemAddress, (uint32_t *)Reg, true))
|
|
{
|
|
if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f("Failed to load half word\n\nMIPS Address: %08X\nX86 Address: %08X",
|
|
(char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM,
|
|
(uint8_t *)lpEP->ContextRecord->Eip).ToUTF16().c_str());
|
|
}
|
|
}
|
|
lpEP->ContextRecord->Eip = (uint32_t)ReadPos;
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
default:
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
break;
|
|
case 0x66:
|
|
switch (*(TypePos + 1))
|
|
{
|
|
case 0x8B:
|
|
if (!LH_NonMemory(MemAddress, (uint32_t *)Reg, false))
|
|
{
|
|
if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f("Failed to half word\n\nMIPS Address: %08X\nX86 Address: %08X",
|
|
(char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM,
|
|
(uint8_t *)lpEP->ContextRecord->Eip).ToUTF16().c_str());
|
|
}
|
|
}
|
|
lpEP->ContextRecord->Eip = (uint32_t)ReadPos;
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
case 0x89:
|
|
if (!SH_NonMemory(MemAddress, *(uint16_t *)Reg))
|
|
{
|
|
if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f("Failed to store half word\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress,
|
|
(uint8_t *)lpEP->ContextRecord->Eip).ToUTF16().c_str());
|
|
}
|
|
}
|
|
lpEP->ContextRecord->Eip = (uint32_t)ReadPos;
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
case 0xC7:
|
|
if (Reg != &lpEP->ContextRecord->Eax)
|
|
{
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
if (!SH_NonMemory(MemAddress, *(uint16_t *)ReadPos)) {
|
|
if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f("Failed to store half word\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress,
|
|
(uint8_t *)lpEP->ContextRecord->Eip).ToUTF16().c_str());
|
|
}
|
|
}
|
|
lpEP->ContextRecord->Eip = (uint32_t)(ReadPos + 2);
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
default:
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
break;
|
|
case 0x88:
|
|
if (!SB_NonMemory(MemAddress, *(uint8_t *)Reg))
|
|
{
|
|
if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f("Failed to store byte\n\nMIPS Address: %08X\nX86 Address: %08X",
|
|
(char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM,
|
|
(uint8_t *)lpEP->ContextRecord->Eip).ToUTF16().c_str());
|
|
}
|
|
}
|
|
lpEP->ContextRecord->Eip = (uint32_t)ReadPos;
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
case 0x8A:
|
|
if (!LB_NonMemory(MemAddress, (uint32_t *)Reg, false))
|
|
{
|
|
if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f("Failed to load byte\n\nMIPS Address: %08X\nX86 Address: %08X",
|
|
(char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM,
|
|
(uint8_t *)lpEP->ContextRecord->Eip).ToUTF16().c_str());
|
|
}
|
|
}
|
|
lpEP->ContextRecord->Eip = (uint32_t)ReadPos;
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
case 0x8B:
|
|
if (!LW_NonMemory(MemAddress, (uint32_t *)Reg))
|
|
{
|
|
if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f("Failed to load word\n\nMIPS Address: %08X\nX86 Address: %08X",
|
|
(char *)exRec.ExceptionInformation[1] - (char *)m_RDRAM,
|
|
(uint8_t *)lpEP->ContextRecord->Eip).ToUTF16().c_str());
|
|
}
|
|
}
|
|
lpEP->ContextRecord->Eip = (uint32_t)ReadPos;
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
case 0x89:
|
|
if (!SW_NonMemory(MemAddress, *(uint32_t *)Reg))
|
|
{
|
|
if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f("Failed to store word\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress,
|
|
(uint8_t *)lpEP->ContextRecord->Eip).ToUTF16().c_str());
|
|
}
|
|
}
|
|
lpEP->ContextRecord->Eip = (uint32_t)ReadPos;
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
case 0xC6:
|
|
if (Reg != &lpEP->ContextRecord->Eax)
|
|
{
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
if (!SB_NonMemory(MemAddress, *(uint8_t *)ReadPos))
|
|
{
|
|
if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f("Failed to store byte\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress,
|
|
(uint8_t *)lpEP->ContextRecord->Eip).ToUTF16().c_str());
|
|
}
|
|
}
|
|
lpEP->ContextRecord->Eip = (uint32_t)(ReadPos + 1);
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
case 0xC7:
|
|
if (Reg != &lpEP->ContextRecord->Eax)
|
|
{
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
if (!SW_NonMemory(MemAddress, *(uint32_t *)ReadPos))
|
|
{
|
|
if (g_Settings->LoadDword(Debugger_ShowUnhandledMemory))
|
|
{
|
|
g_Notify->DisplayError(stdstr_f("Failed to store word\n\nMIPS Address: %08X\nX86 Address: %08X", MemAddress,
|
|
(uint8_t *)lpEP->ContextRecord->Eip).ToUTF16().c_str());
|
|
}
|
|
}
|
|
lpEP->ContextRecord->Eip = (uint32_t)(ReadPos + 4);
|
|
return EXCEPTION_CONTINUE_EXECUTION;
|
|
}
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
#else
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
#endif
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
}
|
|
|
|
bool CMipsMemoryVM::LB_NonMemory(uint32_t PAddr, uint32_t* Value, bool /*SignExtend*/)
|
|
{
|
|
if (PAddr < 0x800000)
|
|
{
|
|
*Value = 0;
|
|
return true;
|
|
}
|
|
|
|
if (PAddr >= 0x10000000 && PAddr < 0x16000000)
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
#ifdef legacycode
|
|
if (WrittenToRom)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ((PAddr & 2) == 0)
|
|
{
|
|
PAddr = (PAddr + 4) ^ 2;
|
|
}
|
|
|
|
if ((PAddr - 0x10000000) < RomFileSize)
|
|
{
|
|
if (SignExtend)
|
|
{
|
|
*Value = (int32_t)((char)ROM[PAddr - 0x10000000]);
|
|
}
|
|
else
|
|
{
|
|
*Value = ROM[PAddr - 0x10000000];
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
*Value = 0;
|
|
return false;
|
|
}
|
|
#endif
|
|
}
|
|
// switch (PAddr & 0xFFF00000)
|
|
//{
|
|
// default:
|
|
*Value = 0;
|
|
// return false;
|
|
// break;
|
|
// }
|
|
return true;
|
|
}
|
|
|
|
bool CMipsMemoryVM::LH_NonMemory(uint32_t PAddr, uint32_t* Value, bool/* SignExtend*/)
|
|
{
|
|
if (PAddr < 0x800000)
|
|
{
|
|
*Value = 0;
|
|
return true;
|
|
}
|
|
|
|
if (PAddr >= 0x10000000 && PAddr < 0x16000000)
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
// switch (PAddr & 0xFFF00000)
|
|
// {
|
|
// default:
|
|
*Value = 0;
|
|
return false;
|
|
// }
|
|
// return true;
|
|
}
|
|
|
|
bool CMipsMemoryVM::LW_NonMemory(uint32_t PAddr, uint32_t* Value)
|
|
{
|
|
#ifdef CFB_READ
|
|
if (PAddr >= CFBStart && PAddr < CFBEnd)
|
|
{
|
|
uint32_t OldProtect;
|
|
VirtualProtect(m_RDRAM+(PAddr & ~0xFFF),0xFFC,PAGE_READONLY, &OldProtect);
|
|
if (FrameBufferRead)
|
|
{
|
|
FrameBufferRead(PAddr & ~0xFFF);
|
|
}
|
|
*Value = *(uint32_t *)(m_RDRAM+PAddr);
|
|
return true;
|
|
}
|
|
#endif
|
|
if (PAddr >= 0x10000000 && PAddr < 0x16000000)
|
|
{
|
|
if (m_RomWrittenTo)
|
|
{
|
|
*Value = m_RomWroteValue;
|
|
//LogMessage("%X: Read crap from Rom %08X from %08X",PROGRAM_COUNTER,*Value,PAddr);
|
|
m_RomWrittenTo = false;
|
|
#ifdef ROM_IN_MAPSPACE
|
|
{
|
|
uint32_t OldProtect;
|
|
VirtualProtect(ROM,RomFileSize,PAGE_READONLY, &OldProtect);
|
|
}
|
|
#endif
|
|
return true;
|
|
}
|
|
if ((PAddr - 0x10000000) < m_RomSize)
|
|
{
|
|
*Value = *(uint32_t *)&m_Rom[PAddr - 0x10000000];
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
*Value = PAddr & 0xFFFF;
|
|
*Value = (*Value << 16) | *Value;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
m_MemLookupAddress = PAddr;
|
|
switch (PAddr & 0xFFF00000)
|
|
{
|
|
case 0x03F00000:
|
|
Load32RDRAMRegisters();
|
|
*Value = m_MemLookupValue.UW[0];
|
|
break;
|
|
case 0x04000000:
|
|
Load32SPRegisters();
|
|
*Value = m_MemLookupValue.UW[0];
|
|
break;
|
|
case 0x04100000:
|
|
Load32DPCommand();
|
|
*Value = m_MemLookupValue.UW[0];
|
|
break;
|
|
case 0x04300000:
|
|
Load32MIPSInterface();
|
|
*Value = m_MemLookupValue.UW[0];
|
|
break;
|
|
case 0x04400000:
|
|
Load32VideoInterface();
|
|
*Value = m_MemLookupValue.UW[0];
|
|
break;
|
|
case 0x04500000:
|
|
Load32AudioInterface();
|
|
*Value = m_MemLookupValue.UW[0];
|
|
break;
|
|
case 0x04600000:
|
|
Load32PeripheralInterface();
|
|
*Value = m_MemLookupValue.UW[0];
|
|
break;
|
|
case 0x04700000:
|
|
Load32RDRAMInterface();
|
|
*Value = m_MemLookupValue.UW[0];
|
|
break;
|
|
case 0x04800000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04800018: *Value = g_Reg->SI_STATUS_REG; break;
|
|
default:
|
|
*Value = 0;
|
|
return false;
|
|
}
|
|
break;
|
|
case 0x05000000:
|
|
*Value = PAddr & 0xFFFF;
|
|
*Value = (*Value << 16) | *Value;
|
|
return false;
|
|
case 0x08000000:
|
|
if (g_System->m_SaveUsing == SaveChip_Auto)
|
|
{
|
|
g_System->m_SaveUsing = SaveChip_FlashRam;
|
|
}
|
|
if (g_System->m_SaveUsing == SaveChip_Sram)
|
|
{
|
|
//Load Sram
|
|
uint8_t tmp[4] = "";
|
|
DmaFromSram(tmp, PAddr - 0x08000000, 4);
|
|
*Value = tmp[3] << 24 | tmp[2] << 16 | tmp[1] << 8 | tmp[0];
|
|
return true;
|
|
}
|
|
else if (g_System->m_SaveUsing != SaveChip_FlashRam)
|
|
{
|
|
*Value = PAddr & 0xFFFF;
|
|
*Value = (*Value << 16) | *Value;
|
|
return false;
|
|
}
|
|
*Value = ReadFromFlashStatus(PAddr);
|
|
break;
|
|
case 0x1FC00000:
|
|
if (PAddr < 0x1FC007C0)
|
|
{
|
|
/* *Value = *(uint32_t *)(&PifRom[PAddr - 0x1FC00000]);
|
|
*Value = swap32by8(*Value); */
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
return true;
|
|
}
|
|
else if (PAddr < 0x1FC00800)
|
|
{
|
|
uint8_t * PIF_Ram = g_MMU->PifRam();
|
|
*Value = *(uint32_t *)(&PIF_Ram[PAddr - 0x1FC007C0]);
|
|
*Value = swap32by8(*Value);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
*Value = 0;
|
|
return false;
|
|
}
|
|
break;
|
|
default:
|
|
*Value = PAddr & 0xFFFF;
|
|
*Value = (*Value << 16) | *Value;
|
|
return false;
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CMipsMemoryVM::SB_NonMemory(uint32_t PAddr, uint8_t Value)
|
|
{
|
|
switch (PAddr & 0xFFF00000)
|
|
{
|
|
case 0x00000000:
|
|
case 0x00100000:
|
|
case 0x00200000:
|
|
case 0x00300000:
|
|
case 0x00400000:
|
|
case 0x00500000:
|
|
case 0x00600000:
|
|
case 0x00700000:
|
|
#ifdef CFB_READ
|
|
if (PAddr >= CFBStart && PAddr < CFBEnd)
|
|
{
|
|
uint32_t OldProtect;
|
|
VirtualProtect(m_RDRAM + (PAddr & ~0xFFF), 0xFFC, PAGE_READWRITE, &OldProtect);
|
|
*(uint8_t *)(m_RDRAM + PAddr) = Value;
|
|
VirtualProtect(m_RDRAM + (PAddr & ~0xFFF), 0xFFC, OldProtect, &OldProtect);
|
|
g_Notify->DisplayError(L"FrameBufferWrite");
|
|
if (FrameBufferWrite) { FrameBufferWrite(PAddr, 1); }
|
|
break;
|
|
}
|
|
#endif
|
|
if (PAddr < RdramSize())
|
|
{
|
|
DWORD OldProtect;
|
|
g_Recompiler->ClearRecompCode_Phys(PAddr & ~0xFFF, 0xFFC, CRecompiler::Remove_ProtectedMem);
|
|
VirtualProtect(m_RDRAM + (PAddr & ~0xFFF), 0xFFC, PAGE_READWRITE, &OldProtect);
|
|
*(uint8_t *)(m_RDRAM + PAddr) = Value;
|
|
}
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CMipsMemoryVM::SH_NonMemory(uint32_t PAddr, uint16_t Value)
|
|
{
|
|
switch (PAddr & 0xFFF00000)
|
|
{
|
|
case 0x00000000:
|
|
case 0x00100000:
|
|
case 0x00200000:
|
|
case 0x00300000:
|
|
case 0x00400000:
|
|
case 0x00500000:
|
|
case 0x00600000:
|
|
case 0x00700000:
|
|
#ifdef CFB_READ
|
|
if (PAddr >= CFBStart && PAddr < CFBEnd)
|
|
{
|
|
uint32_t OldProtect;
|
|
VirtualProtect(m_RDRAM + (PAddr & ~0xFFF), 0xFFC, PAGE_READWRITE, &OldProtect);
|
|
*(uint16_t *)(m_RDRAM + PAddr) = Value;
|
|
if (FrameBufferWrite) { FrameBufferWrite(PAddr & ~0xFFF, 2); }
|
|
//*(uint16_t *)(m_RDRAM+PAddr) = 0xFFFF;
|
|
//VirtualProtect(m_RDRAM+(PAddr & ~0xFFF),0xFFC,PAGE_NOACCESS, &OldProtect);
|
|
g_Notify->DisplayError(L"PAddr = %x", PAddr);
|
|
break;
|
|
}
|
|
#endif
|
|
if (PAddr < RdramSize())
|
|
{
|
|
DWORD OldProtect;
|
|
g_Recompiler->ClearRecompCode_Phys(PAddr & ~0xFFF, 0x1000, CRecompiler::Remove_ProtectedMem);
|
|
VirtualProtect(m_RDRAM + (PAddr & ~0xFFF), 0xFFC, PAGE_READWRITE, &OldProtect);
|
|
*(uint16_t *)(m_RDRAM + PAddr) = Value;
|
|
}
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CMipsMemoryVM::SW_NonMemory(uint32_t PAddr, uint32_t Value)
|
|
{
|
|
if (PAddr >= 0x10000000 && PAddr < 0x16000000)
|
|
{
|
|
if ((PAddr - 0x10000000) < g_Rom->GetRomSize())
|
|
{
|
|
m_RomWrittenTo = true;
|
|
m_RomWroteValue = Value;
|
|
#ifdef ROM_IN_MAPSPACE
|
|
{
|
|
uint32_t OldProtect;
|
|
VirtualProtect(ROM, RomFileSize, PAGE_NOACCESS, &OldProtect);
|
|
}
|
|
#endif
|
|
//LogMessage("%X: Wrote To Rom %08X from %08X",PROGRAM_COUNTER,Value,PAddr);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
switch (PAddr & 0xFFF00000)
|
|
{
|
|
case 0x00000000:
|
|
case 0x00100000:
|
|
case 0x00200000:
|
|
case 0x00300000:
|
|
case 0x00400000:
|
|
case 0x00500000:
|
|
case 0x00600000:
|
|
case 0x00700000:
|
|
#ifdef CFB_READ
|
|
if (PAddr >= CFBStart && PAddr < CFBEnd)
|
|
{
|
|
uint32_t OldProtect;
|
|
VirtualProtect(m_RDRAM + (PAddr & ~0xFFF), 0xFFC, PAGE_READWRITE, &OldProtect);
|
|
*(uint32_t *)(m_RDRAM + PAddr) = Value;
|
|
VirtualProtect(m_RDRAM + (PAddr & ~0xFFF), 0xFFC, OldProtect, &OldProtect);
|
|
g_Notify->DisplayError(L"FrameBufferWrite %X", PAddr);
|
|
if (FrameBufferWrite) { FrameBufferWrite(PAddr, 4); }
|
|
break;
|
|
}
|
|
#endif
|
|
if (PAddr < RdramSize())
|
|
{
|
|
DWORD OldProtect;
|
|
g_Recompiler->ClearRecompCode_Phys(PAddr & ~0xFFF, 0x1000, CRecompiler::Remove_ProtectedMem);
|
|
VirtualProtect(m_RDRAM + (PAddr & ~0xFFF), 0xFFC, PAGE_READWRITE, &OldProtect);
|
|
*(uint32_t *)(m_RDRAM + PAddr) = Value;
|
|
}
|
|
break;
|
|
case 0x03F00000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x03F00000: g_Reg->RDRAM_CONFIG_REG = Value; break;
|
|
case 0x03F00004: g_Reg->RDRAM_DEVICE_ID_REG = Value; break;
|
|
case 0x03F00008: g_Reg->RDRAM_DELAY_REG = Value; break;
|
|
case 0x03F0000C: g_Reg->RDRAM_MODE_REG = Value; break;
|
|
case 0x03F00010: g_Reg->RDRAM_REF_INTERVAL_REG = Value; break;
|
|
case 0x03F00014: g_Reg->RDRAM_REF_ROW_REG = Value; break;
|
|
case 0x03F00018: g_Reg->RDRAM_RAS_INTERVAL_REG = Value; break;
|
|
case 0x03F0001C: g_Reg->RDRAM_MIN_INTERVAL_REG = Value; break;
|
|
case 0x03F00020: g_Reg->RDRAM_ADDR_SELECT_REG = Value; break;
|
|
case 0x03F00024: g_Reg->RDRAM_DEVICE_MANUF_REG = Value; break;
|
|
case 0x03F04004: break;
|
|
case 0x03F08004: break;
|
|
case 0x03F80004: break;
|
|
case 0x03F80008: break;
|
|
case 0x03F8000C: break;
|
|
case 0x03F80014: break;
|
|
default:
|
|
return false;
|
|
}
|
|
break;
|
|
case 0x04000000:
|
|
if (PAddr < 0x04002000)
|
|
{
|
|
g_Recompiler->ClearRecompCode_Phys(PAddr & ~0xFFF, 0xFFF, CRecompiler::Remove_ProtectedMem);
|
|
*(uint32_t *)(m_RDRAM + PAddr) = Value;
|
|
}
|
|
else
|
|
{
|
|
switch (PAddr)
|
|
{
|
|
case 0x04040000: g_Reg->SP_MEM_ADDR_REG = Value; break;
|
|
case 0x04040004: g_Reg->SP_DRAM_ADDR_REG = Value; break;
|
|
case 0x04040008:
|
|
g_Reg->SP_RD_LEN_REG = Value;
|
|
SP_DMA_READ();
|
|
break;
|
|
case 0x0404000C:
|
|
g_Reg->SP_WR_LEN_REG = Value;
|
|
SP_DMA_WRITE();
|
|
break;
|
|
case 0x04040010:
|
|
if ((Value & SP_CLR_HALT) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_HALT;
|
|
}
|
|
if ((Value & SP_SET_HALT) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_HALT;
|
|
}
|
|
if ((Value & SP_CLR_BROKE) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_BROKE;
|
|
}
|
|
if ((Value & SP_CLR_INTR) != 0)
|
|
{
|
|
g_Reg->MI_INTR_REG &= ~MI_INTR_SP;
|
|
g_Reg->m_RspIntrReg &= ~MI_INTR_SP;
|
|
g_Reg->CheckInterrupts();
|
|
}
|
|
if ((Value & SP_SET_INTR) != 0)
|
|
{
|
|
g_Notify->DisplayError(L"SP_SET_INTR");
|
|
}
|
|
if ((Value & SP_CLR_SSTEP) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SSTEP;
|
|
}
|
|
if ((Value & SP_SET_SSTEP) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SSTEP;
|
|
}
|
|
if ((Value & SP_CLR_INTR_BREAK) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_INTR_BREAK;
|
|
}
|
|
if ((Value & SP_SET_INTR_BREAK) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_INTR_BREAK;
|
|
}
|
|
if ((Value & SP_CLR_SIG0) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG0;
|
|
}
|
|
if ((Value & SP_SET_SIG0) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG0;
|
|
}
|
|
if ((Value & SP_CLR_SIG1) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG1;
|
|
}
|
|
if ((Value & SP_SET_SIG1) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG1;
|
|
}
|
|
if ((Value & SP_CLR_SIG2) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG2;
|
|
}
|
|
if ((Value & SP_SET_SIG2) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG2;
|
|
}
|
|
if ((Value & SP_CLR_SIG3) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG3;
|
|
}
|
|
if ((Value & SP_SET_SIG3) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG3;
|
|
}
|
|
if ((Value & SP_CLR_SIG4) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG4;
|
|
}
|
|
if ((Value & SP_SET_SIG4) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG4;
|
|
}
|
|
if ((Value & SP_CLR_SIG5) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG5;
|
|
}
|
|
if ((Value & SP_SET_SIG5) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG5;
|
|
}
|
|
if ((Value & SP_CLR_SIG6) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG6;
|
|
}
|
|
if ((Value & SP_SET_SIG6) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG6;
|
|
}
|
|
if ((Value & SP_CLR_SIG7) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG7;
|
|
}
|
|
if ((Value & SP_SET_SIG7) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG7;
|
|
}
|
|
if ((Value & SP_SET_SIG0) != 0 && g_System->RspAudioSignal())
|
|
{
|
|
g_Reg->MI_INTR_REG |= MI_INTR_SP;
|
|
g_Reg->CheckInterrupts();
|
|
}
|
|
//if (*( uint32_t *)(DMEM + 0xFC0) == 1)
|
|
//{
|
|
// ChangeTimer(RspTimer,0x30000);
|
|
//}
|
|
//else
|
|
//{
|
|
try
|
|
{
|
|
g_System->RunRSP();
|
|
}
|
|
catch (...)
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
//}
|
|
break;
|
|
case 0x0404001C: g_Reg->SP_SEMAPHORE_REG = 0; break;
|
|
case 0x04080000: g_Reg->SP_PC_REG = Value & 0xFFC; break;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
break;
|
|
case 0x04100000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04100000:
|
|
g_Reg->DPC_START_REG = Value;
|
|
g_Reg->DPC_CURRENT_REG = Value;
|
|
break;
|
|
case 0x04100004:
|
|
g_Reg->DPC_END_REG = Value;
|
|
if (g_Plugins->Gfx()->ProcessRDPList)
|
|
{
|
|
g_Plugins->Gfx()->ProcessRDPList();
|
|
}
|
|
break;
|
|
//case 0x04100008: g_Reg->DPC_CURRENT_REG = Value; break;
|
|
case 0x0410000C:
|
|
if ((Value & DPC_CLR_XBUS_DMEM_DMA) != 0)
|
|
{
|
|
g_Reg->DPC_STATUS_REG &= ~DPC_STATUS_XBUS_DMEM_DMA;
|
|
}
|
|
if ((Value & DPC_SET_XBUS_DMEM_DMA) != 0)
|
|
{
|
|
g_Reg->DPC_STATUS_REG |= DPC_STATUS_XBUS_DMEM_DMA;
|
|
}
|
|
if ((Value & DPC_CLR_FREEZE) != 0)
|
|
{
|
|
g_Reg->DPC_STATUS_REG &= ~DPC_STATUS_FREEZE;
|
|
}
|
|
if ((Value & DPC_SET_FREEZE) != 0)
|
|
{
|
|
g_Reg->DPC_STATUS_REG |= DPC_STATUS_FREEZE;
|
|
}
|
|
if ((Value & DPC_CLR_FLUSH) != 0)
|
|
{
|
|
g_Reg->DPC_STATUS_REG &= ~DPC_STATUS_FLUSH;
|
|
}
|
|
if ((Value & DPC_SET_FLUSH) != 0)
|
|
{
|
|
g_Reg->DPC_STATUS_REG |= DPC_STATUS_FLUSH;
|
|
}
|
|
if ((Value & DPC_CLR_FREEZE) != 0)
|
|
{
|
|
if ((g_Reg->SP_STATUS_REG & SP_STATUS_HALT) == 0)
|
|
{
|
|
if ((g_Reg->SP_STATUS_REG & SP_STATUS_BROKE) == 0)
|
|
{
|
|
try
|
|
{
|
|
g_System->RunRSP();
|
|
}
|
|
catch (...)
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#ifdef legacycode
|
|
if (ShowUnhandledMemory)
|
|
{
|
|
//if ( ( Value & DPC_CLR_TMEM_CTR ) != 0)
|
|
//{
|
|
// g_Notify->DisplayError(L"RSP: DPC_STATUS_REG: DPC_CLR_TMEM_CTR");
|
|
//}
|
|
//if ( ( Value & DPC_CLR_PIPE_CTR ) != 0)
|
|
//{
|
|
// g_Notify->DisplayError(L"RSP: DPC_STATUS_REG: DPC_CLR_PIPE_CTR");
|
|
//}
|
|
//if ( ( Value & DPC_CLR_CMD_CTR ) != 0)
|
|
//{
|
|
// g_Notify->DisplayError(L"RSP: DPC_STATUS_REG: DPC_CLR_CMD_CTR");
|
|
//}
|
|
//if ( ( Value & DPC_CLR_CLOCK_CTR ) != 0)
|
|
//{
|
|
// g_Notify->DisplayError(L"RSP: DPC_STATUS_REG: DPC_CLR_CLOCK_CTR");
|
|
//}
|
|
}
|
|
#endif
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
break;
|
|
case 0x04300000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04300000:
|
|
g_Reg->MI_MODE_REG &= ~0x7F;
|
|
g_Reg->MI_MODE_REG |= (Value & 0x7F);
|
|
if ((Value & MI_CLR_INIT) != 0)
|
|
{
|
|
g_Reg->MI_MODE_REG &= ~MI_MODE_INIT;
|
|
}
|
|
if ((Value & MI_SET_INIT) != 0)
|
|
{
|
|
g_Reg->MI_MODE_REG |= MI_MODE_INIT;
|
|
}
|
|
if ((Value & MI_CLR_EBUS) != 0)
|
|
{
|
|
g_Reg->MI_MODE_REG &= ~MI_MODE_EBUS;
|
|
}
|
|
if ((Value & MI_SET_EBUS) != 0)
|
|
{
|
|
g_Reg->MI_MODE_REG |= MI_MODE_EBUS;
|
|
}
|
|
if ((Value & MI_CLR_DP_INTR) != 0)
|
|
{
|
|
g_Reg->MI_INTR_REG &= ~MI_INTR_DP;
|
|
g_Reg->m_GfxIntrReg &= ~MI_INTR_DP;
|
|
g_Reg->CheckInterrupts();
|
|
}
|
|
if ((Value & MI_CLR_RDRAM) != 0)
|
|
{
|
|
g_Reg->MI_MODE_REG &= ~MI_MODE_RDRAM;
|
|
}
|
|
if ((Value & MI_SET_RDRAM) != 0)
|
|
{
|
|
g_Reg->MI_MODE_REG |= MI_MODE_RDRAM;
|
|
}
|
|
break;
|
|
case 0x0430000C:
|
|
if ((Value & MI_INTR_MASK_CLR_SP) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG &= ~MI_INTR_MASK_SP;
|
|
}
|
|
if ((Value & MI_INTR_MASK_SET_SP) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG |= MI_INTR_MASK_SP;
|
|
}
|
|
if ((Value & MI_INTR_MASK_CLR_SI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG &= ~MI_INTR_MASK_SI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_SET_SI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG |= MI_INTR_MASK_SI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_CLR_AI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG &= ~MI_INTR_MASK_AI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_SET_AI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG |= MI_INTR_MASK_AI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_CLR_VI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG &= ~MI_INTR_MASK_VI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_SET_VI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG |= MI_INTR_MASK_VI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_CLR_PI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG &= ~MI_INTR_MASK_PI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_SET_PI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG |= MI_INTR_MASK_PI;
|
|
}
|
|
if ((Value & MI_INTR_MASK_CLR_DP) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG &= ~MI_INTR_MASK_DP;
|
|
}
|
|
if ((Value & MI_INTR_MASK_SET_DP) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG |= MI_INTR_MASK_DP;
|
|
}
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
break;
|
|
case 0x04400000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04400000:
|
|
if (g_Reg->VI_STATUS_REG != Value)
|
|
{
|
|
g_Reg->VI_STATUS_REG = Value;
|
|
if (g_Plugins->Gfx()->ViStatusChanged != NULL)
|
|
{
|
|
g_Plugins->Gfx()->ViStatusChanged();
|
|
}
|
|
}
|
|
break;
|
|
case 0x04400004:
|
|
#ifdef CFB_READ
|
|
if (g_Reg->VI_ORIGIN_REG > 0x280)
|
|
{
|
|
SetFrameBuffer(g_Reg->VI_ORIGIN_REG, (uint32_t)(VI_WIDTH_REG * (VI_WIDTH_REG *.75)));
|
|
}
|
|
#endif
|
|
g_Reg->VI_ORIGIN_REG = (Value & 0xFFFFFF);
|
|
//if (UpdateScreen != NULL )
|
|
//{
|
|
// UpdateScreen();
|
|
//}
|
|
break;
|
|
case 0x04400008:
|
|
if (g_Reg->VI_WIDTH_REG != Value)
|
|
{
|
|
g_Reg->VI_WIDTH_REG = Value;
|
|
if (g_Plugins->Gfx()->ViWidthChanged != NULL)
|
|
{
|
|
g_Plugins->Gfx()->ViWidthChanged();
|
|
}
|
|
}
|
|
break;
|
|
case 0x0440000C: g_Reg->VI_INTR_REG = Value; break;
|
|
case 0x04400010:
|
|
g_Reg->MI_INTR_REG &= ~MI_INTR_VI;
|
|
g_Reg->CheckInterrupts();
|
|
break;
|
|
case 0x04400014: g_Reg->VI_BURST_REG = Value; break;
|
|
case 0x04400018: g_Reg->VI_V_SYNC_REG = Value; break;
|
|
case 0x0440001C: g_Reg->VI_H_SYNC_REG = Value; break;
|
|
case 0x04400020: g_Reg->VI_LEAP_REG = Value; break;
|
|
case 0x04400024: g_Reg->VI_H_START_REG = Value; break;
|
|
case 0x04400028: g_Reg->VI_V_START_REG = Value; break;
|
|
case 0x0440002C: g_Reg->VI_V_BURST_REG = Value; break;
|
|
case 0x04400030: g_Reg->VI_X_SCALE_REG = Value; break;
|
|
case 0x04400034: g_Reg->VI_Y_SCALE_REG = Value; break;
|
|
default:
|
|
return false;
|
|
}
|
|
break;
|
|
case 0x04500000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04500000: g_Reg->AI_DRAM_ADDR_REG = Value; break;
|
|
case 0x04500004:
|
|
g_Reg->AI_LEN_REG = Value;
|
|
if (g_System->bFixedAudio())
|
|
{
|
|
g_Audio->LenChanged();
|
|
}
|
|
else
|
|
{
|
|
if (g_Plugins->Audio()->AiLenChanged != NULL)
|
|
{
|
|
g_Plugins->Audio()->AiLenChanged();
|
|
}
|
|
}
|
|
break;
|
|
case 0x04500008: g_Reg->AI_CONTROL_REG = (Value & 1); break;
|
|
case 0x0450000C:
|
|
/* Clear Interrupt */;
|
|
g_Reg->MI_INTR_REG &= ~MI_INTR_AI;
|
|
g_Reg->m_AudioIntrReg &= ~MI_INTR_AI;
|
|
g_Reg->CheckInterrupts();
|
|
break;
|
|
case 0x04500010:
|
|
g_Reg->AI_DACRATE_REG = Value;
|
|
g_Plugins->Audio()->DacrateChanged(g_System->SystemType());
|
|
if (g_System->bFixedAudio())
|
|
{
|
|
g_Audio->SetFrequency(Value, g_System->SystemType());
|
|
}
|
|
break;
|
|
case 0x04500014: g_Reg->AI_BITRATE_REG = Value; break;
|
|
default:
|
|
return false;
|
|
}
|
|
break;
|
|
case 0x04600000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04600000: g_Reg->PI_DRAM_ADDR_REG = Value; break;
|
|
case 0x04600004: g_Reg->PI_CART_ADDR_REG = Value; break;
|
|
case 0x04600008:
|
|
g_Reg->PI_RD_LEN_REG = Value;
|
|
PI_DMA_READ();
|
|
break;
|
|
case 0x0460000C:
|
|
g_Reg->PI_WR_LEN_REG = Value;
|
|
PI_DMA_WRITE();
|
|
break;
|
|
case 0x04600010:
|
|
//if ((Value & PI_SET_RESET) != 0 )
|
|
//{
|
|
// g_Notify->DisplayError(L"reset Controller");
|
|
//}
|
|
if ((Value & PI_CLR_INTR) != 0)
|
|
{
|
|
g_Reg->MI_INTR_REG &= ~MI_INTR_PI;
|
|
g_Reg->CheckInterrupts();
|
|
}
|
|
break;
|
|
case 0x04600014: g_Reg->PI_DOMAIN1_REG = (Value & 0xFF); break;
|
|
case 0x04600018: g_Reg->PI_BSD_DOM1_PWD_REG = (Value & 0xFF); break;
|
|
case 0x0460001C: g_Reg->PI_BSD_DOM1_PGS_REG = (Value & 0xFF); break;
|
|
case 0x04600020: g_Reg->PI_BSD_DOM1_RLS_REG = (Value & 0xFF); break;
|
|
case 0x04600024: g_Reg->PI_DOMAIN2_REG = (Value & 0xFF); break;
|
|
case 0x04600028: g_Reg->PI_BSD_DOM2_PWD_REG = (Value & 0xFF); break;
|
|
case 0x0460002C: g_Reg->PI_BSD_DOM2_PGS_REG = (Value & 0xFF); break;
|
|
case 0x04600030: g_Reg->PI_BSD_DOM2_RLS_REG = (Value & 0xFF); break;
|
|
default:
|
|
return false;
|
|
}
|
|
break;
|
|
case 0x04700000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04700000: g_Reg->RI_MODE_REG = Value; break;
|
|
case 0x04700004: g_Reg->RI_CONFIG_REG = Value; break;
|
|
case 0x04700008: g_Reg->RI_CURRENT_LOAD_REG = Value; break;
|
|
case 0x0470000C: g_Reg->RI_SELECT_REG = Value; break;
|
|
case 0x04700010: g_Reg->RI_REFRESH_REG = Value; break;
|
|
case 0x04700014: g_Reg->RI_LATENCY_REG = Value; break;
|
|
case 0x04700018: g_Reg->RI_RERROR_REG = Value; break;
|
|
case 0x0470001C: g_Reg->RI_WERROR_REG = Value; break;
|
|
default:
|
|
return false;
|
|
}
|
|
break;
|
|
case 0x04800000:
|
|
switch (PAddr)
|
|
{
|
|
case 0x04800000: g_Reg->SI_DRAM_ADDR_REG = Value; break;
|
|
case 0x04800004:
|
|
g_Reg->SI_PIF_ADDR_RD64B_REG = Value;
|
|
SI_DMA_READ();
|
|
break;
|
|
case 0x04800010:
|
|
g_Reg->SI_PIF_ADDR_WR64B_REG = Value;
|
|
SI_DMA_WRITE();
|
|
break;
|
|
case 0x04800018:
|
|
g_Reg->MI_INTR_REG &= ~MI_INTR_SI;
|
|
g_Reg->SI_STATUS_REG &= ~SI_STATUS_INTERRUPT;
|
|
g_Reg->CheckInterrupts();
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
break;
|
|
case 0x08000000:
|
|
if (g_System->m_SaveUsing == SaveChip_Sram)
|
|
{
|
|
//Store Sram
|
|
uint8_t tmp[4] = "";
|
|
tmp[0] = 0xFF & (Value);
|
|
tmp[1] = 0xFF & (Value >> 8);
|
|
tmp[2] = 0xFF & (Value >> 16);
|
|
tmp[3] = 0xFF & (Value >> 24);
|
|
DmaFromSram(tmp, PAddr - 0x08000000, 4);
|
|
return true;
|
|
}
|
|
if (PAddr != 0x08010000)
|
|
{
|
|
return false;
|
|
}
|
|
if (g_System->m_SaveUsing == SaveChip_Auto)
|
|
{
|
|
g_System->m_SaveUsing = SaveChip_FlashRam;
|
|
}
|
|
if (g_System->m_SaveUsing != SaveChip_FlashRam)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
WriteToFlashCommand(Value);
|
|
return true;
|
|
break;
|
|
case 0x1FC00000:
|
|
if (PAddr < 0x1FC007C0)
|
|
{
|
|
return false;
|
|
}
|
|
else if (PAddr < 0x1FC00800)
|
|
{
|
|
Value = swap32by8(Value);
|
|
*(uint32_t *)(&m_PifRam[PAddr - 0x1FC007C0]) = Value;
|
|
if (PAddr == 0x1FC007FC)
|
|
{
|
|
PifRamWrite();
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
break;
|
|
default:
|
|
return false;
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CMipsMemoryVM::UpdateHalfLine()
|
|
{
|
|
uint32_t NextViTimer = g_SystemTimer->GetTimer(CSystemTimer::ViTimer);
|
|
|
|
if (*g_NextTimer < 0)
|
|
{
|
|
m_HalfLine = 0;
|
|
return;
|
|
}
|
|
|
|
int32_t check_value = (int32_t)(m_HalfLineCheck - NextViTimer);
|
|
if (check_value > 0 && check_value < 40)
|
|
{
|
|
*g_NextTimer -= g_System->ViRefreshRate();
|
|
if (*g_NextTimer < 0)
|
|
{
|
|
*g_NextTimer = 0 - g_System->CountPerOp();
|
|
}
|
|
g_SystemTimer->UpdateTimers();
|
|
NextViTimer = g_SystemTimer->GetTimer(CSystemTimer::ViTimer);
|
|
}
|
|
m_HalfLine = (uint32_t)(*g_NextTimer / g_System->ViRefreshRate());
|
|
m_HalfLine &= ~1;
|
|
m_HalfLine |= m_FieldSerration;
|
|
g_Reg->VI_V_CURRENT_LINE_REG = m_HalfLine;
|
|
m_HalfLineCheck = NextViTimer;
|
|
}
|
|
|
|
void CMipsMemoryVM::UpdateFieldSerration(uint32_t interlaced)
|
|
{
|
|
m_FieldSerration ^= 1;
|
|
m_FieldSerration &= interlaced;
|
|
}
|
|
|
|
void CMipsMemoryVM::ProtectMemory(uint32_t StartVaddr, uint32_t EndVaddr)
|
|
{
|
|
WriteTrace(TraceProtectedMem, TraceDebug, "StartVaddr: %08X EndVaddr: %08X", StartVaddr, EndVaddr);
|
|
if (!ValidVaddr(StartVaddr) || !ValidVaddr(EndVaddr))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//Get Physical Addresses passed
|
|
uint32_t StartPAddr, EndPAddr;
|
|
if (!TranslateVaddr(StartVaddr, StartPAddr))
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
if (!TranslateVaddr(EndVaddr, EndPAddr))
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
|
|
//Get Length of memory being protected
|
|
int32_t Length = ((EndPAddr + 3) - StartPAddr) & ~3;
|
|
if (Length < 0)
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
|
|
//Protect that memory address space
|
|
DWORD OldProtect;
|
|
uint8_t * MemLoc = Rdram() + StartPAddr;
|
|
WriteTrace(TraceProtectedMem, TraceDebug, "Paddr: %08X Length: %X", StartPAddr, Length);
|
|
|
|
VirtualProtect(MemLoc, Length, PAGE_READONLY, &OldProtect);
|
|
}
|
|
|
|
void CMipsMemoryVM::UnProtectMemory(uint32_t StartVaddr, uint32_t EndVaddr)
|
|
{
|
|
WriteTrace(TraceProtectedMem, TraceDebug, "StartVaddr: %08X EndVaddr: %08X", StartVaddr, EndVaddr);
|
|
if (!ValidVaddr(StartVaddr) || !ValidVaddr(EndVaddr)) { return; }
|
|
|
|
//Get Physical Addresses passed
|
|
uint32_t StartPAddr, EndPAddr;
|
|
if (!TranslateVaddr(StartVaddr, StartPAddr))
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
if (!TranslateVaddr(EndVaddr, EndPAddr))
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
|
|
//Get Length of memory being protected
|
|
int32_t Length = ((EndPAddr + 3) - StartPAddr) & ~3;
|
|
if (Length < 0)
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
|
|
//Protect that memory address space
|
|
DWORD OldProtect;
|
|
uint8_t * MemLoc = Rdram() + StartPAddr;
|
|
|
|
VirtualProtect(MemLoc, Length, PAGE_READWRITE, &OldProtect);
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LB()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1, TempReg2;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (Opcode.rt == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = (GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset) ^ 3;
|
|
Map_GPR_32bit(Opcode.rt, true, -1);
|
|
Compile_LB(GetMipsRegMapLo(Opcode.rt), Address, true);
|
|
return;
|
|
}
|
|
if (IsMapped(Opcode.rt))
|
|
{
|
|
ProtectGPR(Opcode.rt);
|
|
}
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TempReg2, TempReg2, 4);
|
|
CompileReadTLBMiss(TempReg1, TempReg2);
|
|
XorConstToX86Reg(TempReg1, 3);
|
|
Map_GPR_32bit(Opcode.rt, true, -1);
|
|
MoveSxByteX86regPointerToX86reg(TempReg1, TempReg2, GetMipsRegMapLo(Opcode.rt));
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
XorConstToX86Reg(TempReg1, 3);
|
|
Map_GPR_32bit(Opcode.rt, true, -1);
|
|
MoveSxN64MemToX86regByte(GetMipsRegMapLo(Opcode.rt), TempReg1);
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LBU()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1, TempReg2;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (Opcode.rt == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = (GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset) ^ 3;
|
|
Map_GPR_32bit(Opcode.rt, false, -1);
|
|
Compile_LB(GetMipsRegMapLo(Opcode.rt), Address, false);
|
|
return;
|
|
}
|
|
if (IsMapped(Opcode.rt))
|
|
{
|
|
ProtectGPR(Opcode.rt);
|
|
}
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TempReg2, TempReg2, 4);
|
|
CompileReadTLBMiss(TempReg1, TempReg2);
|
|
XorConstToX86Reg(TempReg1, 3);
|
|
Map_GPR_32bit(Opcode.rt, false, -1);
|
|
MoveZxByteX86regPointerToX86reg(TempReg1, TempReg2, GetMipsRegMapLo(Opcode.rt));
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
XorConstToX86Reg(TempReg1, 3);
|
|
Map_GPR_32bit(Opcode.rt, false, -1);
|
|
MoveZxN64MemToX86regByte(GetMipsRegMapLo(Opcode.rt), TempReg1);
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LH()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1, TempReg2;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (Opcode.rt == 0) return;
|
|
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = (GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset) ^ 2;
|
|
Map_GPR_32bit(Opcode.rt, true, -1);
|
|
Compile_LH(GetMipsRegMapLo(Opcode.rt), Address, true);
|
|
return;
|
|
}
|
|
if (IsMapped(Opcode.rt))
|
|
{
|
|
ProtectGPR(Opcode.rt);
|
|
}
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TempReg2, TempReg2, 4);
|
|
CompileReadTLBMiss(TempReg1, TempReg2);
|
|
XorConstToX86Reg(TempReg1, 2);
|
|
Map_GPR_32bit(Opcode.rt, true, -1);
|
|
MoveSxHalfX86regPointerToX86reg(TempReg1, TempReg2, GetMipsRegMapLo(Opcode.rt));
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
XorConstToX86Reg(TempReg1, 2);
|
|
Map_GPR_32bit(Opcode.rt, true, -1);
|
|
MoveSxN64MemToX86regHalf(GetMipsRegMapLo(Opcode.rt), TempReg1);
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LHU()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1, TempReg2;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (Opcode.rt == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = (GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset) ^ 2;
|
|
Map_GPR_32bit(Opcode.rt, false, -1);
|
|
Compile_LH(GetMipsRegMapLo(Opcode.rt), Address, false);
|
|
return;
|
|
}
|
|
if (IsMapped(Opcode.rt))
|
|
{
|
|
ProtectGPR(Opcode.rt);
|
|
}
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TempReg2, TempReg2, 4);
|
|
CompileReadTLBMiss(TempReg1, TempReg2);
|
|
XorConstToX86Reg(TempReg1, 2);
|
|
Map_GPR_32bit(Opcode.rt, false, -1);
|
|
MoveZxHalfX86regPointerToX86reg(TempReg1, TempReg2, GetMipsRegMapLo(Opcode.rt));
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
XorConstToX86Reg(TempReg1, 2);
|
|
Map_GPR_32bit(Opcode.rt, true, -1);
|
|
MoveZxN64MemToX86regHalf(GetMipsRegMapLo(Opcode.rt), TempReg1);
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LW()
|
|
{
|
|
Compile_LW(true, false);
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LL()
|
|
{
|
|
Compile_LW(true, true);
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LW(bool ResultSigned, bool bRecordLLBit)
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (Opcode.rt == 0) return;
|
|
|
|
x86Reg TempReg1, TempReg2;
|
|
if (Opcode.base == 29 && g_System->bFastSP())
|
|
{
|
|
char String[100];
|
|
|
|
Map_GPR_32bit(Opcode.rt, ResultSigned, -1);
|
|
TempReg1 = Map_MemoryStack(x86_Any, true);
|
|
sprintf(String, "%Xh", (int16_t)Opcode.offset);
|
|
MoveVariableDispToX86Reg((void *)((uint32_t)(int16_t)Opcode.offset), String, GetMipsRegMapLo(Opcode.rt), TempReg1, 1);
|
|
if (bRecordLLBit)
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset;
|
|
Map_GPR_32bit(Opcode.rt, ResultSigned, -1);
|
|
Compile_LW(GetMipsRegMapLo(Opcode.rt), Address);
|
|
if (bRecordLLBit)
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (g_System->bUseTlb())
|
|
{
|
|
if (IsMapped(Opcode.rt))
|
|
{
|
|
ProtectGPR(Opcode.rt);
|
|
}
|
|
if (IsMapped(Opcode.base) && Opcode.offset == 0)
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
TempReg1 = GetMipsRegMapLo(Opcode.base);
|
|
}
|
|
else
|
|
{
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0) {
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
}
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TempReg2, TempReg2, 4);
|
|
CompileReadTLBMiss(TempReg1, TempReg2);
|
|
Map_GPR_32bit(Opcode.rt, ResultSigned, -1);
|
|
MoveX86regPointerToX86reg(TempReg1, TempReg2, GetMipsRegMapLo(Opcode.rt));
|
|
if (bRecordLLBit)
|
|
{
|
|
MoveConstToVariable(1, _LLBit, "LLBit");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
Map_GPR_32bit(Opcode.rt, ResultSigned, -1);
|
|
LeaSourceAndOffset(GetMipsRegMapLo(Opcode.rt), GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
Map_GPR_32bit(Opcode.rt, ResultSigned, Opcode.base);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Map_GPR_32bit(Opcode.rt, ResultSigned, Opcode.base);
|
|
AddConstToX86Reg(GetMipsRegMapLo(Opcode.rt), (int16_t)Opcode.immediate);
|
|
}
|
|
AndConstToX86Reg(GetMipsRegMapLo(Opcode.rt), 0x1FFFFFFF);
|
|
MoveN64MemToX86reg(GetMipsRegMapLo(Opcode.rt), GetMipsRegMapLo(Opcode.rt));
|
|
if (bRecordLLBit)
|
|
{
|
|
MoveConstToVariable(1, _LLBit, "LLBit");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (g_System->bFastSP() && Opcode.rt == 29)
|
|
{
|
|
ResetX86Protection();
|
|
ResetMemoryStack();
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LWC1()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1, TempReg2, TempReg3;
|
|
char Name[50];
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
m_Section->CompileCop1Test();
|
|
if ((Opcode.ft & 1) != 0)
|
|
{
|
|
if (RegInStack(Opcode.ft - 1, CRegInfo::FPU_Double) || RegInStack(Opcode.ft - 1, CRegInfo::FPU_Qword))
|
|
{
|
|
UnMap_FPR(Opcode.ft - 1, true);
|
|
}
|
|
}
|
|
if (RegInStack(Opcode.ft, CRegInfo::FPU_Double) || RegInStack(Opcode.ft, CRegInfo::FPU_Qword))
|
|
{
|
|
UnMap_FPR(Opcode.ft, true);
|
|
}
|
|
else
|
|
{
|
|
UnMap_FPR(Opcode.ft, false);
|
|
}
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset;
|
|
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
Compile_LW(TempReg1, Address);
|
|
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
sprintf(Name, "_FPR_S[%d]", Opcode.ft);
|
|
MoveVariableToX86reg(&_FPR_S[Opcode.ft], Name, TempReg2);
|
|
MoveX86regToX86Pointer(TempReg1, TempReg2);
|
|
return;
|
|
}
|
|
if (IsMapped(Opcode.base) && Opcode.offset == 0)
|
|
{
|
|
if (g_System->bUseTlb())
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
TempReg1 = GetMipsRegMapLo(Opcode.base);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
UnProtectGPR(Opcode.base);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
if (Opcode.immediate == 0)
|
|
{
|
|
}
|
|
else if (Opcode.immediate == 1)
|
|
{
|
|
IncX86reg(TempReg1);
|
|
}
|
|
else if (Opcode.immediate == 0xFFFF)
|
|
{
|
|
DecX86reg(TempReg1);
|
|
}
|
|
else
|
|
{
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
}
|
|
}
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
if (g_System->bUseTlb())
|
|
{
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TempReg2, TempReg2, 4);
|
|
CompileReadTLBMiss(TempReg1, TempReg2);
|
|
|
|
TempReg3 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86regPointerToX86reg(TempReg1, TempReg2, TempReg3);
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
TempReg3 = Map_TempReg(x86_Any, -1, false);
|
|
MoveN64MemToX86reg(TempReg3, TempReg1);
|
|
}
|
|
sprintf(Name, "_FPR_S[%d]", Opcode.ft);
|
|
MoveVariableToX86reg(&_FPR_S[Opcode.ft], Name, TempReg2);
|
|
MoveX86regToX86Pointer(TempReg3, TempReg2);
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LWL()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1 = x86_Unknown, TempReg2 = x86_Unknown, OffsetReg = x86_Unknown, shift = x86_Unknown;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (Opcode.rt == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset;
|
|
uint32_t Offset = Address & 3;
|
|
|
|
Map_GPR_32bit(Opcode.rt, true, Opcode.rt);
|
|
x86Reg Value = Map_TempReg(x86_Any, -1, false);
|
|
Compile_LW(Value, (Address & ~3));
|
|
AndConstToX86Reg(GetMipsRegMapLo(Opcode.rt), LWL_MASK[Offset]);
|
|
ShiftLeftSignImmed(Value, (uint8_t)LWL_SHIFT[Offset]);
|
|
AddX86RegToX86Reg(GetMipsRegMapLo(Opcode.rt), Value);
|
|
return;
|
|
}
|
|
|
|
shift = Map_TempReg(x86_ECX, -1, false);
|
|
if (IsMapped(Opcode.rt))
|
|
{
|
|
ProtectGPR(Opcode.rt);
|
|
}
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
UnProtectGPR(Opcode.base);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TempReg2, TempReg2, 4);
|
|
|
|
CompileReadTLBMiss(TempReg1, TempReg2);
|
|
}
|
|
OffsetReg = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, OffsetReg);
|
|
AndConstToX86Reg(OffsetReg, 3);
|
|
AndConstToX86Reg(TempReg1, (uint32_t)~3);
|
|
|
|
Map_GPR_32bit(Opcode.rt, true, Opcode.rt);
|
|
AndVariableDispToX86Reg((void *)LWL_MASK, "LWL_MASK", GetMipsRegMapLo(Opcode.rt), OffsetReg, Multip_x4);
|
|
MoveVariableDispToX86Reg((void *)LWL_SHIFT, "LWL_SHIFT", shift, OffsetReg, 4);
|
|
if (g_System->bUseTlb())
|
|
{
|
|
MoveX86regPointerToX86reg(TempReg1, TempReg2, TempReg1);
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
MoveN64MemToX86reg(TempReg1, TempReg1);
|
|
}
|
|
ShiftLeftSign(TempReg1);
|
|
AddX86RegToX86Reg(GetMipsRegMapLo(Opcode.rt), TempReg1);
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LWR()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1 = x86_Unknown, TempReg2 = x86_Unknown, OffsetReg = x86_Unknown, shift = x86_Unknown;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (Opcode.rt == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset;
|
|
uint32_t Offset = Address & 3;
|
|
|
|
Map_GPR_32bit(Opcode.rt, true, Opcode.rt);
|
|
x86Reg Value = Map_TempReg(x86_Any, -1, false);
|
|
Compile_LW(Value, (Address & ~3));
|
|
AndConstToX86Reg(GetMipsRegMapLo(Opcode.rt), LWR_MASK[Offset]);
|
|
ShiftRightUnsignImmed(Value, (uint8_t)LWR_SHIFT[Offset]);
|
|
AddX86RegToX86Reg(GetMipsRegMapLo(Opcode.rt), Value);
|
|
return;
|
|
}
|
|
|
|
shift = Map_TempReg(x86_ECX, -1, false);
|
|
if (IsMapped(Opcode.rt))
|
|
{
|
|
ProtectGPR(Opcode.rt);
|
|
}
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
UnProtectGPR(Opcode.base);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TempReg2, TempReg2, 4);
|
|
|
|
CompileReadTLBMiss(TempReg1, TempReg2);
|
|
}
|
|
OffsetReg = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, OffsetReg);
|
|
AndConstToX86Reg(OffsetReg, 3);
|
|
AndConstToX86Reg(TempReg1, (uint32_t)~3);
|
|
|
|
Map_GPR_32bit(Opcode.rt, true, Opcode.rt);
|
|
AndVariableDispToX86Reg((void *)LWR_MASK, "LWR_MASK", GetMipsRegMapLo(Opcode.rt), OffsetReg, Multip_x4);
|
|
MoveVariableDispToX86Reg((void *)LWR_SHIFT, "LWR_SHIFT", shift, OffsetReg, 4);
|
|
if (g_System->bUseTlb())
|
|
{
|
|
MoveX86regPointerToX86reg(TempReg1, TempReg2, TempReg1);
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
MoveN64MemToX86reg(TempReg1, TempReg1);
|
|
}
|
|
ShiftRightUnsign(TempReg1);
|
|
AddX86RegToX86Reg(GetMipsRegMapLo(Opcode.rt), TempReg1);
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LWU()
|
|
{
|
|
Compile_LW(false, false);
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LD()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (Opcode.rt == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
x86Reg TempReg1, TempReg2;
|
|
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset;
|
|
Map_GPR_64bit(Opcode.rt, -1);
|
|
Compile_LW(GetMipsRegMapHi(Opcode.rt), Address);
|
|
Compile_LW(GetMipsRegMapLo(Opcode.rt), Address + 4);
|
|
if (g_System->bFastSP() && Opcode.rt == 29)
|
|
{
|
|
ResetMemoryStack();
|
|
}
|
|
return;
|
|
}
|
|
if (IsMapped(Opcode.rt))
|
|
{
|
|
ProtectGPR(Opcode.rt);
|
|
}
|
|
if (IsMapped(Opcode.base) && Opcode.offset == 0)
|
|
{
|
|
if (g_System->bUseTlb())
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
TempReg1 = GetMipsRegMapLo(Opcode.base);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
}
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TempReg2, TempReg2, 4);
|
|
CompileReadTLBMiss(TempReg1, TempReg2);
|
|
Map_GPR_64bit(Opcode.rt, -1);
|
|
MoveX86regPointerToX86reg(TempReg1, TempReg2, GetMipsRegMapHi(Opcode.rt));
|
|
MoveX86regPointerToX86regDisp8(TempReg1, TempReg2, GetMipsRegMapLo(Opcode.rt), 4);
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
Map_GPR_64bit(Opcode.rt, -1);
|
|
MoveN64MemToX86reg(GetMipsRegMapHi(Opcode.rt), TempReg1);
|
|
MoveN64MemDispToX86reg(GetMipsRegMapLo(Opcode.rt), TempReg1, 4);
|
|
}
|
|
if (g_System->bFastSP() && Opcode.rt == 29)
|
|
{
|
|
ResetX86Protection();
|
|
g_MMU->ResetMemoryStack();
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LDC1()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1, TempReg2, TempReg3;
|
|
char Name[50];
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
m_Section->CompileCop1Test();
|
|
|
|
UnMap_FPR(Opcode.ft, false);
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset;
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
Compile_LW(TempReg1, Address);
|
|
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
sprintf(Name, "_FPR_D[%d]", Opcode.ft);
|
|
MoveVariableToX86reg(&_FPR_D[Opcode.ft], Name, TempReg2);
|
|
AddConstToX86Reg(TempReg2, 4);
|
|
MoveX86regToX86Pointer(TempReg1, TempReg2);
|
|
|
|
Compile_LW(TempReg1, Address + 4);
|
|
sprintf(Name, "_FPR_S[%d]", Opcode.ft);
|
|
MoveVariableToX86reg(&_FPR_D[Opcode.ft], Name, TempReg2);
|
|
MoveX86regToX86Pointer(TempReg1, TempReg2);
|
|
return;
|
|
}
|
|
if (IsMapped(Opcode.base) && Opcode.offset == 0)
|
|
{
|
|
if (g_System->bUseTlb())
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
TempReg1 = GetMipsRegMapLo(Opcode.base);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
if (Opcode.immediate == 0)
|
|
{
|
|
}
|
|
else if (Opcode.immediate == 1)
|
|
{
|
|
IncX86reg(TempReg1);
|
|
}
|
|
else if (Opcode.immediate == 0xFFFF)
|
|
{
|
|
DecX86reg(TempReg1);
|
|
}
|
|
else
|
|
{
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
}
|
|
}
|
|
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
if (g_System->bUseTlb())
|
|
{
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TempReg2, TempReg2, 4);
|
|
CompileReadTLBMiss(TempReg1, TempReg2);
|
|
TempReg3 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86regPointerToX86reg(TempReg1, TempReg2, TempReg3);
|
|
Push(TempReg2);
|
|
sprintf(Name, "_FPR_S[%d]", Opcode.ft);
|
|
MoveVariableToX86reg(&_FPR_D[Opcode.ft], Name, TempReg2);
|
|
AddConstToX86Reg(TempReg2, 4);
|
|
MoveX86regToX86Pointer(TempReg3, TempReg2);
|
|
Pop(TempReg2);
|
|
MoveX86regPointerToX86regDisp8(TempReg1, TempReg2, TempReg3, 4);
|
|
sprintf(Name, "_FPR_S[%d]", Opcode.ft);
|
|
MoveVariableToX86reg(&_FPR_D[Opcode.ft], Name, TempReg2);
|
|
MoveX86regToX86Pointer(TempReg3, TempReg2);
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
TempReg3 = Map_TempReg(x86_Any, -1, false);
|
|
MoveN64MemToX86reg(TempReg3, TempReg1);
|
|
|
|
sprintf(Name, "_FPR_S[%d]", Opcode.ft);
|
|
MoveVariableToX86reg(&_FPR_D[Opcode.ft], Name, TempReg2);
|
|
AddConstToX86Reg(TempReg2, 4);
|
|
MoveX86regToX86Pointer(TempReg3, TempReg2);
|
|
|
|
MoveN64MemDispToX86reg(TempReg3, TempReg1, 4);
|
|
sprintf(Name, "_FPR_S[%d]", Opcode.ft);
|
|
MoveVariableToX86reg(&_FPR_D[Opcode.ft], Name, TempReg2);
|
|
MoveX86regToX86Pointer(TempReg3, TempReg2);
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LDL()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (Opcode.base != 0)
|
|
{
|
|
UnMap_GPR(Opcode.base, true);
|
|
}
|
|
|
|
if (Opcode.rt != 0)
|
|
{
|
|
UnMap_GPR(Opcode.rt, true);
|
|
}
|
|
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToVariable(Opcode.Hex, &R4300iOp::m_Opcode.Hex, "R4300iOp::m_Opcode.Hex");
|
|
Call_Direct(R4300iOp::LDL, "R4300iOp::LDL");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_LDR()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (Opcode.base != 0)
|
|
{
|
|
UnMap_GPR(Opcode.base, true);
|
|
}
|
|
|
|
if (Opcode.rt != 0)
|
|
{
|
|
UnMap_GPR(Opcode.rt, true);
|
|
}
|
|
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToVariable(Opcode.Hex, &R4300iOp::m_Opcode.Hex, "R4300iOp::m_Opcode.Hex");
|
|
Call_Direct(R4300iOp::LDR, "R4300iOp::LDR");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SB()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1, TempReg2;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = (GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset) ^ 3;
|
|
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
Compile_SB_Const((uint8_t)(GetMipsRegLo(Opcode.rt) & 0xFF), Address);
|
|
}
|
|
else if (IsMapped(Opcode.rt) && Is8BitReg(GetMipsRegMapLo(Opcode.rt)))
|
|
{
|
|
Compile_SB_Register(GetMipsRegMapLo(Opcode.rt), Address);
|
|
}
|
|
else
|
|
{
|
|
Compile_SB_Register(Map_TempReg(x86_Any8Bit, Opcode.rt, false), Address);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (IsMapped(Opcode.rt))
|
|
{
|
|
ProtectGPR(Opcode.rt);
|
|
}
|
|
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
UnProtectGPR(Opcode.base);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
Compile_StoreInstructClean(TempReg1, 4);
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_WriteMap, "m_TLB_WriteMap", TempReg2, TempReg2, 4);
|
|
CompileWriteTLBMiss(TempReg1, TempReg2);
|
|
XorConstToX86Reg(TempReg1, 3);
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
MoveConstByteToX86regPointer((uint8_t)(GetMipsRegLo(Opcode.rt) & 0xFF), TempReg1, TempReg2);
|
|
}
|
|
else if (IsMapped(Opcode.rt) && Is8BitReg(GetMipsRegMapLo(Opcode.rt)))
|
|
{
|
|
MoveX86regByteToX86regPointer(GetMipsRegMapLo(Opcode.rt), TempReg1, TempReg2);
|
|
}
|
|
else
|
|
{
|
|
UnProtectGPR(Opcode.rt);
|
|
MoveX86regByteToX86regPointer(Map_TempReg(x86_Any8Bit, Opcode.rt, false), TempReg1, TempReg2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
XorConstToX86Reg(TempReg1, 3);
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
MoveConstByteToN64Mem((uint8_t)(GetMipsRegLo(Opcode.rt) & 0xFF), TempReg1);
|
|
}
|
|
else if (IsMapped(Opcode.rt) && Is8BitReg(GetMipsRegMapLo(Opcode.rt)))
|
|
{
|
|
MoveX86regByteToN64Mem(GetMipsRegMapLo(Opcode.rt), TempReg1);
|
|
}
|
|
else
|
|
{
|
|
UnProtectGPR(Opcode.rt);
|
|
MoveX86regByteToN64Mem(Map_TempReg(x86_Any8Bit, Opcode.rt, false), TempReg1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SH()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1, TempReg2;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = (GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset) ^ 2;
|
|
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
Compile_SH_Const((uint16_t)(GetMipsRegLo(Opcode.rt) & 0xFFFF), Address);
|
|
}
|
|
else if (IsMapped(Opcode.rt))
|
|
{
|
|
Compile_SH_Register(GetMipsRegMapLo(Opcode.rt), Address);
|
|
}
|
|
else
|
|
{
|
|
Compile_SH_Register(Map_TempReg(x86_Any, Opcode.rt, false), Address);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (IsMapped(Opcode.rt))
|
|
{
|
|
ProtectGPR(Opcode.rt);
|
|
}
|
|
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
UnProtectGPR(Opcode.base);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_WriteMap, "m_TLB_WriteMap", TempReg2, TempReg2, 4);
|
|
CompileWriteTLBMiss(TempReg1, TempReg2);
|
|
XorConstToX86Reg(TempReg1, 2);
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
MoveConstHalfToX86regPointer((uint16_t)(GetMipsRegLo(Opcode.rt) & 0xFFFF), TempReg1, TempReg2);
|
|
}
|
|
else if (IsMapped(Opcode.rt))
|
|
{
|
|
MoveX86regHalfToX86regPointer(GetMipsRegMapLo(Opcode.rt), TempReg1, TempReg2);
|
|
}
|
|
else
|
|
{
|
|
MoveX86regHalfToX86regPointer(Map_TempReg(x86_Any, Opcode.rt, false), TempReg1, TempReg2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
XorConstToX86Reg(TempReg1, 2);
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
MoveConstHalfToN64Mem((uint16_t)(GetMipsRegLo(Opcode.rt) & 0xFFFF), TempReg1);
|
|
}
|
|
else if (IsMapped(Opcode.rt))
|
|
{
|
|
MoveX86regHalfToN64Mem(GetMipsRegMapLo(Opcode.rt), TempReg1);
|
|
}
|
|
else
|
|
{
|
|
MoveX86regHalfToN64Mem(Map_TempReg(x86_Any, Opcode.rt, false), TempReg1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SW()
|
|
{
|
|
Compile_SW(false);
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SC()
|
|
{
|
|
Compile_SW(true);
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SW(bool bCheckLLbit)
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
x86Reg TempReg1, TempReg2;
|
|
if (Opcode.base == 29 && g_System->bFastSP())
|
|
{
|
|
if (bCheckLLbit)
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
if (IsMapped(Opcode.rt))
|
|
{
|
|
ProtectGPR(Opcode.rt);
|
|
}
|
|
TempReg1 = Map_MemoryStack(x86_Any, true);
|
|
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
MoveConstToMemoryDisp(GetMipsRegLo(Opcode.rt), TempReg1, (uint32_t)((int16_t)Opcode.offset));
|
|
}
|
|
else if (IsMapped(Opcode.rt))
|
|
{
|
|
MoveX86regToMemory(GetMipsRegMapLo(Opcode.rt), TempReg1, (uint32_t)((int16_t)Opcode.offset));
|
|
}
|
|
else
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, Opcode.rt, false);
|
|
MoveX86regToMemory(TempReg2, TempReg1, (uint32_t)((int16_t)Opcode.offset));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset;
|
|
|
|
if (bCheckLLbit)
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
Compile_SW_Const(GetMipsRegLo(Opcode.rt), Address);
|
|
}
|
|
else if (IsMapped(Opcode.rt))
|
|
{
|
|
Compile_SW_Register(GetMipsRegMapLo(Opcode.rt), Address);
|
|
}
|
|
else
|
|
{
|
|
Compile_SW_Register(Map_TempReg(x86_Any, Opcode.rt, false), Address);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (IsMapped(Opcode.rt))
|
|
ProtectGPR(Opcode.rt);
|
|
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (g_System->bDelaySI() || g_System->bDelayDP())
|
|
{
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp());
|
|
UpdateCounters(m_RegWorkingSet, false, true);
|
|
m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp());
|
|
}
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
UnProtectGPR(Opcode.base);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
Compile_StoreInstructClean(TempReg1, 4);
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_WriteMap, "m_TLB_WriteMap", TempReg2, TempReg2, 4);
|
|
CompileWriteTLBMiss(TempReg1, TempReg2);
|
|
uint8_t * Jump = NULL;
|
|
if (bCheckLLbit)
|
|
{
|
|
CompConstToVariable(1, _LLBit, "_LLBit");
|
|
JneLabel8("LLBit_Continue", 0);
|
|
Jump = m_RecompPos - 1;
|
|
}
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
MoveConstToX86regPointer(GetMipsRegLo(Opcode.rt), TempReg1, TempReg2);
|
|
}
|
|
else if (IsMapped(Opcode.rt))
|
|
{
|
|
MoveX86regToX86regPointer(GetMipsRegMapLo(Opcode.rt), TempReg1, TempReg2);
|
|
}
|
|
else
|
|
{
|
|
MoveX86regToX86regPointer(Map_TempReg(x86_Any, Opcode.rt, false), TempReg1, TempReg2);
|
|
}
|
|
if (bCheckLLbit)
|
|
{
|
|
CPU_Message(" ");
|
|
CPU_Message(" LLBit_Continue:");
|
|
SetJump8(Jump, m_RecompPos);
|
|
Map_GPR_32bit(Opcode.rt, false, -1);
|
|
MoveVariableToX86reg(_LLBit, "_LLBit", GetMipsRegMapLo(Opcode.rt));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bCheckLLbit)
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
MoveConstToN64Mem(GetMipsRegLo(Opcode.rt), TempReg1);
|
|
}
|
|
else if (IsMapped(Opcode.rt))
|
|
{
|
|
MoveX86regToN64Mem(GetMipsRegMapLo(Opcode.rt), TempReg1);
|
|
}
|
|
else
|
|
{
|
|
MoveX86regToN64Mem(Map_TempReg(x86_Any, Opcode.rt, false), TempReg1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SWC1()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1, TempReg2, TempReg3;
|
|
char Name[50];
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
m_Section->CompileCop1Test();
|
|
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset;
|
|
|
|
UnMap_FPR(Opcode.ft, true);
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
|
|
sprintf(Name, "_FPR_S[%d]", Opcode.ft);
|
|
MoveVariableToX86reg(&_FPR_S[Opcode.ft], Name, TempReg1);
|
|
MoveX86PointerToX86reg(TempReg1, TempReg1);
|
|
Compile_SW_Register(TempReg1, Address);
|
|
return;
|
|
}
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
if (Opcode.immediate == 0)
|
|
{
|
|
}
|
|
else if (Opcode.immediate == 1)
|
|
{
|
|
IncX86reg(TempReg1);
|
|
}
|
|
else if (Opcode.immediate == 0xFFFF)
|
|
{
|
|
DecX86reg(TempReg1);
|
|
}
|
|
else
|
|
{
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
}
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_WriteMap, "m_TLB_WriteMap", TempReg2, TempReg2, 4);
|
|
CompileWriteTLBMiss(TempReg1, TempReg2);
|
|
|
|
UnMap_FPR(Opcode.ft, true);
|
|
TempReg3 = Map_TempReg(x86_Any, -1, false);
|
|
sprintf(Name, "_FPR_S[%d]", Opcode.ft);
|
|
MoveVariableToX86reg(&_FPR_S[Opcode.ft], Name, TempReg3);
|
|
MoveX86PointerToX86reg(TempReg3, TempReg3);
|
|
MoveX86regToX86regPointer(TempReg3, TempReg1, TempReg2);
|
|
}
|
|
else
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
UnMap_FPR(Opcode.ft, true);
|
|
sprintf(Name, "_FPR_S[%d]", Opcode.ft);
|
|
MoveVariableToX86reg(&_FPR_S[Opcode.ft], Name, TempReg2);
|
|
MoveX86PointerToX86reg(TempReg2, TempReg2);
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
MoveX86regToN64Mem(TempReg2, TempReg1);
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SWL()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1 = x86_Unknown, TempReg2 = x86_Unknown, Value = x86_Unknown,
|
|
shift = x86_Unknown, OffsetReg = x86_Unknown;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address;
|
|
|
|
Address = GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset;
|
|
uint32_t Offset = Address & 3;
|
|
|
|
Value = Map_TempReg(x86_Any, -1, false);
|
|
Compile_LW(Value, (Address & ~3));
|
|
AndConstToX86Reg(Value, R4300iOp::SWL_MASK[Offset]);
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.rt, false);
|
|
ShiftRightUnsignImmed(TempReg1, (uint8_t)SWL_SHIFT[Offset]);
|
|
AddX86RegToX86Reg(Value, TempReg1);
|
|
Compile_SW_Register(Value, (Address & ~3));
|
|
return;
|
|
}
|
|
shift = Map_TempReg(x86_ECX, -1, false);
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
UnProtectGPR(Opcode.base);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TempReg2, TempReg2, 4);
|
|
CompileReadTLBMiss(TempReg1, TempReg2);
|
|
}
|
|
|
|
OffsetReg = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, OffsetReg);
|
|
AndConstToX86Reg(OffsetReg, 3);
|
|
AndConstToX86Reg(TempReg1, (uint32_t)~3);
|
|
|
|
Value = Map_TempReg(x86_Any, -1, false);
|
|
if (g_System->bUseTlb())
|
|
{
|
|
MoveX86regPointerToX86reg(TempReg1, TempReg2, Value);
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
MoveN64MemToX86reg(Value, TempReg1);
|
|
}
|
|
|
|
AndVariableDispToX86Reg((void *)SWL_MASK, "SWL_MASK", Value, OffsetReg, Multip_x4);
|
|
if (!IsConst(Opcode.rt) || GetMipsRegLo(Opcode.rt) != 0)
|
|
{
|
|
MoveVariableDispToX86Reg((void *)SWL_SHIFT, "SWL_SHIFT", shift, OffsetReg, 4);
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
MoveConstToX86reg(GetMipsRegLo(Opcode.rt), OffsetReg);
|
|
}
|
|
else if (IsMapped(Opcode.rt))
|
|
{
|
|
MoveX86RegToX86Reg(GetMipsRegMapLo(Opcode.rt), OffsetReg);
|
|
}
|
|
else
|
|
{
|
|
MoveVariableToX86reg(&_GPR[Opcode.rt].UW[0], CRegName::GPR_Lo[Opcode.rt], OffsetReg);
|
|
}
|
|
ShiftRightUnsign(OffsetReg);
|
|
AddX86RegToX86Reg(Value, OffsetReg);
|
|
}
|
|
|
|
if (g_System->bUseTlb())
|
|
{
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_WriteMap, "m_TLB_WriteMap", TempReg2, TempReg2, 4);
|
|
|
|
MoveX86regToX86regPointer(Value, TempReg1, TempReg2);
|
|
}
|
|
else
|
|
{
|
|
MoveX86regToN64Mem(Value, TempReg1);
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SWR()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1 = x86_Unknown, TempReg2 = x86_Unknown, Value = x86_Unknown,
|
|
OffsetReg = x86_Unknown, shift = x86_Unknown;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset;
|
|
uint32_t Offset = Address & 3;
|
|
|
|
Value = Map_TempReg(x86_Any, -1, false);
|
|
Compile_LW(Value, (Address & ~3));
|
|
AndConstToX86Reg(Value, SWR_MASK[Offset]);
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.rt, false);
|
|
ShiftLeftSignImmed(TempReg1, (uint8_t)SWR_SHIFT[Offset]);
|
|
AddX86RegToX86Reg(Value, TempReg1);
|
|
Compile_SW_Register(Value, (Address & ~3));
|
|
return;
|
|
}
|
|
shift = Map_TempReg(x86_ECX, -1, false);
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
UnProtectGPR(Opcode.base);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_ReadMap, "m_TLB_ReadMap", TempReg2, TempReg2, 4);
|
|
CompileReadTLBMiss(TempReg1, TempReg2);
|
|
}
|
|
|
|
OffsetReg = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, OffsetReg);
|
|
AndConstToX86Reg(OffsetReg, 3);
|
|
AndConstToX86Reg(TempReg1, (uint32_t)~3);
|
|
|
|
Value = Map_TempReg(x86_Any, -1, false);
|
|
if (g_System->bUseTlb())
|
|
{
|
|
MoveX86regPointerToX86reg(TempReg1, TempReg2, Value);
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
MoveN64MemToX86reg(Value, TempReg1);
|
|
}
|
|
|
|
AndVariableDispToX86Reg((void *)SWR_MASK, "SWR_MASK", Value, OffsetReg, Multip_x4);
|
|
if (!IsConst(Opcode.rt) || GetMipsRegLo(Opcode.rt) != 0)
|
|
{
|
|
MoveVariableDispToX86Reg((void *)SWR_SHIFT, "SWR_SHIFT", shift, OffsetReg, 4);
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
MoveConstToX86reg(GetMipsRegLo(Opcode.rt), OffsetReg);
|
|
}
|
|
else if (IsMapped(Opcode.rt))
|
|
{
|
|
MoveX86RegToX86Reg(GetMipsRegMapLo(Opcode.rt), OffsetReg);
|
|
}
|
|
else
|
|
{
|
|
MoveVariableToX86reg(&_GPR[Opcode.rt].UW[0], CRegName::GPR_Lo[Opcode.rt], OffsetReg);
|
|
}
|
|
ShiftLeftSign(OffsetReg);
|
|
AddX86RegToX86Reg(Value, OffsetReg);
|
|
}
|
|
|
|
if (g_System->bUseTlb())
|
|
{
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_WriteMap, "m_TLB_WriteMap", TempReg2, TempReg2, 4);
|
|
|
|
MoveX86regToX86regPointer(Value, TempReg1, TempReg2);
|
|
}
|
|
else
|
|
{
|
|
MoveX86regToN64Mem(Value, TempReg1);
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_StoreInstructClean(x86Reg AddressReg, int32_t Length)
|
|
{
|
|
if (!g_System->bSMM_StoreInstruc())
|
|
{
|
|
return;
|
|
}
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
/*
|
|
stdstr_f strLen("%d",Length);
|
|
UnMap_AllFPRs();
|
|
|
|
/*x86Reg StoreTemp1 = Map_TempReg(x86_Any,-1,false);
|
|
MoveX86RegToX86Reg(AddressReg, StoreTemp1);
|
|
AndConstToX86Reg(StoreTemp1,0xFFC);*/
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
PushImm32("CRecompiler::Remove_StoreInstruc", CRecompiler::Remove_StoreInstruc);
|
|
PushImm32(Length);
|
|
Push(AddressReg);
|
|
MoveConstToX86reg((uint32_t)g_Recompiler, x86_ECX);
|
|
Call_Direct(AddressOf(&CRecompiler::ClearRecompCode_Virt), "CRecompiler::ClearRecompCode_Virt");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
/*JmpLabel8("MemCheckDone",0);
|
|
uint8_t * MemCheckDone = m_RecompPos - 1;
|
|
|
|
CPU_Message(" ");
|
|
CPU_Message(" NotDelaySlot:");
|
|
SetJump8(NotDelaySlotJump,m_RecompPos);
|
|
|
|
MoveX86RegToX86Reg(AddressReg, StoreTemp1);
|
|
ShiftRightUnsignImmed(StoreTemp1,12);
|
|
LeaRegReg(StoreTemp1,StoreTemp1,(ULONG)&(g_Recompiler->FunctionTable()[0]),Multip_x4);
|
|
CompConstToX86regPointer(StoreTemp1,0);
|
|
JeLabel8("MemCheckDone",0);
|
|
uint8_t * MemCheckDone2 = m_RecompPos - 1;
|
|
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
PushImm32("CRecompiler::Remove_StoreInstruc",CRecompiler::Remove_StoreInstruc);
|
|
PushImm32(strLen.c_str(),Length);
|
|
Push(AddressReg);
|
|
MoveConstToX86reg((uint32_t)g_Recompiler,x86_ECX);
|
|
Call_Direct(AddressOf(&CRecompiler::ClearRecompCode_Virt), "CRecompiler::ClearRecompCode_Virt");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
|
|
CPU_Message(" ");
|
|
CPU_Message(" MemCheckDone:");
|
|
SetJump8(MemCheckDone,m_RecompPos);
|
|
SetJump8(MemCheckDone2,m_RecompPos);
|
|
|
|
X86Protected(StoreTemp1) = false;*/
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SD()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1, TempReg2;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset;
|
|
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
Compile_SW_Const(Is64Bit(Opcode.rt) ? GetMipsRegHi(Opcode.rt) : (GetMipsRegLo_S(Opcode.rt) >> 31), Address);
|
|
Compile_SW_Const(GetMipsRegLo(Opcode.rt), Address + 4);
|
|
}
|
|
else if (IsMapped(Opcode.rt))
|
|
{
|
|
Compile_SW_Register(Is64Bit(Opcode.rt) ? GetMipsRegMapHi(Opcode.rt) : Map_TempReg(x86_Any, Opcode.rt, true), Address);
|
|
Compile_SW_Register(GetMipsRegMapLo(Opcode.rt), Address + 4);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.rt, true);
|
|
Compile_SW_Register(TempReg1, Address);
|
|
Compile_SW_Register(Map_TempReg(TempReg1, Opcode.rt, false), Address + 4);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (IsMapped(Opcode.rt))
|
|
{
|
|
ProtectGPR(Opcode.rt);
|
|
}
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
UnProtectGPR(Opcode.base);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
|
|
Compile_StoreInstructClean(TempReg1, 8);
|
|
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_WriteMap, "m_TLB_WriteMap", TempReg2, TempReg2, 4);
|
|
CompileWriteTLBMiss(TempReg1, TempReg2);
|
|
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
if (Is64Bit(Opcode.rt))
|
|
{
|
|
MoveConstToX86regPointer(GetMipsRegHi(Opcode.rt), TempReg1, TempReg2);
|
|
}
|
|
else
|
|
{
|
|
MoveConstToX86regPointer((GetMipsRegLo_S(Opcode.rt) >> 31), TempReg1, TempReg2);
|
|
}
|
|
AddConstToX86Reg(TempReg1, 4);
|
|
MoveConstToX86regPointer(GetMipsRegLo(Opcode.rt), TempReg1, TempReg2);
|
|
}
|
|
else if (IsMapped(Opcode.rt))
|
|
{
|
|
if (Is64Bit(Opcode.rt))
|
|
{
|
|
MoveX86regToX86regPointer(GetMipsRegMapHi(Opcode.rt), TempReg1, TempReg2);
|
|
}
|
|
else
|
|
{
|
|
MoveX86regToX86regPointer(Map_TempReg(x86_Any, Opcode.rt, true), TempReg1, TempReg2);
|
|
}
|
|
AddConstToX86Reg(TempReg1, 4);
|
|
MoveX86regToX86regPointer(GetMipsRegMapLo(Opcode.rt), TempReg1, TempReg2);
|
|
}
|
|
else
|
|
{
|
|
x86Reg Reg = Map_TempReg(x86_Any, Opcode.rt, true);
|
|
MoveX86regToX86regPointer(Reg, TempReg1, TempReg2);
|
|
AddConstToX86Reg(TempReg1, 4);
|
|
MoveX86regToX86regPointer(Map_TempReg(Reg, Opcode.rt, false), TempReg1, TempReg2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
if (IsConst(Opcode.rt))
|
|
{
|
|
if (Is64Bit(Opcode.rt))
|
|
{
|
|
MoveConstToN64Mem(GetMipsRegHi(Opcode.rt), TempReg1);
|
|
}
|
|
else if (IsSigned(Opcode.rt))
|
|
{
|
|
MoveConstToN64Mem((GetMipsRegLo_S(Opcode.rt) >> 31), TempReg1);
|
|
}
|
|
else
|
|
{
|
|
MoveConstToN64Mem(0, TempReg1);
|
|
}
|
|
MoveConstToN64MemDisp(GetMipsRegLo(Opcode.rt), TempReg1, 4);
|
|
}
|
|
else if (IsKnown(Opcode.rt) && IsMapped(Opcode.rt))
|
|
{
|
|
if (Is64Bit(Opcode.rt))
|
|
{
|
|
MoveX86regToN64Mem(GetMipsRegMapHi(Opcode.rt), TempReg1);
|
|
}
|
|
else if (IsSigned(Opcode.rt))
|
|
{
|
|
MoveX86regToN64Mem(Map_TempReg(x86_Any, Opcode.rt, true), TempReg1);
|
|
}
|
|
else
|
|
{
|
|
MoveConstToN64Mem(0, TempReg1);
|
|
}
|
|
MoveX86regToN64MemDisp(GetMipsRegMapLo(Opcode.rt), TempReg1, 4);
|
|
}
|
|
else
|
|
{
|
|
x86Reg Reg;
|
|
MoveX86regToN64Mem(Reg = Map_TempReg(x86_Any, Opcode.rt, true), TempReg1);
|
|
MoveX86regToN64MemDisp(Map_TempReg(Reg, Opcode.rt, false), TempReg1, 4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SDC1()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
x86Reg TempReg1, TempReg2, TempReg3;
|
|
char Name[50];
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
m_Section->CompileCop1Test();
|
|
|
|
if (IsConst(Opcode.base))
|
|
{
|
|
uint32_t Address = GetMipsRegLo(Opcode.base) + (int16_t)Opcode.offset;
|
|
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
sprintf(Name, "_FPR_D[%d]", Opcode.ft);
|
|
MoveVariableToX86reg((uint8_t *)&_FPR_D[Opcode.ft], Name, TempReg1);
|
|
AddConstToX86Reg(TempReg1, 4);
|
|
MoveX86PointerToX86reg(TempReg1, TempReg1);
|
|
Compile_SW_Register(TempReg1, Address);
|
|
|
|
sprintf(Name, "_FPR_D[%d]", Opcode.ft);
|
|
MoveVariableToX86reg(&_FPR_D[Opcode.ft], Name, TempReg1);
|
|
MoveX86PointerToX86reg(TempReg1, TempReg1);
|
|
Compile_SW_Register(TempReg1, Address + 4);
|
|
return;
|
|
}
|
|
if (IsMapped(Opcode.base))
|
|
{
|
|
ProtectGPR(Opcode.base);
|
|
if (Opcode.offset != 0)
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, -1, false);
|
|
LeaSourceAndOffset(TempReg1, GetMipsRegMapLo(Opcode.base), (int16_t)Opcode.offset);
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TempReg1 = Map_TempReg(x86_Any, Opcode.base, false);
|
|
if (Opcode.immediate == 0)
|
|
{
|
|
}
|
|
else if (Opcode.immediate == 1)
|
|
{
|
|
IncX86reg(TempReg1);
|
|
}
|
|
else if (Opcode.immediate == 0xFFFF)
|
|
{
|
|
DecX86reg(TempReg1);
|
|
}
|
|
else
|
|
{
|
|
AddConstToX86Reg(TempReg1, (int16_t)Opcode.immediate);
|
|
}
|
|
}
|
|
if (g_System->bUseTlb())
|
|
{
|
|
TempReg2 = Map_TempReg(x86_Any, -1, false);
|
|
MoveX86RegToX86Reg(TempReg1, TempReg2);
|
|
ShiftRightUnsignImmed(TempReg2, 12);
|
|
MoveVariableDispToX86Reg(m_TLB_WriteMap, "m_TLB_WriteMap", TempReg2, TempReg2, 4);
|
|
CompileWriteTLBMiss(TempReg1, TempReg2);
|
|
|
|
TempReg3 = Map_TempReg(x86_Any, -1, false);
|
|
sprintf(Name, "_FPR_D[%d]", Opcode.ft);
|
|
MoveVariableToX86reg((uint8_t *)&_FPR_D[Opcode.ft], Name, TempReg3);
|
|
AddConstToX86Reg(TempReg3, 4);
|
|
MoveX86PointerToX86reg(TempReg3, TempReg3);
|
|
MoveX86regToX86regPointer(TempReg3, TempReg1, TempReg2);
|
|
AddConstToX86Reg(TempReg1, 4);
|
|
|
|
sprintf(Name, "_FPR_D[%d]", Opcode.ft);
|
|
MoveVariableToX86reg((uint8_t *)&_FPR_D[Opcode.ft], Name, TempReg3);
|
|
MoveX86PointerToX86reg(TempReg3, TempReg3);
|
|
MoveX86regToX86regPointer(TempReg3, TempReg1, TempReg2);
|
|
}
|
|
else
|
|
{
|
|
AndConstToX86Reg(TempReg1, 0x1FFFFFFF);
|
|
TempReg3 = Map_TempReg(x86_Any, -1, false);
|
|
sprintf(Name, "_FPR_D[%d]", Opcode.ft);
|
|
MoveVariableToX86reg((uint8_t *)&_FPR_D[Opcode.ft], Name, TempReg3);
|
|
AddConstToX86Reg(TempReg3, 4);
|
|
MoveX86PointerToX86reg(TempReg3, TempReg3);
|
|
MoveX86regToN64Mem(TempReg3, TempReg1);
|
|
sprintf(Name, "_FPR_D[%d]", Opcode.ft);
|
|
MoveVariableToX86reg((uint8_t *)&_FPR_D[Opcode.ft], Name, TempReg3);
|
|
MoveX86PointerToX86reg(TempReg3, TempReg3);
|
|
MoveX86regToN64MemDisp(TempReg3, TempReg1, 4);
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SDL()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (Opcode.base != 0)
|
|
{
|
|
UnMap_GPR(Opcode.base, true);
|
|
}
|
|
|
|
if (Opcode.rt != 0)
|
|
{
|
|
UnMap_GPR(Opcode.rt, true);
|
|
}
|
|
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToVariable(Opcode.Hex, &R4300iOp::m_Opcode.Hex, "R4300iOp::m_Opcode.Hex");
|
|
Call_Direct(R4300iOp::SDL, "R4300iOp::SDL");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
}
|
|
|
|
void CMipsMemoryVM::Compile_SDR()
|
|
{
|
|
OPCODE & Opcode = CRecompilerOps::m_Opcode;
|
|
|
|
CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(Opcode.Hex, m_CompilePC));
|
|
|
|
if (Opcode.base != 0)
|
|
{
|
|
UnMap_GPR(Opcode.base, true);
|
|
}
|
|
|
|
if (Opcode.rt != 0)
|
|
{
|
|
UnMap_GPR(Opcode.rt, true);
|
|
}
|
|
|
|
BeforeCallDirect(m_RegWorkingSet);
|
|
MoveConstToVariable(Opcode.Hex, &R4300iOp::m_Opcode.Hex, "R4300iOp::m_Opcode.Hex");
|
|
Call_Direct(R4300iOp::SDR, "R4300iOp::SDR");
|
|
AfterCallDirect(m_RegWorkingSet);
|
|
}
|
|
|
|
LPCTSTR CMipsMemoryVM::LabelName(uint32_t Address) const
|
|
{
|
|
//StringMap::iterator theIterator = m_LabelList.find(Address);
|
|
//if (theIterator != m_LabelList.end())
|
|
//{
|
|
// return (*theIterator).second;
|
|
//}
|
|
|
|
sprintf(m_strLabelName, "0x%08X", Address);
|
|
return m_strLabelName;
|
|
}
|
|
|
|
void CMipsMemoryVM::TLB_Mapped(uint32_t VAddr, uint32_t Len, uint32_t PAddr, bool bReadOnly)
|
|
{
|
|
size_t count, VEnd;
|
|
|
|
VEnd = VAddr + Len;
|
|
for (count = VAddr; count < VEnd; count += 0x1000)
|
|
{
|
|
size_t Index = count >> 12;
|
|
m_TLB_ReadMap[Index] = ((size_t)m_RDRAM + (count - VAddr + PAddr)) - count;
|
|
if (!bReadOnly)
|
|
{
|
|
m_TLB_WriteMap[Index] = ((size_t)m_RDRAM + (count - VAddr + PAddr)) - count;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::TLB_Unmaped(uint32_t Vaddr, uint32_t Len)
|
|
{
|
|
size_t count, End;
|
|
|
|
End = Vaddr + Len;
|
|
for (count = Vaddr; count < End; count += 0x1000)
|
|
{
|
|
size_t Index = count >> 12;
|
|
m_TLB_ReadMap[Index] = NULL;
|
|
m_TLB_WriteMap[Index] = NULL;
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::RdramChanged(CMipsMemoryVM * _this)
|
|
{
|
|
const size_t new_size = g_Settings->LoadDword(Game_RDRamSize);
|
|
const size_t old_size = _this->m_AllocatedRdramSize;
|
|
|
|
if (old_size == new_size)
|
|
{
|
|
return;
|
|
}
|
|
if (old_size > new_size)
|
|
{
|
|
VirtualFree(
|
|
_this->m_RDRAM + new_size,
|
|
old_size - new_size,
|
|
MEM_DECOMMIT
|
|
);
|
|
}
|
|
else
|
|
{
|
|
void * result;
|
|
|
|
result = VirtualAlloc(
|
|
_this->m_RDRAM + old_size,
|
|
new_size - old_size,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE
|
|
);
|
|
if (result == NULL)
|
|
{
|
|
WriteTrace(TraceN64System, TraceError, "failed to allocate extended memory");
|
|
g_Notify->FatalError(GS(MSG_MEM_ALLOC_ERROR));
|
|
}
|
|
}
|
|
|
|
if (new_size > 0xFFFFFFFFul)
|
|
{ // should be unreachable because: size_t new_size = g_Settings->(uint32_t)
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
} // ...However, FFFFFFFF also is a limit to RCP addressing, so we care.
|
|
_this->m_AllocatedRdramSize = (uint32_t)new_size;
|
|
}
|
|
|
|
void CMipsMemoryVM::ChangeSpStatus()
|
|
{
|
|
if ((RegModValue & SP_CLR_HALT) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_HALT;
|
|
}
|
|
if ((RegModValue & SP_SET_HALT) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_HALT;
|
|
}
|
|
if ((RegModValue & SP_CLR_BROKE) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_BROKE;
|
|
}
|
|
if ((RegModValue & SP_CLR_INTR) != 0)
|
|
{
|
|
g_Reg->MI_INTR_REG &= ~MI_INTR_SP;
|
|
g_Reg->m_RspIntrReg &= ~MI_INTR_SP;
|
|
g_Reg->CheckInterrupts();
|
|
}
|
|
if ((RegModValue & SP_SET_INTR) != 0 && bHaveDebugger())
|
|
{
|
|
g_Notify->DisplayError(L"SP_SET_INTR");
|
|
}
|
|
if ((RegModValue & SP_CLR_SSTEP) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SSTEP;
|
|
}
|
|
if ((RegModValue & SP_SET_SSTEP) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SSTEP;
|
|
}
|
|
if ((RegModValue & SP_CLR_INTR_BREAK) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_INTR_BREAK;
|
|
}
|
|
if ((RegModValue & SP_SET_INTR_BREAK) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_INTR_BREAK;
|
|
}
|
|
if ((RegModValue & SP_CLR_SIG0) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG0;
|
|
}
|
|
if ((RegModValue & SP_SET_SIG0) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG0;
|
|
}
|
|
if ((RegModValue & SP_CLR_SIG1) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG1;
|
|
}
|
|
if ((RegModValue & SP_SET_SIG1) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG1;
|
|
}
|
|
if ((RegModValue & SP_CLR_SIG2) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG2;
|
|
}
|
|
if ((RegModValue & SP_SET_SIG2) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG2;
|
|
}
|
|
if ((RegModValue & SP_CLR_SIG3) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG3;
|
|
}
|
|
if ((RegModValue & SP_SET_SIG3) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG3;
|
|
}
|
|
if ((RegModValue & SP_CLR_SIG4) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG4;
|
|
}
|
|
if ((RegModValue & SP_SET_SIG4) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG4;
|
|
}
|
|
if ((RegModValue & SP_CLR_SIG5) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG5;
|
|
}
|
|
if ((RegModValue & SP_SET_SIG5) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG5;
|
|
}
|
|
if ((RegModValue & SP_CLR_SIG6) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG6;
|
|
}
|
|
if ((RegModValue & SP_SET_SIG6) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG6;
|
|
}
|
|
if ((RegModValue & SP_CLR_SIG7) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG &= ~SP_STATUS_SIG7;
|
|
}
|
|
if ((RegModValue & SP_SET_SIG7) != 0)
|
|
{
|
|
g_Reg->SP_STATUS_REG |= SP_STATUS_SIG7;
|
|
}
|
|
|
|
if ((RegModValue & SP_SET_SIG0) != 0 && g_System->RspAudioSignal())
|
|
{
|
|
g_Reg->MI_INTR_REG |= MI_INTR_SP;
|
|
g_Reg->CheckInterrupts();
|
|
}
|
|
//if (*( uint32_t *)(DMEM + 0xFC0) == 1)
|
|
//{
|
|
// ChangeTimer(RspTimer,0x40000);
|
|
//}
|
|
//else
|
|
//{
|
|
try
|
|
{
|
|
g_System->RunRSP();
|
|
}
|
|
catch (...)
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
//}
|
|
}
|
|
|
|
void CMipsMemoryVM::ChangeMiIntrMask()
|
|
{
|
|
if ((RegModValue & MI_INTR_MASK_CLR_SP) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG &= ~MI_INTR_MASK_SP;
|
|
}
|
|
if ((RegModValue & MI_INTR_MASK_SET_SP) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG |= MI_INTR_MASK_SP;
|
|
}
|
|
if ((RegModValue & MI_INTR_MASK_CLR_SI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG &= ~MI_INTR_MASK_SI;
|
|
}
|
|
if ((RegModValue & MI_INTR_MASK_SET_SI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG |= MI_INTR_MASK_SI;
|
|
}
|
|
if ((RegModValue & MI_INTR_MASK_CLR_AI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG &= ~MI_INTR_MASK_AI;
|
|
}
|
|
if ((RegModValue & MI_INTR_MASK_SET_AI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG |= MI_INTR_MASK_AI;
|
|
}
|
|
if ((RegModValue & MI_INTR_MASK_CLR_VI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG &= ~MI_INTR_MASK_VI;
|
|
}
|
|
if ((RegModValue & MI_INTR_MASK_SET_VI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG |= MI_INTR_MASK_VI;
|
|
}
|
|
if ((RegModValue & MI_INTR_MASK_CLR_PI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG &= ~MI_INTR_MASK_PI;
|
|
}
|
|
if ((RegModValue & MI_INTR_MASK_SET_PI) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG |= MI_INTR_MASK_PI;
|
|
}
|
|
if ((RegModValue & MI_INTR_MASK_CLR_DP) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG &= ~MI_INTR_MASK_DP;
|
|
}
|
|
if ((RegModValue & MI_INTR_MASK_SET_DP) != 0)
|
|
{
|
|
g_Reg->MI_INTR_MASK_REG |= MI_INTR_MASK_DP;
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Load32RDRAMRegisters(void)
|
|
{
|
|
switch (m_MemLookupAddress & 0x1FFFFFFF)
|
|
{
|
|
case 0x03F00000: m_MemLookupValue.UW[0] = g_Reg->RDRAM_CONFIG_REG; break;
|
|
case 0x03F00004: m_MemLookupValue.UW[0] = g_Reg->RDRAM_DEVICE_ID_REG; break;
|
|
case 0x03F00008: m_MemLookupValue.UW[0] = g_Reg->RDRAM_DELAY_REG; break;
|
|
case 0x03F0000C: m_MemLookupValue.UW[0] = g_Reg->RDRAM_MODE_REG; break;
|
|
case 0x03F00010: m_MemLookupValue.UW[0] = g_Reg->RDRAM_REF_INTERVAL_REG; break;
|
|
case 0x03F00014: m_MemLookupValue.UW[0] = g_Reg->RDRAM_REF_ROW_REG; break;
|
|
case 0x03F00018: m_MemLookupValue.UW[0] = g_Reg->RDRAM_RAS_INTERVAL_REG; break;
|
|
case 0x03F0001C: m_MemLookupValue.UW[0] = g_Reg->RDRAM_MIN_INTERVAL_REG; break;
|
|
case 0x03F00020: m_MemLookupValue.UW[0] = g_Reg->RDRAM_ADDR_SELECT_REG; break;
|
|
case 0x03F00024: m_MemLookupValue.UW[0] = g_Reg->RDRAM_DEVICE_MANUF_REG; break;
|
|
default:
|
|
m_MemLookupValue.UW[0] = 0;
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
}
|
|
m_MemLookupValid = true;
|
|
}
|
|
|
|
void CMipsMemoryVM::Load32SPRegisters(void)
|
|
{
|
|
switch (m_MemLookupAddress & 0x1FFFFFFF)
|
|
{
|
|
case 0x04040010: m_MemLookupValue.UW[0] = g_Reg->SP_STATUS_REG; break;
|
|
case 0x04040014: m_MemLookupValue.UW[0] = g_Reg->SP_DMA_FULL_REG; break;
|
|
case 0x04040018: m_MemLookupValue.UW[0] = g_Reg->SP_DMA_BUSY_REG; break;
|
|
case 0x0404001C:
|
|
m_MemLookupValue.UW[0] = g_Reg->SP_SEMAPHORE_REG;
|
|
g_Reg->SP_SEMAPHORE_REG = 1;
|
|
break;
|
|
case 0x04080000: m_MemLookupValue.UW[0] = g_Reg->SP_PC_REG; break;
|
|
default:
|
|
m_MemLookupValue.UW[0] = 0;
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Load32DPCommand(void)
|
|
{
|
|
switch (m_MemLookupAddress & 0x1FFFFFFF)
|
|
{
|
|
case 0x0410000C: m_MemLookupValue.UW[0] = g_Reg->DPC_STATUS_REG; break;
|
|
case 0x04100010: m_MemLookupValue.UW[0] = g_Reg->DPC_CLOCK_REG; break;
|
|
case 0x04100014: m_MemLookupValue.UW[0] = g_Reg->DPC_BUFBUSY_REG; break;
|
|
case 0x04100018: m_MemLookupValue.UW[0] = g_Reg->DPC_PIPEBUSY_REG; break;
|
|
case 0x0410001C: m_MemLookupValue.UW[0] = g_Reg->DPC_TMEM_REG; break;
|
|
default:
|
|
m_MemLookupValue.UW[0] = 0;
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Load32MIPSInterface(void)
|
|
{
|
|
switch (m_MemLookupAddress & 0x1FFFFFFF)
|
|
{
|
|
case 0x04300000: m_MemLookupValue.UW[0] = g_Reg->MI_MODE_REG; break;
|
|
case 0x04300004: m_MemLookupValue.UW[0] = g_Reg->MI_VERSION_REG; break;
|
|
case 0x04300008: m_MemLookupValue.UW[0] = g_Reg->MI_INTR_REG; break;
|
|
case 0x0430000C: m_MemLookupValue.UW[0] = g_Reg->MI_INTR_MASK_REG; break;
|
|
default:
|
|
m_MemLookupValue.UW[0] = 0;
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Load32VideoInterface(void)
|
|
{
|
|
switch (m_MemLookupAddress & 0x1FFFFFFF)
|
|
{
|
|
case 0x04400000: m_MemLookupValue.UW[0] = g_Reg->VI_STATUS_REG; break;
|
|
case 0x04400004: m_MemLookupValue.UW[0] = g_Reg->VI_ORIGIN_REG; break;
|
|
case 0x04400008: m_MemLookupValue.UW[0] = g_Reg->VI_WIDTH_REG; break;
|
|
case 0x0440000C: m_MemLookupValue.UW[0] = g_Reg->VI_INTR_REG; break;
|
|
case 0x04400010:
|
|
g_MMU->UpdateHalfLine();
|
|
m_MemLookupValue.UW[0] = g_MMU->m_HalfLine;
|
|
break;
|
|
case 0x04400014: m_MemLookupValue.UW[0] = g_Reg->VI_BURST_REG; break;
|
|
case 0x04400018: m_MemLookupValue.UW[0] = g_Reg->VI_V_SYNC_REG; break;
|
|
case 0x0440001C: m_MemLookupValue.UW[0] = g_Reg->VI_H_SYNC_REG; break;
|
|
case 0x04400020: m_MemLookupValue.UW[0] = g_Reg->VI_LEAP_REG; break;
|
|
case 0x04400024: m_MemLookupValue.UW[0] = g_Reg->VI_H_START_REG; break;
|
|
case 0x04400028: m_MemLookupValue.UW[0] = g_Reg->VI_V_START_REG; break;
|
|
case 0x0440002C: m_MemLookupValue.UW[0] = g_Reg->VI_V_BURST_REG; break;
|
|
case 0x04400030: m_MemLookupValue.UW[0] = g_Reg->VI_X_SCALE_REG; break;
|
|
case 0x04400034: m_MemLookupValue.UW[0] = g_Reg->VI_Y_SCALE_REG; break;
|
|
default:
|
|
m_MemLookupValue.UW[0] = 0;
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Load32AudioInterface(void)
|
|
{
|
|
switch (m_MemLookupAddress & 0x1FFFFFFF)
|
|
{
|
|
case 0x04500004:
|
|
if (g_System->bFixedAudio())
|
|
{
|
|
m_MemLookupValue.UW[0] = g_Audio->GetLength();
|
|
}
|
|
else
|
|
{
|
|
if (g_Plugins->Audio()->AiReadLength != NULL)
|
|
{
|
|
m_MemLookupValue.UW[0] = g_Plugins->Audio()->AiReadLength();
|
|
}
|
|
else
|
|
{
|
|
m_MemLookupValue.UW[0] = 0;
|
|
}
|
|
}
|
|
break;
|
|
case 0x0450000C:
|
|
if (g_System->bFixedAudio())
|
|
{
|
|
m_MemLookupValue.UW[0] = g_Audio->GetStatus();
|
|
}
|
|
else
|
|
{
|
|
m_MemLookupValue.UW[0] = g_Reg->AI_STATUS_REG;
|
|
}
|
|
break;
|
|
default:
|
|
m_MemLookupValue.UW[0] = 0;
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Load32PeripheralInterface(void)
|
|
{
|
|
switch (m_MemLookupAddress & 0x1FFFFFFF)
|
|
{
|
|
case 0x04600010: m_MemLookupValue.UW[0] = g_Reg->PI_STATUS_REG; break;
|
|
case 0x04600014: m_MemLookupValue.UW[0] = g_Reg->PI_DOMAIN1_REG; break;
|
|
case 0x04600018: m_MemLookupValue.UW[0] = g_Reg->PI_BSD_DOM1_PWD_REG; break;
|
|
case 0x0460001C: m_MemLookupValue.UW[0] = g_Reg->PI_BSD_DOM1_PGS_REG; break;
|
|
case 0x04600020: m_MemLookupValue.UW[0] = g_Reg->PI_BSD_DOM1_RLS_REG; break;
|
|
case 0x04600024: m_MemLookupValue.UW[0] = g_Reg->PI_DOMAIN2_REG; break;
|
|
case 0x04600028: m_MemLookupValue.UW[0] = g_Reg->PI_BSD_DOM2_PWD_REG; break;
|
|
case 0x0460002C: m_MemLookupValue.UW[0] = g_Reg->PI_BSD_DOM2_PGS_REG; break;
|
|
case 0x04600030: m_MemLookupValue.UW[0] = g_Reg->PI_BSD_DOM2_RLS_REG; break;
|
|
default:
|
|
m_MemLookupValue.UW[0] = 0;
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMipsMemoryVM::Load32RDRAMInterface(void)
|
|
{
|
|
switch (m_MemLookupAddress & 0x1FFFFFFF)
|
|
{
|
|
case 0x04700000: m_MemLookupValue.UW[0] = g_Reg->RI_MODE_REG; break;
|
|
case 0x04700004: m_MemLookupValue.UW[0] = g_Reg->RI_CONFIG_REG; break;
|
|
case 0x04700008: m_MemLookupValue.UW[0] = g_Reg->RI_CURRENT_LOAD_REG; break;
|
|
case 0x0470000C: m_MemLookupValue.UW[0] = g_Reg->RI_SELECT_REG; break;
|
|
case 0x04700010: m_MemLookupValue.UW[0] = g_Reg->RI_REFRESH_REG; break;
|
|
case 0x04700014: m_MemLookupValue.UW[0] = g_Reg->RI_LATENCY_REG; break;
|
|
case 0x04700018: m_MemLookupValue.UW[0] = g_Reg->RI_RERROR_REG; break;
|
|
case 0x0470001C: m_MemLookupValue.UW[0] = g_Reg->RI_WERROR_REG; break;
|
|
default:
|
|
m_MemLookupValue.UW[0] = 0;
|
|
if (bHaveDebugger())
|
|
{
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
}
|
|
}
|
|
} |