Lib65816/include/Cpu65816.hpp

207 lines
6.7 KiB
C++

/*
* This file is part of the 65816 Emulator Library.
* Copyright (c) 2018 Francesco Rigoni.
*
* https://github.com/FrancescoRigoni/Lib65816
*
* 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 3.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CPU_65816__
#define __CPU_65816__
#include <stdint.h>
#include "SystemBus.hpp"
#include "Interrupt.hpp"
#include "Addressing.hpp"
#include "Stack.hpp"
#include "CpuStatus.hpp"
#include "OpCode.hpp"
#include "Log.hpp"
#include "Binary.hpp"
#include "BuildConfig.hpp"
// Macro used by OpCode methods when an unrecognized OpCode is being executed.
#define LOG_UNEXPECTED_OPCODE(opCode) Log::err(LOG_TAG).str("Unexpected OpCode: ").str(opCode.getName()).show();
class Cpu65816Debugger;
class Cpu65816 {
friend class Cpu65816Debugger;
public:
Cpu65816(SystemBus &, EmulationModeInterrupts *, NativeModeInterrupts *);
void setRESPin(bool);
void setRDYPin(bool);
void setIRQPin(bool value) { mPins.IRQ = value;}
void setNMIPin(bool value) { mPins.NMI = value;}
void setABORTPin(bool value) { mPins.ABORT = value;}
// Temporary
bool executeNextInstruction();
void setXL(uint8_t x);
void setYL(uint8_t y);
void setX(uint16_t x);
void setY(uint16_t y);
void setA(uint16_t a);
uint16_t getA();
Address getProgramAddress();
void setProgramAddress(const Address &);
Stack *getStack();
CpuStatus *getCpuStatus();
private:
SystemBus &mSystemBus;
EmulationModeInterrupts *mEmulationInterrupts;
NativeModeInterrupts *mNativeInterrupts;
// Accumulator register
uint16_t mA = 0;
// X index register
uint16_t mX = 0;
// Y index register
uint16_t mY = 0;
// Status register
CpuStatus mCpuStatus;
// Data bank register
uint8_t mDB = 0;
// Direct page register
uint16_t mD = 0;
struct {
// Reset to true means low power mode (do nothing) (should jump indirect via 0x00FFFC)
bool RES = true;
// Ready to false means CPU is waiting for an NMI/IRQ/ABORT/RESET
bool RDY = false;
// nmi true execute nmi vector (0x00FFEA)
bool NMI = false;
// irq true exucute irq vector (0x00FFEE)
bool IRQ = false;
// abort true execute abort vector (0x00FFE8)
bool ABORT = false;
} mPins;
Stack mStack;
// Address of the current OpCode
Address mProgramAddress {0x00, 0x0000};
// Total number of cycles
uint64_t mTotalCyclesCounter = 0;
bool accumulatorIs8BitWide();
bool accumulatorIs16BitWide();
bool indexIs8BitWide();
bool indexIs16BitWide();
uint16_t indexWithXRegister();
uint16_t indexWithYRegister();
Address getAddressOfOpCodeData(OpCode &);
bool opCodeAddressingCrossesPageBoundary(OpCode &);
void addToCycles(int);
void subtractFromCycles(int);
void addToProgramAddress(int);
void addToProgramAddressAndCycles(int, int);
// OpCode Table.
static OpCode OP_CODE_TABLE[];
// OpCodes handling routines.
// Implementations for these methods can be found in the corresponding OpCode_XXX.cpp file.
void executeORA(OpCode &);
void executeORA8Bit(OpCode &);
void executeORA16Bit(OpCode &);
void executeStack(OpCode &);
void executeStatusReg(OpCode &);
void executeMemoryROL(OpCode &);
void executeAccumulatorROL(OpCode &);
void executeROL(OpCode &);
void executeMemoryROR(OpCode &);
void executeAccumulatorROR(OpCode &);
void executeROR(OpCode &);
void executeInterrupt(OpCode &);
void executeJumpReturn(OpCode &);
void execute8BitSBC(OpCode &);
void execute16BitSBC(OpCode &);
void execute8BitBCDSBC(OpCode &);
void execute16BitBCDSBC(OpCode &);
void executeSBC(OpCode &);
void execute8BitADC(OpCode &);
void execute16BitADC(OpCode &);
void execute8BitBCDADC(OpCode &);
void execute16BitBCDADC(OpCode &);
void executeADC(OpCode &);
void executeSTA(OpCode &);
void executeSTX(OpCode &);
void executeSTY(OpCode &);
void executeSTZ(OpCode &);
void executeTransfer(OpCode &);
void executeMemoryASL(OpCode &);
void executeAccumulatorASL(OpCode &);
void executeASL(OpCode &);
void executeAND8Bit(OpCode &);
void executeAND16Bit(OpCode &);
void executeAND(OpCode &);
void executeLDA8Bit(OpCode &);
void executeLDA16Bit(OpCode &);
void executeLDA(OpCode &);
void executeLDX8Bit(OpCode &);
void executeLDX16Bit(OpCode &);
void executeLDX(OpCode &);
void executeLDY8Bit(OpCode &);
void executeLDY16Bit(OpCode &);
void executeLDY(OpCode &);
void executeEOR8Bit(OpCode &);
void executeEOR16Bit(OpCode &);
void executeEOR(OpCode &);
int executeBranchShortOnCondition(bool, OpCode &);
int executeBranchLongOnCondition(bool, OpCode &);
void executeBranch(OpCode &);
void execute8BitCMP(OpCode &);
void execute16BitCMP(OpCode &);
void executeCMP(OpCode &);
void execute8BitDecInMemory(OpCode &);
void execute16BitDecInMemory(OpCode &);
void execute8BitIncInMemory(OpCode &);
void execute16BitIncInMemory(OpCode &);
void executeINCDEC(OpCode &);
void execute8BitCPX(OpCode &);
void execute16BitCPX(OpCode &);
void execute8BitCPY(OpCode &);
void execute16BitCPY(OpCode &);
void executeCPXCPY(OpCode &);
void execute8BitTSB(OpCode &);
void execute16BitTSB(OpCode &);
void execute8BitTRB(OpCode &);
void execute16BitTRB(OpCode &);
void executeTSBTRB(OpCode &);
void execute8BitBIT(OpCode &);
void execute16BitBIT(OpCode &);
void executeBIT(OpCode &);
void executeMemoryLSR(OpCode &);
void executeAccumulatorLSR(OpCode &);
void executeLSR(OpCode &);
void executeMisc(OpCode &);
void reset();
};
#endif