Files
ppsspp/Core/MIPS/ARM/RegCache.h
T

171 lines
4.1 KiB
C++

// Copyright (C) 2003 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/
#pragma once
#include "../MIPSAnalyst.h"
#include "ArmEmitter.h"
using namespace ArmGen;
enum FlushMode
{
FLUSH_ALL
};
enum GrabMode
{
M_READ = 1,
M_WRITE = 2,
M_READWRITE = 3,
};
enum Loc {
LOC_IMM,
LOC_REG,
LOC_MEM
};
struct Location
{
Loc loc;
bool IsSimpleReg() const {return loc == LOC_REG;}
ARMReg GetSimpleReg() const {return reg;}
bool IsImm() const { return loc == LOC_IMM; }
void SetImm32(u32 i) {loc = LOC_IMM; imm = i;}
void SetM(void *p) {loc = LOC_MEM; ptr = (u32 *)p;}
void SetReg(ARMReg r) {loc = LOC_REG; reg = r;}
union {
u32 *ptr;
ARMReg reg;
u32 imm;
};
};
struct MIPSCachedReg
{
Location location;
bool away; // value not in source register
};
struct ARMCachedReg
{
int ppcReg;
bool dirty;
bool free;
};
typedef int XReg;
typedef int PReg;
#define NUMARMREGS 15
class RegCache
{
private:
bool locks[32];
bool saved_locks[32];
bool saved_xlocks[NUMARMREGS];
protected:
bool xlocks[NUMARMREGS];
MIPSCachedReg regs[32];
ARMCachedReg xregs[NUMARMREGS];
MIPSCachedReg saved_regs[32];
ARMCachedReg saved_xregs[NUMARMREGS];
virtual const int *GetAllocationOrder(int &count) = 0;
ARMXEmitter *emit;
public:
MIPSState *mips;
RegCache();
virtual ~RegCache() {}
virtual void Start(MIPSState *mips, MIPSAnalyst::AnalysisResults &stats) = 0;
void DiscardRegContentsIfCached(int preg);
void SetEmitter(ARMXEmitter *emitter) {emit = emitter;}
void FlushR(ARMReg reg);
void FlushR(ARMReg reg, ARMReg reg2) {FlushR(reg); FlushR(reg2);}
void FlushLockX(ARMReg reg) {
FlushR(reg);
LockX(reg);
}
void FlushLockX(ARMReg reg1, ARMReg reg2) {
FlushR(reg1); FlushR(reg2);
LockX(reg1); LockX(reg2);
}
virtual void Flush(FlushMode mode);
// virtual void Flush(PPCAnalyst::CodeOp *op) {Flush(FLUSH_ALL);}
int SanityCheck() const;
void KillImmediate(int preg, bool doLoad, bool makeDirty);
//TODO - instead of doload, use "read", "write"
//read only will not set dirty flag
virtual void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true) = 0;
virtual void StoreFromRegister(int preg) = 0;
const Location &R(int preg) const {return regs[preg].location;}
ARMReg RX(int preg) const
{
if (regs[preg].away && regs[preg].location.IsSimpleReg())
return regs[preg].location.GetSimpleReg();
PanicAlert("Not so simple - %i", preg);
return (ARMReg)-1;
}
virtual Location GetDefaultLocation(int reg) const = 0;
// Register locking. A locked registers will not be spilled when trying to find a new free register.
void Lock(int p1, int p2=0xff, int p3=0xff, int p4=0xff);
void LockX(int x1, int x2=0xff, int x3=0xff, int x4=0xff);
void UnlockAll();
void UnlockAllX();
bool IsFreeX(int xreg) const;
ARMReg GetFreeXReg();
void SaveState();
void LoadState();
};
class GPRRegCache : public RegCache
{
public:
void Start(MIPSState *mips, MIPSAnalyst::AnalysisResults &stats);
void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true);
void StoreFromRegister(int preg);
Location GetDefaultLocation(int reg) const;
const int *GetAllocationOrder(int &count);
void SetImmediate32(int preg, u32 immValue);
};
class FPURegCache : public RegCache
{
public:
void Start(MIPSState *mips, MIPSAnalyst::AnalysisResults &stats);
void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true);
void StoreFromRegister(int preg);
const int *GetAllocationOrder(int &count);
Location GetDefaultLocation(int reg) const;
};