summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorhrydgard <hrydgard@gmail.com>2008-08-30 13:06:17 +0000
committerhrydgard <hrydgard@gmail.com>2008-08-30 13:06:17 +0000
commit5ac5a0498222cc26b5437cc460745239291d5229 (patch)
tree9dde195029211010c2a823084b00ad1ce455932a /Source/Core
parentff0a613427de1533edf2f5b3347a44fd9f242998 (diff)
More state save code, "proper" fix for the quantizer problem
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@382 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/Core.cpp4
-rw-r--r--Source/Core/Core/Src/HW/HW.cpp1
-rw-r--r--Source/Core/Core/Src/HW/Memmap.cpp11
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp5
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit.h1
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/JitCache.cpp14
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/JitCache.h16
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp6
-rw-r--r--Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp13
-rw-r--r--Source/Core/Core/Src/State.cpp25
-rw-r--r--Source/Core/Core/Src/State.h20
-rw-r--r--Source/Core/DolphinWX/src/Frame.cpp27
12 files changed, 119 insertions, 24 deletions
diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp
index f2ec671444..516ad809c3 100644
--- a/Source/Core/Core/Src/Core.cpp
+++ b/Source/Core/Core/Src/Core.cpp
@@ -413,15 +413,11 @@ EState GetState()
}
void SaveState() {
- CCPU::EnableStepping(true);
State_Save("state.dlp");
- CCPU::EnableStepping(false);
}
void LoadState() {
- CCPU::EnableStepping(true);
State_Load("state.dlp");
- CCPU::EnableStepping(false);
}
const SCoreStartupParameter& GetStartupParameter()
diff --git a/Source/Core/Core/Src/HW/HW.cpp b/Source/Core/Core/Src/HW/HW.cpp
index 3aac2ce66b..a132670db9 100644
--- a/Source/Core/Core/Src/HW/HW.cpp
+++ b/Source/Core/Core/Src/HW/HW.cpp
@@ -89,6 +89,7 @@ namespace HW
void DoState(PointerWrap &p)
{
+ Memory::DoState(p);
PixelEngine::DoState(p);
CommandProcessor::DoState(p);
VideoInterface::DoState(p);
diff --git a/Source/Core/Core/Src/HW/Memmap.cpp b/Source/Core/Core/Src/HW/Memmap.cpp
index 40f98c56e4..1c183f7955 100644
--- a/Source/Core/Core/Src/HW/Memmap.cpp
+++ b/Source/Core/Core/Src/HW/Memmap.cpp
@@ -18,6 +18,7 @@
#include "Common.h"
#include "MemoryUtil.h"
#include "MemArena.h"
+#include "ChunkFile.h"
#include "Memmap.h"
#include "../Core.h"
@@ -143,7 +144,6 @@ template <class T, u8* P> void HWCALL HW_Write_Memory(T _Data, const u32 _Addres
#define AUDIO_START 0x1B
#define GP_START 0x20
-
void InitHWMemFuncs()
{
for (int i = 0; i < NUMHWMEMFUN; i++)
@@ -523,6 +523,15 @@ bool Init()
return true;
}
+void DoState(PointerWrap &p)
+{
+ bool wii = Core::GetStartupParameter().bWii;
+ p.DoArray(m_pRAM, RAM_SIZE);
+ p.DoArray(m_pEFB, EFB_SIZE);
+ p.DoArray(m_pL1Cache, L1_CACHE_SIZE);
+ if (wii)
+ p.DoArray(m_pEXRAM, EXRAM_SIZE);
+}
bool Shutdown()
{
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp
index 6b0e0b5eb6..c94b29e599 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp
@@ -370,6 +370,7 @@ namespace Jit64
js.fifoBytesThisBlock = 0;
js.curBlock = &b;
js.blockSetsQuantizers = false;
+ js.block_flags = 0;
//Analyze the block, collect all instructions it is made of (including inlining,
//if that is enabled), reorder instructions for optimal performance, and join joinable instructions.
@@ -415,7 +416,8 @@ namespace Jit64
js.compilerPC = ops[i].address;
js.op = &ops[i];
js.instructionNumber = i;
- if (i == (int)size - 1) js.isLastInstruction = true;
+ if (i == (int)size - 1)
+ js.isLastInstruction = true;
// const GekkoOpInfo *info = GetOpInfo();
// if (js.isLastInstruction)
@@ -435,6 +437,7 @@ namespace Jit64
}
js.compilerPC += 4;
+ b.flags = js.block_flags;
b.codeSize = (u32)(GetCodePtr() - start);
b.originalSize = js.compilerPC - emaddress;
return normalEntry;
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h
index 83b47d9d61..fda7686941 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h
@@ -48,6 +48,7 @@ namespace Jit64
int blockSize;
int instructionNumber;
int downcountAmount;
+ int block_flags;
bool isLastInstruction;
bool blockSetsQuantizers;
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitCache.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitCache.cpp
index e897e96afa..b4f5f88a9e 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/JitCache.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/JitCache.cpp
@@ -118,6 +118,15 @@ namespace Jit64
SetCodePtr(codeCache);
}
+ void DestroyBlocksWithFlag(BlockFlag death_flag)
+ {
+ for (int i = 0; i < numBlocks; i++) {
+ if (blocks[i].flags & death_flag) {
+ DestroyBlock(i, false);
+ }
+ }
+ }
+
void ResetCache()
{
ShutdownCache();
@@ -338,8 +347,11 @@ namespace Jit64
//for something else, then it's fine.
LOG(MASTER_LOG, "WARNING - ClearCache detected code overwrite @ %08x", blocks[blocknum].originalAddress);
}
- // TODO: Unlink block.
+ // We don't unlink blocks, we just send anyone who tries to run them back to the dispatcher.
+ // Not entirely ideal, but .. pretty good.
+
+ // TODO - make sure that the below stuff really is safe.
u8 *prev_code = GetWritableCodePtr();
// Spurious entrances from previously linked blocks can only come through checkedEntry
SetCodePtr((u8*)b.checkedEntry);
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitCache.h b/Source/Core/Core/Src/PowerPC/Jit64/JitCache.h
index d7382f15ad..ea7c86d8b0 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/JitCache.h
+++ b/Source/Core/Core/Src/PowerPC/Jit64/JitCache.h
@@ -28,6 +28,18 @@ namespace Jit64
//Code pointers are stored separately, they will be accessed much more frequently
+ enum BlockFlag
+ {
+ BLOCK_USE_GQR0 = 0x1,
+ BLOCK_USE_GQR1 = 0x2,
+ BLOCK_USE_GQR2 = 0x4,
+ BLOCK_USE_GQR3 = 0x8,
+ BLOCK_USE_GQR4 = 0x10,
+ BLOCK_USE_GQR5 = 0x20,
+ BLOCK_USE_GQR6 = 0x40,
+ BLOCK_USE_GQR7 = 0x80,
+ };
+
// TODO(ector) - optimize this struct for size
struct JitBlock
{
@@ -42,6 +54,7 @@ namespace Jit64
int runCount; // for profiling.
const u8 *checkedEntry;
bool invalid;
+ int flags;
};
void PrintStats();
@@ -62,6 +75,9 @@ namespace Jit64
u8 **GetCodePointers();
u8 *Jit(u32 emaddress);
+
+ void DestroyBlocksWithFlag(BlockFlag death_flag);
+
void LinkBlocks();
void ClearCache();
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp
index 00ea2d2d80..429f9e3655 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp
@@ -107,6 +107,8 @@ const double GC_ALIGNED16(m_dequantizeTableD[]) =
void psq_st(UGeckoInstruction inst)
{
INSTRUCTION_START;
+ js.block_flags |= BLOCK_USE_GQR0 << inst.I;
+
if (js.blockSetsQuantizers || !Core::GetStartupParameter().bOptimizeQuantizers)
{
Default(inst);
@@ -118,6 +120,7 @@ void psq_st(UGeckoInstruction inst)
Default(inst);
return;
}
+
const UGQR gqr(rSPR(SPR_GQR0 + inst.I));
const EQuantizeType stType = static_cast<EQuantizeType>(gqr.ST_TYPE);
int stScale = gqr.ST_SCALE;
@@ -281,11 +284,14 @@ const u8 GC_ALIGNED16(pbswapShuffleNoop[16]) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
void psq_l(UGeckoInstruction inst)
{
INSTRUCTION_START;
+ js.block_flags |= BLOCK_USE_GQR0 << inst.I;
+
if (js.blockSetsQuantizers || !Core::GetStartupParameter().bOptimizeQuantizers)
{
Default(inst);
return;
}
+
const UGQR gqr(rSPR(SPR_GQR0 + inst.I));
const EQuantizeType ldType = static_cast<EQuantizeType>(gqr.LD_TYPE);
int ldScale = gqr.LD_SCALE;
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp
index 8b3bab2b1a..959fa55cea 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp
@@ -22,6 +22,8 @@
#include "../PowerPC.h"
#include "../PPCTables.h"
#include "x64Emitter.h"
+#include "ABI.h"
+#include "Thunk.h"
#include "Jit.h"
#include "JitCache.h"
@@ -55,7 +57,16 @@ namespace Jit64
case SPR_GQR0 + 7:
js.blockSetsQuantizers = true;
// Prevent recompiler from compiling in old quantizer values.
- // TODO - actually save the set state and use it in following quantizer ops.
+ // If the value changed, destroy all blocks using this quantizer
+ // This will create a little bit of block churn, but hopefully not too bad.
+ {
+ MOV(32, R(EAX), M(&PowerPC::ppcState.spr[iIndex])); // Load old value
+ CMP(32, R(EAX), gpr.R(inst.RD));
+ FixupBranch skip_destroy = J_CC(CC_E, false);
+ int gqr = iIndex - SPR_GQR0;
+ ABI_CallFunctionC(ProtectFunction(&Jit64::DestroyBlocksWithFlag, 1), (u32)BLOCK_USE_GQR0 << gqr);
+ SetJumpTarget(skip_destroy);
+ }
break;
// TODO - break block if quantizers are written to.
default:
diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp
index e27007c9bb..5215c5ea87 100644
--- a/Source/Core/Core/Src/State.cpp
+++ b/Source/Core/Core/Src/State.cpp
@@ -1,11 +1,30 @@
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
#include "Common.h"
#include "State.h"
#include "CoreTiming.h"
#include "HW/HW.h"
#include "PowerPC/PowerPC.h"
+#include "PowerPC/Jit64/JitCache.h"
#include "Plugins/Plugin_Video.h"
+#include "Plugins/Plugin_DSP.h"
#include <string>
@@ -18,11 +37,14 @@ void DoState(PointerWrap &p)
{
PowerPC::DoState(p);
HW::DoState(p);
+ CoreTiming::DoState(p);
PluginVideo::Video_DoState(p.GetPPtr(), p.GetMode());
}
void SaveStateCallback(u64 userdata, int cyclesLate)
{
+ Jit64::ClearCache();
+
u8 *ptr = 0;
PointerWrap p(&ptr, PointerWrap::MODE_MEASURE);
DoState(p);
@@ -39,7 +61,8 @@ void SaveStateCallback(u64 userdata, int cyclesLate)
void LoadStateCallback(u64 userdata, int cyclesLate)
{
- // ChunkFile f(cur_filename.c_str(), ChunkFile::MODE_READ);
+ Jit64::ClearCache();
+
FILE *f = fopen(cur_filename.c_str(), "r");
fseek(f, 0, SEEK_END);
int sz = ftell(f);
diff --git a/Source/Core/Core/Src/State.h b/Source/Core/Core/Src/State.h
index 2fd5fe091a..e2800ff240 100644
--- a/Source/Core/Core/Src/State.h
+++ b/Source/Core/Core/Src/State.h
@@ -1,11 +1,27 @@
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
#ifndef _STATE_H
#define _STATE_H
-// None of these happen instantly - they get scheduled as an event.
-
void State_Init();
void State_Shutdown();
+// These don't happen instantly - they get scheduled as events.
void State_Save(const char *filename);
void State_Load(const char *filename);
diff --git a/Source/Core/DolphinWX/src/Frame.cpp b/Source/Core/DolphinWX/src/Frame.cpp
index ffade630ae..c9b926c58e 100644
--- a/Source/Core/DolphinWX/src/Frame.cpp
+++ b/Source/Core/DolphinWX/src/Frame.cpp
@@ -170,24 +170,25 @@ void CFrame::CreateMenu()
fileMenu->Append(wxID_OPEN, _T("&Open..."));
fileMenu->Append(wxID_REFRESH, _T("&Refresh"));
fileMenu->Append(IDM_BROWSE, _T("&Browse for ISOs..."));
- fileMenu->AppendSeparator();
- m_pMenuItemPlay = new wxMenuItem(fileMenu, IDM_PLAY, _T("&Play"));
- fileMenu->Append(m_pMenuItemPlay);
- m_pMenuItemStop = new wxMenuItem(fileMenu, IDM_STOP, _T("&Stop"));
- fileMenu->Append(m_pMenuItemStop);
-
- fileMenu->AppendSeparator();
- m_pMenuItemLoad = new wxMenuItem(fileMenu, IDM_LOADSTATE, _T("&Load State... (AKA Russian Roulette)"));
- fileMenu->Append(m_pMenuItemLoad);
- m_pMenuItemLoad->Enable(false);
- m_pMenuItemSave = new wxMenuItem(fileMenu, IDM_SAVESTATE, _T("Sa&ve State... (Use at your own risk)"));
- fileMenu->Append(m_pMenuItemSave);
- m_pMenuItemSave->Enable(false);
fileMenu->AppendSeparator();
fileMenu->Append(wxID_EXIT, _T("E&xit"), _T(""));
m_pMenuBar->Append(fileMenu, _T("&File"));
+ // emulation menu
+ wxMenu* emulationMenu = new wxMenu;
+ m_pMenuItemPlay = new wxMenuItem(fileMenu, IDM_PLAY, _T("&Play"));
+ emulationMenu->Append(m_pMenuItemPlay);
+ m_pMenuItemStop = new wxMenuItem(fileMenu, IDM_STOP, _T("&Stop"));
+ emulationMenu->Append(m_pMenuItemStop);
+ emulationMenu->AppendSeparator();
+
+ m_pMenuItemLoad = new wxMenuItem(fileMenu, IDM_LOADSTATE, _T("&Load State"));
+ emulationMenu->Append(m_pMenuItemLoad);
+ m_pMenuItemSave = new wxMenuItem(fileMenu, IDM_SAVESTATE, _T("Sa&ve State"));
+ emulationMenu->Append(m_pMenuItemSave);
+ m_pMenuBar->Append(emulationMenu, _T("&Emulation"));
+
// options menu
wxMenu* pOptionsMenu = new wxMenu;
m_pPluginOptions = new wxMenuItem(pOptionsMenu, IDM_PLUGIN_OPTIONS, _T("&Select plugins"));