Add JML, AND AbsoluteLong, ADC AbsoluteLong

This commit is contained in:
scawful
2023-08-19 19:12:28 -04:00
parent f5c5c34b47
commit 7dcbc7f83c
4 changed files with 350 additions and 176 deletions

View File

@@ -66,6 +66,9 @@ uint8_t CPU::FetchByteDirectPage(uint8_t operand) {
}
void CPU::ExecuteInstruction(uint8_t opcode) {
// Update the PC based on the Program Bank Register
PC |= (static_cast<uint16_t>(PB) << 16);
// uint8_t opcode = FetchByte();
uint8_t operand = -1;
switch (opcode) {
@@ -94,7 +97,7 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
ADC(operand);
break;
case 0x6F: // ADC Absolute Long
operand = memory.ReadByte(AbsoluteLong());
operand = memory.ReadWord(AbsoluteLong());
ADC(operand);
break;
case 0x71: // ADC DP Indirect Indexed, Y
@@ -153,8 +156,7 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
AND(Absolute());
break;
case 0x2F: // AND Absolute Long
operand = memory.ReadByte(AbsoluteLong());
AND(operand);
ANDAbsoluteLong(AbsoluteLong());
break;
case 0x31: // AND DP Indirect Indexed, Y
operand = memory.ReadByte(DirectPageIndirectIndexedY());
@@ -177,16 +179,13 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
AND(operand);
break;
case 0x39: // AND Absolute Indexed, Y
operand = memory.ReadByte(AbsoluteIndexedY());
AND(operand);
AND(AbsoluteIndexedY());
break;
case 0x3D: // AND Absolute Indexed, X
operand = memory.ReadByte(AbsoluteIndexedX());
AND(operand);
AND(AbsoluteIndexedX());
break;
case 0x3F: // AND Absolute Long Indexed, X
operand = memory.ReadByte(AbsoluteLongIndexedX());
AND(operand);
AND(AbsoluteLongIndexedX());
break;
case 0x06: // ASL Direct Page
@@ -451,7 +450,7 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
JMP(Absolute());
break;
case 0x5C: // JMP Absolute Long
// JMP();
JML(AbsoluteLong());
break;
case 0x6C: // JMP Absolute Indirect
JMP(AbsoluteIndirect());
@@ -574,7 +573,7 @@ void CPU::ExecuteInstruction(uint8_t opcode) {
break;
case 0xEA: // NOP No Operation
// NOP();
NOP();
break;
case 0x01: // ORA DP Indexed Indirect, X
@@ -1010,6 +1009,14 @@ void CPU::AND(uint16_t address) {
}
}
// New function for absolute long addressing mode
void CPU::ANDAbsoluteLong(uint32_t address) {
uint32_t operand32 = memory.ReadWordLong(address);
A &= operand32;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80000000);
}
} // namespace emu
} // namespace app
} // namespace yaze

View File

