diff options
| author | hrydgard <hrydgard@gmail.com> | 2008-08-30 13:06:17 +0000 |
|---|---|---|
| committer | hrydgard <hrydgard@gmail.com> | 2008-08-30 13:06:17 +0000 |
| commit | 5ac5a0498222cc26b5437cc460745239291d5229 (patch) | |
| tree | 9dde195029211010c2a823084b00ad1ce455932a /Source/Core | |
| parent | ff0a613427de1533edf2f5b3347a44fd9f242998 (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.cpp | 4 | ||||
| -rw-r--r-- | Source/Core/Core/Src/HW/HW.cpp | 1 | ||||
| -rw-r--r-- | Source/Core/Core/Src/HW/Memmap.cpp | 11 | ||||
| -rw-r--r-- | Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp | 5 | ||||
| -rw-r--r-- | Source/Core/Core/Src/PowerPC/Jit64/Jit.h | 1 | ||||
| -rw-r--r-- | Source/Core/Core/Src/PowerPC/Jit64/JitCache.cpp | 14 | ||||
| -rw-r--r-- | Source/Core/Core/Src/PowerPC/Jit64/JitCache.h | 16 | ||||
| -rw-r--r-- | Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp | 6 | ||||
| -rw-r--r-- | Source/Core/Core/Src/PowerPC/Jit64/Jit_SystemRegisters.cpp | 13 | ||||
| -rw-r--r-- | Source/Core/Core/Src/State.cpp | 25 | ||||
| -rw-r--r-- | Source/Core/Core/Src/State.h | 20 | ||||
| -rw-r--r-- | Source/Core/DolphinWX/src/Frame.cpp | 27 |
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"));
|
