From 66f82dc5f0582c71db4be570ff2d4719e2ca2e1f Mon Sep 17 00:00:00 2001
From: Anonymus Raccoon
Date: Wed, 13 May 2020 14:11:58 +0200
Subject: [PATCH] Implementing ASL
---
sources/CPU/CPU.hpp | 12 +++---
sources/CPU/Instructions/BitsInstructions.cpp | 40 +++++++++++++++++++
tests/CPU/testBits.cpp | 38 ++++++++++++++++++
3 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/sources/CPU/CPU.hpp b/sources/CPU/CPU.hpp
index 1bbe317..a65944c 100644
--- a/sources/CPU/CPU.hpp
+++ b/sources/CPU/CPU.hpp
@@ -421,6 +421,8 @@ namespace ComSquare::CPU
int XBA(uint24_t, AddressingMode);
//! @brief Test Memory Bits against Accumulator
int BIT(uint24_t, AddressingMode);
+ //! @brief Arithmetic Shift Left
+ int ASL(uint24_t, AddressingMode);
//! @brief All the instructions of the CPU.
//! @info Instructions are indexed by their opcode
@@ -431,15 +433,15 @@ namespace ComSquare::CPU
{&CPU::ORA, 4, "ora", AddressingMode::StackRelative, 2}, // 03
{&CPU::TSB, 5, "tsb", AddressingMode::DirectPage, 2}, // 04
{&CPU::ORA, 3, "ora", AddressingMode::DirectPage, 2}, // 05
- {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 06
+ {&CPU::ASL, 5, "asl", AddressingMode::DirectPage, 2}, // 06
{&CPU::ORA, 6, "ora", AddressingMode::DirectPageIndirectLong, 2}, // 07
{&CPU::PHP, 3, "php", AddressingMode::Implied, 3}, // 08
{&CPU::ORA, 2, "ora", AddressingMode::ImmediateForA, 2}, // 09
- {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 0A
+ {&CPU::ASL, 2, "asl", AddressingMode::Implied, 1}, // 0A
{&CPU::PHD, 4, "phd", AddressingMode::Implied, 1}, // 0B
{&CPU::TSB, 6, "tsb", AddressingMode::Absolute, 3}, // 0C
{&CPU::ORA, 3, "ora", AddressingMode::Absolute, 4}, // 0D
- {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 0E
+ {&CPU::ASL, 6, "asl", AddressingMode::Absolute, 3}, // 0E
{&CPU::ORA, 5, "ora", AddressingMode::AbsoluteLong, 5}, // 0F
{&CPU::BPL, 7, "bpl", AddressingMode::Immediate8bits, 2}, // 10
{&CPU::ORA, 5, "ora", AddressingMode::DirectPageIndirectIndexedByY, 2}, // 11
@@ -447,7 +449,7 @@ namespace ComSquare::CPU
{&CPU::ORA, 7, "ora", AddressingMode::StackRelativeIndirectIndexedByY, 2}, // 13
{&CPU::BRK, 7, "trb #-#", AddressingMode::Implied, 2}, // 14
{&CPU::ORA, 4, "ora", AddressingMode::DirectPageIndexedByX, 2}, // 15
- {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 16
+ {&CPU::ASL, 6, "asl", AddressingMode::DirectPageIndexedByX, 2}, // 16
{&CPU::ORA, 6, "ora", AddressingMode::DirectPageIndirectIndexedByYLong, 2}, // 17
{&CPU::CLC, 2, "clc", AddressingMode::Implied, 1}, // 18
{&CPU::ORA, 4, "ora", AddressingMode::AbsoluteIndexedByY, 3}, // 19
@@ -455,7 +457,7 @@ namespace ComSquare::CPU
{&CPU::TCS, 2, "tcs", AddressingMode::Implied, 1}, // 1B
{&CPU::BRK, 7, "trb #-#", AddressingMode::Implied, 2}, // 1C
{&CPU::ORA, 4, "ora", AddressingMode::AbsoluteIndexedByX, 3}, // 1D
- {&CPU::BRK, 7, "asl #-#", AddressingMode::Implied, 2}, // 1E
+ {&CPU::ASL, 7, "asl", AddressingMode::AbsoluteIndexedByX, 3}, // 1E
{&CPU::ORA, 5, "ora", AddressingMode::AbsoluteIndexedByXLong, 4}, // 1F
{&CPU::JSR, 6, "jsr", AddressingMode::Absolute, 3}, // 20
{&CPU::AND, 6, "and", AddressingMode::DirectPageIndirectIndexedByX, 2}, // 21
diff --git a/sources/CPU/Instructions/BitsInstructions.cpp b/sources/CPU/Instructions/BitsInstructions.cpp
index 41848f6..7ad9f83 100644
--- a/sources/CPU/Instructions/BitsInstructions.cpp
+++ b/sources/CPU/Instructions/BitsInstructions.cpp
@@ -55,4 +55,44 @@ namespace ComSquare::CPU
}
return cycles;
}
+
+ int CPU::ASL(uint24_t valueAddr, AddressingMode mode)
+ {
+ unsigned highByte = this->_registers.p.m ? 0x80u : 0x8000u;
+
+ if (mode == Implied) {
+ this->_registers.a <<= 1u;
+ this->_registers.p.n = this->_registers.a & highByte;
+ this->_registers.p.z = this->_registers.a == 0;
+ return 0;
+ }
+
+ uint16_t value = this->_bus->read(valueAddr);
+ if (!this->_registers.p.m)
+ value += this->_bus->read(valueAddr + 1) << 8u;
+
+ this->_registers.p.c = value & highByte;
+
+ value <<= 1u;
+ this->_bus->write(valueAddr, value);
+ if (!this->_registers.p.m)
+ this->_bus->write(valueAddr + 1, value >> 8u);
+
+ this->_registers.p.n = value & highByte;
+ this->_registers.p.z = value == 0;
+
+ int cycles = 2 * !this->_registers.p.m;
+ switch (mode) {
+ case DirectPage:
+ case DirectPageIndexedByX:
+ cycles += this->_registers.dl != 0;
+ break;
+ case AbsoluteIndexedByX:
+ cycles += this->_hasIndexCrossedPageBoundary;
+ break;
+ default:
+ break;
+ }
+ return cycles;
+ }
}
\ No newline at end of file
diff --git a/tests/CPU/testBits.cpp b/tests/CPU/testBits.cpp
index 9e8e5dd..1e94a0a 100644
--- a/tests/CPU/testBits.cpp
+++ b/tests/CPU/testBits.cpp
@@ -114,4 +114,42 @@ Test(BIT, other)
cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
cr_assert_eq(snes.cpu->_registers.p.v, true, "The overflow flag should be set.");
cr_assert_eq(snes.cpu->_registers.p.n, true, "The negative flag should be set.");
+}
+
+Test(ASL, emulationTest)
+{
+ Init()
+ snes.wram->_data[0] = 0b10110011;
+ snes.cpu->_registers.p.m = true;
+ snes.cpu->ASL(0x0, ComSquare::CPU::AddressingMode::Absolute);
+ cr_assert_eq(snes.wram->_data[0], 0b01100110, "The data in ram should be 0b01100110 but it was %x", snes.wram->_data[0]);
+ cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
+ cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set.");
+ cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
+}
+
+Test(ASL, nativeTest)
+{
+ Init()
+ snes.wram->_data[0] = 0b10110011;
+ snes.wram->_data[1] = 0b10000011;
+ snes.cpu->_registers.p.m = false;
+ snes.cpu->ASL(0x0, ComSquare::CPU::AddressingMode::Absolute);
+ cr_assert_eq(snes.wram->_data[0], 0b01100110, "The data in ram should be 0b01100110 but it was %x", snes.wram->_data[0]);
+ cr_assert_eq(snes.wram->_data[1], 0b00000111, "The data in ram should be 0b00000111 but it was %x", snes.wram->_data[1]);
+ cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
+ cr_assert_eq(snes.cpu->_registers.p.c, true, "The carry flag should be set.");
+ cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
+}
+
+Test(ASL, accumulator)
+{
+ Init()
+ snes.cpu->_registers.a = 0b10110011;
+ snes.cpu->_registers.p.m = true;
+ snes.cpu->ASL(0x0, ComSquare::CPU::AddressingMode::Implied);
+ cr_assert_eq(snes.cpu->_registers.al, 0b01100110, "The accumulator should be 0b01100110 but it was %x", snes.cpu->_registers.al);
+ cr_assert_eq(snes.cpu->_registers.p.z, false, "The zero flag should not be set.");
+ cr_assert_eq(snes.cpu->_registers.p.c, false, "The carry flag should not be set.");
+ cr_assert_eq(snes.cpu->_registers.p.n, false, "The negative flag should not be set.");
}
\ No newline at end of file