@@ -105,7 +105,7 @@ class CPU : public Memory {
// Low: First operand byte
//
// LDA long
uint16_t AbsoluteLong() { return FetchLong(); }
uint32_t AbsoluteLong() { return FetchLong(); }
// Effective Address:
// The 24-bit operand is added to X based on the emulation mode
@@ -243,11 +243,14 @@ class CPU : public Memory {
// Registers
uint8_t A = 0; // Accumulator
uint8_t B = 0; // Accumulator (High)
uint8_t X = 0; // X index register
uint8_t X2 = 0; // X index register (High)
uint8_t Y = 0; // Y index register
uint8_t Y2 = 0; // Y index register (High)
uint16_t D = 0; // Direct Page register
uint16_t DB = 0; // Data Bank register
uint16_t PB = 0; // Program Bank register
uint8_t PB = 0; // Program Bank register
uint16_t PC = 0; // Program Counter
uint8_t E = 1; // Emulation mode flag
uint8_t status; // Processor Status (P)
@@ -288,91 +291,47 @@ class CPU : public Memory {
// ==========================================================================
// Instructions
/// ``` Unimplemented
// Left to implement
// * = in progress
// ADC: Add with carry *
// AND: Logical AND *
// ASL: Arithmetic shift left
// BCC: Branch if carry clear *
// BCS: Branch if carry set *
// BEQ: Branch if equal (zero set) *
// BIT: Bit test
// BMI: Branch if minus (negative set)
// BNE: Branch if not equal (zero clear)
// BPL: Branch if plus (negative clear)
// BRA: Branch always
// BRK: Break
// BRL: Branch always long
// BVC: Branch if overflow clear
// BVS: Branch if overflow set
// CMP: Compare
// COP: Coprocessor
// CPX: Compare X register
// CPY: Compare Y register
// DEC: Decrement
// EOR: Exclusive OR
// JMP: Jump
// JML: Jump long
// JSR: Jump to subroutine
// JSL: Jump to subroutine long
// LDA: Load accumulator
// LDX: Load X register
// LDY: Load Y register
// LSR: Logical shift right
// MVN: Move negative
// MVP: Move positive
// NOP: No operation
// ORA: Logical OR
// PEA: Push effective address
// PEI: Push effective indirect address
// PER: Push effective PC-relative address
// ROL: Rotate left
// ROR: Rotate right
// RTI: Return from interrupt
// RTL: Return from subroutine long
// RTS: Return from subroutine
// SBC: Subtract with carry
// STA: Store accumulator
// STP: Stop the clock
// STX: Store X register
// STY: Store Y register
// STZ: Store zero
// TDC: Transfer direct page register to accumulator
// TRB: Test and reset bits
// TSB: Test and set bits
// WAI: Wait for interrupt
// XBA: Exchange B and A accumulator
// ADC: Add with carry
void ADC(uint8_t operand);
void ANDAbsoluteLong(uint32_t address);
// AND: Logical AND
void AND(uint16_t address);
void BEQ(int8_t offset) {
if (GetZeroFlag()) { // If the zero flag is set
PC += offset; // Add the offset to the program counter
}
}
// ASL: Arithmetic shift left ```
// BCC: Branch if carry clear
void BCC(int8_t offset) {
if (!GetCarryFlag()) { // If the carry flag is clear
PC += offset; // Add the offset to the program counter
}
}
// BCS: Branch if carry set ```
// BEQ: Branch if equal (zero set)
void BEQ(int8_t offset) {
if (GetZeroFlag()) { // If the zero flag is set
PC += offset; // Add the offset to the program counter
}
}
// BIT: Bit test ```
// BMI: Branch if minus (negative set) ```
// BNE: Branch if not equal (zero clear) ```
// BPL: Branch if plus (negative clear) ```
// BRA: Branch always ```
// BRK: Break ```
// BRL: Branch always long
void BRL(int16_t offset) {
PC += offset; // Add the offset to the program counter
}
void LDA() {
A = memory[PC];
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
PC++;
}
// SEC: Set carry flag
void SEC() { status |= 0x01; }
// BVC: Branch if overflow clear ```
// BVS: Branch if overflow set ```
// CLC: Clear carry flag
void CLC() { status &= ~0x01; }
@@ -386,20 +345,25 @@ class CPU : public Memory {
// CLV: Clear overflow flag
void CLV() { status &= ~0x40; }
bool emulation_mode = false;
// CMP: Compare ```
// COP: Coprocessor ```
// CPX: Compare X register
void CPX(uint16_t address) {
uint16_t memory_value =
E ? memory.ReadByte(address) : memory.ReadWord(address);
compare(X, memory_value);
}
// CPY: Compare Y register
void CPY(uint16_t address) {
uint16_t memory_value =
E ? memory.ReadByte(address) : memory.ReadWord(address);
compare(Y, memory_value);
}
// DEC: Decrement ```
// DEX: Decrement X register
void DEX() {
X--;
@@ -414,21 +378,10 @@ class CPU : public Memory {
SetNegativeFlag(Y & 0x80);
}
// INX: Increment X register
void INX() {
X++;
SetNegativeFlag(X & 0x80);
SetZeroFlag(X == 0);
}
// EOR: Exclusive OR ```
// INY: Increment Y register
void INY() {
Y++;
SetNegativeFlag(Y & 0x80);
SetZeroFlag(Y == 0);
}
// INC: Increment memory
// INC: Increment
// TODO: Check if this is correct
void INC(uint16_t address) {
if (GetAccumulatorSize()) {
uint8_t value = ReadByte(address);
@@ -451,11 +404,33 @@ class CPU : public Memory {
}
}
// JMP: Jump to new address
// INX: Increment X register
void INX() {
X++;
SetNegativeFlag(X & 0x80);
SetZeroFlag(X == 0);
}
// INY: Increment Y register
void INY() {
Y++;
SetNegativeFlag(Y & 0x80);
SetZeroFlag(Y == 0);
}
// JMP: Jump
void JMP(uint16_t address) {
PC = address; // Set program counter to the new address
}
// JML: Jump long
void JML(uint32_t address) {
// Set the lower 16 bits of PC to the lower 16 bits of the address
PC = static_cast<uint8_t>(address & 0xFFFF);
// Set the PBR to the upper 8 bits of the address
PB = static_cast<uint8_t>((address >> 16) & 0xFF);
}
// JSR: Jump to subroutine
void JSR(uint16_t address) {
PC -= 1; // Subtract 1 from program counter
@@ -471,51 +446,65 @@ class CPU : public Memory {
PC = address; // Set program counter to the new address
}
// Push Accumulator on Stack
// LDA: Load accumulator
void LDA() {
A = memory[PC];
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
PC++;
}
// LDX: Load X register ```
// LDY: Load Y register ```
// LSR: Logical shift right ```
// MVN: Move negative ```
// MVP: Move positive ```
// NOP: No operation
void NOP() {
// Do nothing
}
// ORA: Logical OR ```
// PEA: Push effective address ```
// PEI: Push effective indirect address ```
// PER: Push effective PC-relative address ```
// PHA: Push Accumulator on Stack
void PHA() { memory.PushByte(A); }
// Pull Accumulator from Stack
// PHB: Push Data Bank Register on Stack
void PHB() { memory.PushByte(DB); }
// PHD: Push Program Bank Register on Stack
void PHD() { memory.PushWord(D); }
// PHK: Push Program Bank Register on Stack
void PHK() { memory.PushByte(PB); }
// PHP: Push Processor Status Register on Stack
void PHP() { memory.PushByte(status); }
// PHX: Push X Index Register on Stack
void PHX() { memory.PushByte(X); }
// PHY: Push Y Index Register on Stack
void PHY() { memory.PushByte(Y); }
// PLA: Pull Accumulator from Stack
void PLA() {
A = memory.PopByte();
SetNegativeFlag((A & 0x80) != 0);
SetZeroFlag(A == 0);
}
// Push Processor Status Register on Stack
void PHP() { memory.PushByte(status); }
// Pull Processor Status Register from Stack
void PLP() { status = memory.PopByte(); }
void PHX() { memory.PushByte(X); }
void PLX() {
X = memory.PopByte();
SetNegativeFlag((A & 0x80) != 0);
SetZeroFlag(X == 0);
}
void PHY() { memory.PushByte(Y); }
void PLY() {
Y = memory.PopByte();
SetNegativeFlag((A & 0x80) != 0);
SetZeroFlag(Y == 0);
}
// Push Data Bank Register on Stack
void PHB() { memory.PushByte(DB); }
// Pull Data Bank Register from Stack
// PLB: Pull data bank register
void PLB() {
DB = memory.PopByte();
SetNegativeFlag((DB & 0x80) != 0);
SetZeroFlag(DB == 0);
}
// Push Program Bank Register on Stack
void PHD() { memory.PushWord(D); }
// Pull Direct Page Register from Stack
void PLD() {
D = memory.PopWord();
@@ -523,89 +512,141 @@ class CPU : public Memory {
SetZeroFlag(D == 0);
}
// Push Program Bank Register on Stack
void PHK() { memory.PushByte(PB); }
// Pull Processor Status Register from Stack
void PLP() { status = memory.PopByte(); }
void SEI() { status |= 0x04; }
void SED() { status |= 0x08; }
void SEP() {
PC++;
auto byte = FetchByte();
status |= byte;
// PLX: Pull X Index Register from Stack
void PLX() {
X = memory.PopByte();
SetNegativeFlag((A & 0x80) != 0);
SetZeroFlag(X == 0);
}
// PHY: Pull Y Index Register from Stack
void PLY() {
Y = memory.PopByte();
SetNegativeFlag((A & 0x80) != 0);
SetZeroFlag(Y == 0);
}
// REP: Reset status bits
void REP() {
PC++;
auto byte = FetchByte();
status &= ~byte;
}
void TCD() {
D = A;
SetZeroFlag(D == 0);
SetNegativeFlag(D & 0x80);
// ROL: Rotate left ```
// ROR: Rotate right ```
// RTI: Return from interrupt ```
// RTL: Return from subroutine long ```
// RTS: Return from subroutine ```
// SBC: Subtract with carry ```
// SEC: Set carry flag
void SEC() { status |= 0x01; }
// SED: Set decimal mode
void SED() { status |= 0x08; }
// SEI: Set interrupt disable flag
void SEI() { status |= 0x04; }
// SEP: Set status bits
void SEP() {
PC++;
auto byte = FetchByte();
status |= byte;
}
void TDC() {
A = D;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
}
void TCS() { memory.SetSP(A); }
// STA: Store accumulator ```
// STP: Stop the clock ```
// STX: Store X register ```
// STY: Store Y register ```
// STZ: Store zero ```
// TAX: Transfer accumulator to X
void TAX() {
X = A;
SetZeroFlag(X == 0);
SetNegativeFlag(X & 0x80);
}
// TAY: Transfer accumulator to Y
void TAY() {
Y = A;
SetZeroFlag(Y == 0);
SetNegativeFlag(Y & 0x80);
}
void TYA() {
A = Y;
// TCD: Transfer accumulator to direct page register
void TCD() {
D = A;
SetZeroFlag(D == 0);
SetNegativeFlag(D & 0x80);
}
// TCS: Transfer accumulator to stack pointer
void TCS() { memory.SetSP(A); }
// TDC: Transfer direct page register to accumulator
void TDC() {
A = D;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
}
void TXA() {
A = X;
// TRB: Test and reset bits ```
// TSB: Test and set bits ```
// TSC: Transfer stack pointer to accumulator
void TSC() {
A = SP();
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
}
void TXY() {
X = Y;
SetZeroFlag(X == 0);
SetNegativeFlag(X & 0x80);
}
void TYX() {
Y = X;
SetZeroFlag(Y == 0);
SetNegativeFlag(Y & 0x80);
}
// TSX: Transfer stack pointer to X
void TSX() {
X = SP();
SetZeroFlag(X == 0);
SetNegativeFlag(X & 0x80);
}
void TXS() { memory.SetSP(X); }
void TSC() {
A = SP();
// TXA: Transfer X to accumulator
void TXA() {
A = X;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
}
// TXS: Transfer X to stack pointer
void TXS() { memory.SetSP(X); }
// TXY: Transfer X to Y
void TXY() {
X = Y;
SetZeroFlag(X == 0);
SetNegativeFlag(X & 0x80);
}
// TYA: Transfer Y to accumulator
void TYA() {
A = Y;
SetZeroFlag(A == 0);
SetNegativeFlag(A & 0x80);
}
// TYX: Transfer Y to X
void TYX() {
Y = X;
SetZeroFlag(Y == 0);
SetNegativeFlag(Y & 0x80);
}
// WAI: Wait for interrupt ```
// XBA: Exchange B and A accumulator ```
// XCE: Exchange Carry and Emulation Flags
void XCE() {
uint8_t carry = status & 0x01;

View File

@@ -58,8 +58,8 @@ class MemoryImpl : public Memory {
if (address < dp_memory_.size()) {
return dp_memory_.ReadByte(static_cast<uint8_t>(address));
}
// uint32_t mapped_address = GetMappedAddress(address);
return memory_.at(address);
uint32_t mapped_address = GetMappedAddress(address);
return memory_.at(mapped_address);
}
uint16_t ReadWord(uint16_t address) const override {
if (address < dp_memory_.size()) {
@@ -77,8 +77,8 @@ class MemoryImpl : public Memory {
}
void WriteByte(uint32_t address, uint8_t value) override {
// uint32_t mapped_address = GetMappedAddress(address);
memory_[address] = value;
uint32_t mapped_address = GetMappedAddress(address);
memory_[mapped_address] = value;
}
void WriteWord(uint32_t address, uint16_t value) override {
uint32_t mapped_address = GetMappedAddress(address);