Displaying: CNoeR3000A.h
#pragma once
#if !defined(_CNOER3000A_H_)
#define _CNOER3000A_H_
#define NOER3000A_DEBUGGER() 0
#include "NoesisLocalAPI.h"
#if NOER3000A_DEBUGGER()
#include "CNoeDebugger.h"
#endif
struct SR3000ADefaultOpHandler;
class CNoeR3000A
{
friend class CNoeR3000AOps;
public:
static const uint32_t skInstructionSize = 4;
static const uint32_t skInstructionOffsetOp = 26;
static const uint32_t skInstructionOffsetOp2 = 0;
static const uint32_t skInstructionOpBits = 6;
static const uint32_t skInstructionOpMaxCount = (1 << skInstructionOpBits);
static const uint32_t skInstructionOffsetRegSA = 6;
static const uint32_t skInstructionOffsetRegRD = 11;
static const uint32_t skInstructionOffsetRegRT = 16;
static const uint32_t skInstructionOffsetRegRS = 21;
static const uint32_t skInstructionRegBits = 5;
static const uint32_t skInstructionRegMaxCount = (1 << skInstructionRegBits);
static const uint32_t skInstructionJumpAddressBits = 26;
static const uint32_t skInstructionJumpAddressPCMask = 0xF0000000;
static const uint32_t skMaximumOpStringLength = 1024;
static const uint32_t skMaximumOpNameLength = 8;
enum EGPR
{
kGPR_Zero = 0, kGPR_AT, kGPR_V0, kGPR_V1, kGPR_A0, kGPR_A1, kGPR_A2, kGPR_A3, kGPR_T0, kGPR_T1, kGPR_T2, kGPR_T3, kGPR_T4, kGPR_T5, kGPR_T6, kGPR_T7, kGPR_S0, kGPR_S1, kGPR_S2, kGPR_S3, kGPR_S4, kGPR_S5, kGPR_S6, kGPR_S7, kGPR_T8, kGPR_T9, kGPR_K0, kGPR_K1, kGPR_GP, kGPR_SP, kGPR_FP, kGPR_RA, kGPR_Count
};
enum EIR
{
kIR_Lo = 0,
kIR_Hi,
kIR_PC,
kIR_Op,
kIR_Count
};
enum EC0R
{
kC0R_Index = 0,
kC0R_Random,
kC0R_EntryLo,
kC0R_C3,
kC0R_Context,
kC0R_C5,
kC0R_C6,
kC0R_C7,
kC0R_VAddr,
kC0R_C9,
kC0R_EntryHi,
kC0R_C11,
kC0R_Status,
kC0R_Cause,
kC0R_EPC,
kC0R_C15,
kC0R_C16,
kC0R_C17,
kC0R_C18,
kC0R_C19,
kC0R_C20,
kC0R_C21,
kC0R_C22,
kC0R_C23,
kC0R_C24,
kC0R_C25,
kC0R_C26,
kC0R_C27,
kC0R_C28,
kC0R_C29,
kC0R_C30,
kC0R_C31,
kC0R_Count
};
enum EAccessType
{
kAT_Default = 0,
kAT_External
};
typedef uint8_t (*TReadMemory8)(CNoeR3000A *pCpu, const uint32_t addr, const EAccessType accessType);
typedef uint16_t (*TReadMemory16)(CNoeR3000A *pCpu, const uint32_t addr, const EAccessType accessType);
typedef uint32_t (*TReadMemory32)(CNoeR3000A *pCpu, const uint32_t addr, const EAccessType accessType);
typedef uint32_t (*TReadInstruction)(CNoeR3000A *pCpu, const uint32_t addr, const EAccessType accessType);
typedef void (*TWriteMemory8)(CNoeR3000A *pCpu, const uint32_t addr, const uint8_t memVal, const EAccessType accessType);
typedef void (*TWriteMemory16)(CNoeR3000A *pCpu, const uint32_t addr, const uint16_t memVal, const EAccessType accessType);
typedef void (*TWriteMemory32)(CNoeR3000A *pCpu, const uint32_t addr, const uint32_t memVal, const EAccessType accessType);
typedef void (*TWriteCOP0Reg)(CNoeR3000A *pCpu, const EC0R cop0Reg, const uint32_t regVal);
typedef uint32_t (*TDelayLoadForOp)(CNoeR3000A *pCpu, const uint32_t opVal);
typedef void (*TOnCyclesConsumed)(CNoeR3000A *pCpu, const uint64_t cycleCount);
typedef void (*TOnOpExecuted)(CNoeR3000A *pCpu, const uint32_t opVal);
typedef void (*TOnBranch)(CNoeR3000A *pCpu, const uint32_t addr); typedef bool (*TOpHandlerFunction)(CNoeR3000A *pCpu, const uint32_t opVal);
typedef bool (*TOpStringFormatFunction)(char *pStringOut, CNoeR3000A *pCpu, const uint32_t opVal);
struct SOpHandler
{
explicit SOpHandler(const uint32_t opVal, const uint32_t opMask, TOpHandlerFunction pOpHandler, TOpStringFormatFunction pOpStringFormat)
: mOpVal(opVal)
, mOpMask(opMask)
, mpOpHandler(pOpHandler)
, mpOpStringFormat(pOpStringFormat)
{
}
uint32_t mOpVal;
uint32_t mOpMask;
TOpHandlerFunction mpOpHandler;
TOpStringFormatFunction mpOpStringFormat;
};
CNoeR3000A();
void ExecuteCycles(const uint64_t cycleCount);
void SetDefaults();
void Reset();
void ConsumeCycles(const int64_t cycleCount);
void CheckDelayedOperations();
uint32_t *GPR() { return mpGPR; }
uint32_t *IR() { return mpIR; }
uint32_t *C0R() { return mpC0R; }
void AddOpHandler(const SOpHandler &opHandler); void SetReadMemory8(TReadMemory8 pReadMemory8);
void SetReadMemory16(TReadMemory16 pReadMemory16);
void SetReadMemory32(TReadMemory32 pReadMemory32);
void SetReadInstruction(TReadInstruction pReadInstruction);
void SetWriteMemory8(TWriteMemory8 pWriteMemory8);
void SetWriteMemory16(TWriteMemory16 pWriteMemory16);
void SetWriteMemory32(TWriteMemory32 pWriteMemory32);
void SetWriteCOP0Reg(TWriteCOP0Reg pWriteCOP0Reg);
void SetDelayLoadForOp(TDelayLoadForOp pDelayLoadForOp);
void SetOnCyclesConsumed(TOnCyclesConsumed pOnCyclesConsumed);
void SetOnOpExecuted(TOnOpExecuted pOnOpExecuted);
void SetOnBranchBegin(TOnBranch pOnBranchBegin);
void SetOnBranchTaken(TOnBranch pOnBranchTaken);
void SetGPRMemory(uint32_t *pGPR); void SetIRMemory(uint32_t *pIR); void SetC0RMemory(uint32_t *pC0R);
uint8_t ReadMemory8(const uint32_t addr, const EAccessType accessType = kAT_Default);
uint16_t ReadMemory16(const uint32_t addr, const EAccessType accessType = kAT_Default);
uint32_t ReadMemory32(const uint32_t addr, const EAccessType accessType = kAT_Default);
uint32_t ReadInstruction(const uint32_t addr, const EAccessType accessType = kAT_Default);
void WriteMemory8(const uint32_t addr, const uint8_t memVal, const EAccessType accessType = kAT_Default);
void WriteMemory16(const uint32_t addr, const uint16_t memVal, const EAccessType accessType = kAT_Default);
void WriteMemory32(const uint32_t addr, const uint32_t memVal, const EAccessType accessType = kAT_Default);
uint64_t GetCyclesPerOp() const { return mCyclesPerOp; }
void SetCyclesPerOp(const uint64_t cyclesPerOp) { mCyclesPerOp = cyclesPerOp; }
uint64_t GetCyclesExecuted() const { return mCyclesExecuted; }
void SetDelayBranchCycles(const uint32_t delayBranchCycles) { mDelayBranchCycles = delayBranchCycles; }
void SetDelayLoadCycles(const uint32_t delayLoadCycles) { mDelayLoadCycles = delayLoadCycles; }
void *GetUserData() const { return mpUserData; }
void SetUserData(void *pUserData) { mpUserData = pUserData; }
static uint32_t GetInstructionOp(const uint32_t opVal) { return (opVal >> skInstructionOffsetOp) & ((1 << skInstructionOpBits) - 1); }
static uint32_t GetInstructionOp2(const uint32_t opVal) { return (opVal >> skInstructionOffsetOp2) & ((1 << skInstructionOpBits) - 1); }
static uint32_t GetInstructionSA(const uint32_t opVal) { return (opVal >> skInstructionOffsetRegSA) & ((1 << skInstructionRegBits) - 1); }
static uint32_t GetInstructionRD(const uint32_t opVal) { return (opVal >> skInstructionOffsetRegRD) & ((1 << skInstructionRegBits) - 1); }
static uint32_t GetInstructionRT(const uint32_t opVal) { return (opVal >> skInstructionOffsetRegRT) & ((1 << skInstructionRegBits) - 1); }
static uint32_t GetInstructionRS(const uint32_t opVal) { return (opVal >> skInstructionOffsetRegRS) & ((1 << skInstructionRegBits) - 1); }
static uint32_t GetInstructionJumpAddress(const uint32_t opVal) { return (opVal & ((1 << skInstructionJumpAddressBits) - 1)) << 2; }
static const char *GetGPRName(const EGPR gprIndex);
void FormatOpString(char *pStringOut, const uint32_t opVal, const uint32_t opAddr);
#if NOER3000A_DEBUGGER()
CNoeDebugger &Debugger() { return mDebugger; }
#endif
private:
void ReadAndExecuteOp();
void ExecuteOp(const uint32_t opVal, const uint32_t opAddr);
void TakeBranch(const uint32_t addr);
void LoadGPR(const EGPR gprIndex, const uint32_t opVal, const uint32_t regVal); static SR3000ADefaultOpHandler mspDefaultOpHandlers[CNoeR3000A::skInstructionOpMaxCount];
static SR3000ADefaultOpHandler mspTable2OpHandlers[CNoeR3000A::skInstructionOpMaxCount];
static SR3000ADefaultOpHandler mspCBranchOpHandlers[CNoeR3000A::skInstructionRegMaxCount];
static SR3000ADefaultOpHandler mspCOP0OpHandlers[CNoeR3000A::skInstructionRegMaxCount];
typedef std::vector<SOpHandler> TOpHandlerList; TOpHandlerList mOpHandlers[skInstructionOpMaxCount];
TReadMemory8 mpReadMemory8;
TReadMemory16 mpReadMemory16;
TReadMemory32 mpReadMemory32;
TReadInstruction mpReadInstruction;
TWriteMemory8 mpWriteMemory8;
TWriteMemory16 mpWriteMemory16;
TWriteMemory32 mpWriteMemory32;
TWriteCOP0Reg mpWriteCOP0Reg;
TDelayLoadForOp mpDelayLoadForOp;
TOnCyclesConsumed mpOnCyclesConsumed;
TOnOpExecuted mpOnOpExecuted;
TOnBranch mpOnBranchBegin;
TOnBranch mpOnBranchTaken;
uint32_t *mpGPR;
uint32_t *mpIR;
uint32_t *mpC0R;
uint64_t mCyclesPerOp;
uint64_t mCyclesExecuted;
struct SDelayBranch
{
SDelayBranch()
: mAddr(0)
, mTargetCycle(0)
{
}
uint32_t mAddr;
uint64_t mTargetCycle;
};
SDelayBranch mDelayBranch;
struct SDelayGPRLoad
{
SDelayGPRLoad()
: mRegVal(0)
, mTargetCycle(0)
{
}
uint32_t mRegVal;
uint64_t mTargetCycle;
};
SDelayGPRLoad mDelayGPRLoad[kGPR_Count];
uint64_t mDelayGPRLoadMask;
uint32_t mDelayBranchCycles;
uint32_t mDelayLoadCycles;
void *mpUserData;
#if NOER3000A_DEBUGGER()
CNoeDebugger mDebugger;
#endif
uint32_t mDefaultGPR[kGPR_Count];
uint32_t mDefaultIR[kIR_Count];
uint32_t mDefaultC0R[kC0R_Count];
};
#endif //_CNOER3000A_H_