Add WriteLong to Memory, CPU
This commit is contained in:
@@ -806,6 +806,7 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
|
|||||||
case 0x20: // JSR Absolute
|
case 0x20: // JSR Absolute
|
||||||
{
|
{
|
||||||
operand = Absolute(AccessType::Control);
|
operand = Absolute(AccessType::Control);
|
||||||
|
PB = (operand >> 16);
|
||||||
JSR(operand);
|
JSR(operand);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -904,7 +905,7 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
|
|||||||
case 0xBD: // LDA Absolute Indexed, X
|
case 0xBD: // LDA Absolute Indexed, X
|
||||||
{
|
{
|
||||||
operand = AbsoluteIndexedX();
|
operand = AbsoluteIndexedX();
|
||||||
LDA(operand);
|
LDA(operand, false, false, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xBF: // LDA Absolute Long Indexed, X
|
case 0xBF: // LDA Absolute Long Indexed, X
|
||||||
@@ -1321,9 +1322,11 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
|
|||||||
STA(operand);
|
STA(operand);
|
||||||
break;
|
break;
|
||||||
case 0x97: // STA DP Indirect Long Indexed, Y
|
case 0x97: // STA DP Indirect Long Indexed, Y
|
||||||
|
{
|
||||||
operand = DirectPageIndirectLongIndexedY();
|
operand = DirectPageIndirectLongIndexedY();
|
||||||
STA(operand);
|
STA(operand);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 0x99: // STA Absolute Indexed, Y
|
case 0x99: // STA Absolute Indexed, Y
|
||||||
operand = AbsoluteIndexedY();
|
operand = AbsoluteIndexedY();
|
||||||
STA(operand);
|
STA(operand);
|
||||||
@@ -1510,7 +1513,8 @@ void CPU::LogInstructions(uint16_t PC, uint8_t opcode, uint16_t operand,
|
|||||||
<< "$" << std::uppercase << std::setw(2) << std::setfill('0')
|
<< "$" << std::uppercase << std::setw(2) << std::setfill('0')
|
||||||
<< static_cast<int>(PB) << ":" << std::hex << PC;
|
<< static_cast<int>(PB) << ":" << std::hex << PC;
|
||||||
std::cout << " \033[1;32m"
|
std::cout << " \033[1;32m"
|
||||||
<< ": 0x" << std::hex << static_cast<int>(opcode) << " ";
|
<< ": 0x" << std::hex << std::uppercase << std::setw(2)
|
||||||
|
<< std::setfill('0') << static_cast<int>(opcode) << " ";
|
||||||
std::cout << " \033[1;35m" << opcode_to_mnemonic.at(opcode) << " "
|
std::cout << " \033[1;35m" << opcode_to_mnemonic.at(opcode) << " "
|
||||||
<< "\033[0m";
|
<< "\033[0m";
|
||||||
|
|
||||||
@@ -1526,7 +1530,53 @@ void CPU::LogInstructions(uint16_t PC, uint8_t opcode, uint16_t operand,
|
|||||||
std::cout << std::hex << std::setw(4) << std::setfill('0')
|
std::cout << std::hex << std::setw(4) << std::setfill('0')
|
||||||
<< static_cast<int>(operand);
|
<< static_cast<int>(operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool x_indexing, y_indexing;
|
||||||
|
auto x_indexed_instruction_opcodes = {0x15, 0x16, 0x17, 0x55, 0x56,
|
||||||
|
0x57, 0xD5, 0xD6, 0xD7, 0xF5,
|
||||||
|
0xF6, 0xF7, 0xBD};
|
||||||
|
auto y_indexed_instruction_opcodes = {0x19, 0x97, 0x1D, 0x59, 0x5D, 0x99,
|
||||||
|
0x9D, 0xB9, 0xD9, 0xDD, 0xF9, 0xFD};
|
||||||
|
if (std::find(x_indexed_instruction_opcodes.begin(),
|
||||||
|
x_indexed_instruction_opcodes.end(),
|
||||||
|
opcode) != x_indexed_instruction_opcodes.end()) {
|
||||||
|
x_indexing = true;
|
||||||
|
} else {
|
||||||
|
x_indexing = false;
|
||||||
}
|
}
|
||||||
|
if (std::find(y_indexed_instruction_opcodes.begin(),
|
||||||
|
y_indexed_instruction_opcodes.end(),
|
||||||
|
opcode) != y_indexed_instruction_opcodes.end()) {
|
||||||
|
y_indexing = true;
|
||||||
|
} else {
|
||||||
|
y_indexing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x_indexing) {
|
||||||
|
std::cout << ", X";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y_indexing) {
|
||||||
|
std::cout << ", Y";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log the registers and flags.
|
||||||
|
std::cout << std::right;
|
||||||
|
std::cout << "\033[1;33m"
|
||||||
|
<< " A:" << std::hex << std::setw(2) << std::setfill('0')
|
||||||
|
<< static_cast<int>(A);
|
||||||
|
std::cout << " X:" << std::hex << std::setw(2) << std::setfill('0')
|
||||||
|
<< static_cast<int>(X);
|
||||||
|
std::cout << " Y:" << std::hex << std::setw(2) << std::setfill('0')
|
||||||
|
<< static_cast<int>(Y);
|
||||||
|
std::cout << " S:" << std::hex << std::setw(2) << std::setfill('0')
|
||||||
|
<< static_cast<int>(status);
|
||||||
|
std::cout << " DB:" << std::hex << std::setw(2) << std::setfill('0')
|
||||||
|
<< static_cast<int>(DB);
|
||||||
|
std::cout << " D:" << std::hex << std::setw(2) << std::setfill('0')
|
||||||
|
<< static_cast<int>(D);
|
||||||
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1548,7 +1598,6 @@ uint8_t CPU::GetInstructionLength(uint8_t opcode) {
|
|||||||
case 0xFC: // JSR Absolute Indexed Indirect
|
case 0xFC: // JSR Absolute Indexed Indirect
|
||||||
case 0xDC: // JMP Absolute Indirect Long
|
case 0xDC: // JMP Absolute Indirect Long
|
||||||
case 0x6B: // RTL
|
case 0x6B: // RTL
|
||||||
|
|
||||||
case 0x82: // BRL Relative Long
|
case 0x82: // BRL Relative Long
|
||||||
PC = next_pc_;
|
PC = next_pc_;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1559,7 +1608,7 @@ uint8_t CPU::GetInstructionLength(uint8_t opcode) {
|
|||||||
|
|
||||||
case 0x60: // RTS
|
case 0x60: // RTS
|
||||||
PC = last_call_frame_;
|
PC = last_call_frame_;
|
||||||
return 0;
|
return 3;
|
||||||
|
|
||||||
// Branch Instructions (BCC, BCS, BNE, BEQ, etc.)
|
// Branch Instructions (BCC, BCS, BNE, BEQ, etc.)
|
||||||
case 0x90: // BCC near
|
case 0x90: // BCC near
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ class CPU : public Memory, public Loggable, public core::ExperimentFlags {
|
|||||||
// Low: First operand byte
|
// Low: First operand byte
|
||||||
//
|
//
|
||||||
// LDA addr
|
// LDA addr
|
||||||
uint16_t Absolute(AccessType access_type = AccessType::Data);
|
uint32_t Absolute(AccessType access_type = AccessType::Data);
|
||||||
|
|
||||||
// Effective Address:
|
// Effective Address:
|
||||||
// The Data Bank Register is concatened with the 16-bit operand
|
// The Data Bank Register is concatened with the 16-bit operand
|
||||||
@@ -342,6 +342,9 @@ class CPU : public Memory, public Loggable, public core::ExperimentFlags {
|
|||||||
void WriteWord(uint32_t address, uint16_t value) override {
|
void WriteWord(uint32_t address, uint16_t value) override {
|
||||||
memory.WriteWord(address, value);
|
memory.WriteWord(address, value);
|
||||||
}
|
}
|
||||||
|
void WriteLong(uint32_t address, uint32_t value) {
|
||||||
|
memory.WriteLong(address, value);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t FetchByte() {
|
uint8_t FetchByte() {
|
||||||
uint32_t address = (PB << 16) | PC + 1;
|
uint32_t address = (PB << 16) | PC + 1;
|
||||||
@@ -498,7 +501,8 @@ class CPU : public Memory, public Loggable, public core::ExperimentFlags {
|
|||||||
void JSL(uint32_t address);
|
void JSL(uint32_t address);
|
||||||
|
|
||||||
// LDA: Load accumulator
|
// LDA: Load accumulator
|
||||||
void LDA(uint16_t address, bool immediate = false, bool direct_page = false);
|
void LDA(uint16_t address, bool immediate = false, bool direct_page = false,
|
||||||
|
bool data_bank = false);
|
||||||
|
|
||||||
// LDX: Load X register
|
// LDX: Load X register
|
||||||
void LDX(uint16_t address, bool immediate = false);
|
void LDX(uint16_t address, bool immediate = false);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace yaze {
|
|||||||
namespace app {
|
namespace app {
|
||||||
namespace emu {
|
namespace emu {
|
||||||
|
|
||||||
uint16_t CPU::Absolute(CPU::AccessType access_type) {
|
uint32_t CPU::Absolute(CPU::AccessType access_type) {
|
||||||
auto operand = FetchWord();
|
auto operand = FetchWord();
|
||||||
uint32_t bank =
|
uint32_t bank =
|
||||||
(access_type == CPU::AccessType::Data) ? (DB << 16) : (PB << 16);
|
(access_type == CPU::AccessType::Data) ? (DB << 16) : (PB << 16);
|
||||||
|
|||||||
@@ -361,7 +361,7 @@ void CPU::JSL(uint32_t address) {
|
|||||||
next_pc_ = address; // Set program counter to the new address
|
next_pc_ = address; // Set program counter to the new address
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::LDA(uint16_t address, bool isImmediate, bool direct_page) {
|
void CPU::LDA(uint16_t address, bool isImmediate, bool direct_page, bool data_bank) {
|
||||||
uint8_t bank = PB;
|
uint8_t bank = PB;
|
||||||
if (direct_page) {
|
if (direct_page) {
|
||||||
bank = 0;
|
bank = 0;
|
||||||
@@ -628,7 +628,9 @@ void CPU::RTL() {
|
|||||||
PB = memory.PopByte();
|
PB = memory.PopByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPU::RTS() { last_call_frame_ = memory.PopWord(); }
|
void CPU::RTS() {
|
||||||
|
last_call_frame_ = memory.PopWord();
|
||||||
|
}
|
||||||
|
|
||||||
void CPU::SBC(uint32_t value, bool isImmediate) {
|
void CPU::SBC(uint32_t value, bool isImmediate) {
|
||||||
uint16_t operand;
|
uint16_t operand;
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ class Memory {
|
|||||||
|
|
||||||
virtual void WriteByte(uint32_t address, uint8_t value) = 0;
|
virtual void WriteByte(uint32_t address, uint8_t value) = 0;
|
||||||
virtual void WriteWord(uint32_t address, uint16_t value) = 0;
|
virtual void WriteWord(uint32_t address, uint16_t value) = 0;
|
||||||
|
virtual void WriteLong(uint32_t address, uint32_t value) = 0;
|
||||||
|
|
||||||
virtual void PushByte(uint8_t value) = 0;
|
virtual void PushByte(uint8_t value) = 0;
|
||||||
virtual uint8_t PopByte() = 0;
|
virtual uint8_t PopByte() = 0;
|
||||||
@@ -263,6 +264,12 @@ class MemoryImpl : public Memory, public Loggable {
|
|||||||
memory_.at(mapped_address) = value & 0xFF;
|
memory_.at(mapped_address) = value & 0xFF;
|
||||||
memory_.at(mapped_address + 1) = (value >> 8) & 0xFF;
|
memory_.at(mapped_address + 1) = (value >> 8) & 0xFF;
|
||||||
}
|
}
|
||||||
|
void WriteLong(uint32_t address, uint32_t value) override {
|
||||||
|
uint32_t mapped_address = GetMappedAddress(address);
|
||||||
|
memory_.at(mapped_address) = value & 0xFF;
|
||||||
|
memory_.at(mapped_address + 1) = (value >> 8) & 0xFF;
|
||||||
|
memory_.at(mapped_address + 2) = (value >> 16) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
// Stack operations
|
// Stack operations
|
||||||
void PushByte(uint8_t value) override {
|
void PushByte(uint8_t value) override {
|
||||||
@@ -347,11 +354,11 @@ class MemoryImpl : public Memory, public Loggable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bank <= 0x3F) {
|
if (bank <= 0x3F) {
|
||||||
if (offset <= 0x1FFF) {
|
if (address <= 0x1FFF) {
|
||||||
return (0x7E << 16) + offset; // Shadow RAM
|
return (0x7E << 16) + offset; // Shadow RAM
|
||||||
} else if (offset <= 0x5FFF) {
|
} else if (address <= 0x5FFF) {
|
||||||
return (bank << 16) + (offset - 0x2000) + 0x2000; // Hardware Registers
|
return (bank << 16) + (offset - 0x2000) + 0x2000; // Hardware Registers
|
||||||
} else if (offset <= 0x7FFF) {
|
} else if (address <= 0x7FFF) {
|
||||||
return offset - 0x6000 + 0x6000; // Expansion RAM
|
return offset - 0x6000 + 0x6000; // Expansion RAM
|
||||||
} else {
|
} else {
|
||||||
// Return lorom mapping
|
// Return lorom mapping
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ class MockMemory : public Memory {
|
|||||||
|
|
||||||
MOCK_METHOD2(WriteByte, void(uint32_t address, uint8_t value));
|
MOCK_METHOD2(WriteByte, void(uint32_t address, uint8_t value));
|
||||||
MOCK_METHOD2(WriteWord, void(uint32_t address, uint16_t value));
|
MOCK_METHOD2(WriteWord, void(uint32_t address, uint16_t value));
|
||||||
|
MOCK_METHOD2(WriteLong, void(uint32_t address, uint32_t value));
|
||||||
|
|
||||||
MOCK_METHOD1(PushByte, void(uint8_t value));
|
MOCK_METHOD1(PushByte, void(uint8_t value));
|
||||||
MOCK_METHOD0(PopByte, uint8_t());
|
MOCK_METHOD0(PopByte, uint8_t());
|
||||||
@@ -173,8 +174,9 @@ class MockMemory : public Memory {
|
|||||||
return value;
|
return value;
|
||||||
});
|
});
|
||||||
ON_CALL(*this, SP()).WillByDefault([this]() { return SP_; });
|
ON_CALL(*this, SP()).WillByDefault([this]() { return SP_; });
|
||||||
ON_CALL(*this, SetSP(::testing::_))
|
ON_CALL(*this, SetSP(::testing::_)).WillByDefault([this](uint16_t value) {
|
||||||
.WillByDefault([this](uint16_t value) { SP_ = value; });
|
SP_ = value;
|
||||||
|
});
|
||||||
ON_CALL(*this, ClearMemory()).WillByDefault([this]() {
|
ON_CALL(*this, ClearMemory()).WillByDefault([this]() {
|
||||||
memory_.resize(64000, 0x00);
|
memory_.resize(64000, 0x00);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user