From 876b78a5c9ca3c75fc2f8a5a8fb5ce688703bf78 Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Wed, 13 May 2020 17:52:47 +0200
Subject: [PATCH] Implementing PER
---
sources/CPU/AddressingModes.cpp | 7 +++++++
sources/CPU/CPU.cpp | 6 ++----
sources/CPU/CPU.hpp | 10 +++++++---
sources/CPU/Instruction.hpp | 1 +
sources/CPU/Instructions/InternalInstruction.cpp | 9 +++++++++
tests/CPU/testInternal.cpp | 13 +++++++++++++
6 files changed, 39 insertions(+), 7 deletions(-)
diff --git a/sources/CPU/AddressingModes.cpp b/sources/CPU/AddressingModes.cpp
index d19a985..3f649c2 100644
--- a/sources/CPU/AddressingModes.cpp
+++ b/sources/CPU/AddressingModes.cpp
@@ -14,6 +14,13 @@ namespace ComSquare::CPU
return ret;
}
+ uint24_t CPU::_getImmediateAddr16Bits()
+ {
+ uint24_t ret = this->_registers.pac;
+ this->_registers.pc += 2;
+ return ret;
+ }
+
uint24_t CPU::_getImmediateAddrForA()
{
uint24_t effective = this->_registers.pac;
diff --git a/sources/CPU/CPU.cpp b/sources/CPU/CPU.cpp
index 8116408..34a01ae 100644
--- a/sources/CPU/CPU.cpp
+++ b/sources/CPU/CPU.cpp
@@ -6,9 +6,7 @@
#include
#include
-#include "../Exceptions/NotImplementedException.hpp"
#include "../Exceptions/InvalidAddress.hpp"
-#include "../Exceptions/InvalidOpcode.hpp"
namespace ComSquare::CPU
{
@@ -218,6 +216,8 @@ namespace ComSquare::CPU
return 0;
case Immediate8bits:
return this->_getImmediateAddr8Bits();
+ case Immediate16bits:
+ return this->_getImmediateAddr16Bits();
case ImmediateForA:
return this->_getImmediateAddrForA();
case ImmediateForX:
@@ -264,8 +264,6 @@ namespace ComSquare::CPU
case AbsoluteIndirectIndexedByX:
return this->_getAbsoluteIndirectIndexedByXAddr();
- default:
- return 0;
}
}
diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp
index 1c6be7d..d0b0d47 100644
--- a/sources/CPU/CPU.hpp
+++ b/sources/CPU/CPU.hpp
@@ -198,8 +198,10 @@ namespace ComSquare::CPU
//! @brief True if an addressing mode with an iterator (x, y) has crossed the page. (Used because crossing the page boundary take one more cycle to run certain instructions).
bool _hasIndexCrossedPageBoundary = false;
- //! @brief Immediate address mode is specified with a value in 8. (This functions returns the 24bit space address of the value).
+ //! @brief Immediate address mode is specified with a value in 8 bits. (This functions returns the 24bit space address of the value).
uint24_t _getImmediateAddr8Bits();
+ //! @brief Immediate address mode is specified with a value in 16 bits. (This functions returns the 24bit space address of the value).
+ uint24_t _getImmediateAddr16Bits();
//! @brief Immediate address mode is specified with a value in 8 or 16 bits. The value is 16 bits if the m flag is unset. (This functions returns the 24bit space address of the value).
uint24_t _getImmediateAddrForA();
//! @brief Immediate address mode is specified with a value in 8 or 16 bits. The value is 16 bits if the x flag is unset. (This functions returns the 24bit space address of the value).
@@ -431,6 +433,8 @@ namespace ComSquare::CPU
int ROL(uint24_t, AddressingMode);
// !@brief Rotate Right
int ROR(uint24_t, AddressingMode);
+ //! @brief Push Effective PC Relative Indirect Address
+ int PER(uint24_t, AddressingMode);
//! @brief All the instructions of the CPU.
//! @info Instructions are indexed by their opcode
@@ -533,7 +537,7 @@ namespace ComSquare::CPU
{&CPU::EOR, 5, "eor", AddressingMode::AbsoluteIndexedByXLong, 4}, // 5F
{&CPU::RTL, 6, "rtl", AddressingMode::Implied, 1}, // 60
{&CPU::ADC, 6, "adc", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 61
- {&CPU::BRK, 7, "per #-#", AddressingMode::Implied, 2}, // 62
+ {&CPU::PER, 6, "per", AddressingMode::Immediate16bits, 3}, // 62
{&CPU::ADC, 4, "adc", AddressingMode::StackRelative, 2}, // 63
{&CPU::STZ, 3, "stz", AddressingMode::DirectPage, 2}, // 64
{&CPU::ADC, 3, "adc", AddressingMode::DirectPage, 2}, // 65
@@ -606,7 +610,7 @@ namespace ComSquare::CPU
{&CPU::TAY, 2, "tay", AddressingMode::Implied, 1}, // A8
{&CPU::LDA, 2, "lda", AddressingMode::ImmediateForA, 2}, // A9
{&CPU::TAX, 2, "tax", AddressingMode::Implied, 1}, // AA
- {&CPU::BRK, 7, "trb #-#", AddressingMode::Implied, 2}, // AB
+ {&CPU::BRK, 7, "plb #-#", AddressingMode::Implied, 2}, // AB
{&CPU::LDY, 4, "ldy", AddressingMode::Absolute, 4}, // AC
{&CPU::LDA, 4, "lda", AddressingMode::Absolute, 3}, // AD
{&CPU::LDX, 4, "ldx", AddressingMode::Absolute, 3}, // AE
diff --git a/sources/CPU/Instruction.hpp b/sources/CPU/Instruction.hpp
index 8061d1e..f6ef811 100644
--- a/sources/CPU/Instruction.hpp
+++ b/sources/CPU/Instruction.hpp
@@ -17,6 +17,7 @@ namespace ComSquare::CPU
Implied,
Immediate8bits,
+ Immediate16bits,
ImmediateForA,
ImmediateForX,
diff --git a/sources/CPU/Instructions/InternalInstruction.cpp b/sources/CPU/Instructions/InternalInstruction.cpp
index 1fc020a..d3ee972 100644
--- a/sources/CPU/Instructions/InternalInstruction.cpp
+++ b/sources/CPU/Instructions/InternalInstruction.cpp
@@ -184,6 +184,15 @@ namespace ComSquare::CPU
return !this->_registers.p.x_b;
}
+ int CPU::PER(uint24_t valueAddr, AddressingMode)
+ {
+ uint16_t value = this->_bus->read(valueAddr);
+ value += this->_bus->read(valueAddr + 1) << 8u;
+ value += this->_registers.pc;
+ this->_push(value);
+ return 0;
+ }
+
int CPU::XCE(uint24_t, AddressingMode)
{
bool oldCarry = this->_registers.p.c;
diff --git a/tests/CPU/testInternal.cpp b/tests/CPU/testInternal.cpp
index 0619ece..6710426 100644
--- a/tests/CPU/testInternal.cpp
+++ b/tests/CPU/testInternal.cpp
@@ -914,4 +914,17 @@ Test(JML, simpleJump)
snes.cpu->_registers.pc = 0x8000;
snes.cpu->JML(0x10AB00, ComSquare::CPU::AddressingMode::Implied);
cr_assert_eq(snes.cpu->_registers.pac, 0x10AB00, "The program counter should be equal to 0x10AB00 but it was 0x%x.", snes.cpu->_registers.pac);
+}
+
+Test(PER, simple)
+{
+ Init()
+ snes.cpu->_registers.pac = 0x008005;
+ snes.cpu->_registers.s = 0x1FFF;
+ snes.wram->_data[0x0] = 0xFF;
+ snes.wram->_data[0x1] = 0xFF;
+ snes.cpu->PER(0x0, ComSquare::CPU::AddressingMode::Implied);
+ cr_assert_eq(snes.cpu->_registers.s, 0x1FFD, "The stack pointer should be equal to 0x1FFD but it was 0x%x.", snes.cpu->_registers.s);
+ uint16_t value = snes.cpu->_pop16();
+ cr_assert_eq(value, 0x8004, "The pushed value should be equal to 0x8004 but it was 0x%x.", value);
}
\ No newline at end of file