Switch back to use standard bit encoded fields.

Signed-off-by: Adrian.Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian.Conlon 2017-07-10 15:51:33 +01:00
parent 3001a97128
commit d3c0494fb3
8 changed files with 82 additions and 167 deletions

View File

@ -19,6 +19,7 @@ namespace EightBit {
Disassembly(MOS6502& processor, const Symbols& symbols);
std::string Dump_Flags(uint8_t value) const;
std::string Dump_ByteValue(uint8_t value) const;
std::string Dump_WordValue(uint16_t value) const;

View File

@ -1,84 +0,0 @@
#pragma once
#include <string>
#include <cstdint>
namespace EightBit {
struct StatusFlags {
bool negative;
bool overflow;
bool reserved;
bool brk;
bool decimal;
bool interrupt;
bool zero;
bool carry;
enum StatusBits {
Negative = 0x80, // N
Overflow = 0x40, // V
Reserved = 0x20, // ignored
Break = 0x10, // B
Decimal = 0x08, // D (use BCD for arithmetic)
Interrupt = 0x04, // I (IRQ disable)
Zero = 0x02, // Z
Carry = 0x01, // C
};
StatusFlags(uint8_t value) {
negative = (value & StatusBits::Negative) != 0;
overflow = (value & StatusBits::Overflow) != 0;
reserved = (value & StatusBits::Reserved) != 0;
brk = (value & StatusBits::Break) != 0;
decimal = (value & StatusBits::Decimal) != 0;
interrupt = (value & StatusBits::Interrupt) != 0;
zero = (value & StatusBits::Zero) != 0;
carry = (value & StatusBits::Carry) != 0;
}
operator uint8_t() const {
uint8_t flags = 0;
if (negative)
flags |= StatusBits::Negative;
if (overflow)
flags |= StatusBits::Overflow;
if (reserved)
flags |= StatusBits::Reserved;
if (brk)
flags |= StatusBits::Break;
if (decimal)
flags |= StatusBits::Decimal;
if (interrupt)
flags |= StatusBits::Interrupt;
if (zero)
flags |= StatusBits::Zero;
if (carry)
flags |= StatusBits::Carry;
return flags;
}
operator std::string() const {
std::string returned;
returned += negative ? "N" : "-";
returned += overflow ? "O" : "-";
returned += reserved ? "R" : "-";
returned += brk ? "B" : "-";
returned += decimal ? "D" : "-";
returned += interrupt ? "I" : "-";
returned += zero ? "Z" : "-";
returned += carry ? "C" : "-";
return returned;
}
};
}

View File

@ -8,13 +8,23 @@
#include "Memory.h"
#include "Processor.h"
#include "ProcessorType.h"
#include "StatusFlags.h"
#include "AddressingMode.h"
#include "Signal.h"
namespace EightBit {
class MOS6502 : public Processor {
public:
enum StatusBits {
NF = 0x80, // Negative
VF = 0x40, // Overflow
RF = 0x20, // reserved
BF = 0x10, // Brk
DF = 0x08, // D (use BCD for arithmetic)
IF = 0x04, // I (IRQ disable)
ZF = 0x02, // Zero
CF = 0x01, // Carry
};
typedef std::function<void()> instruction_t;
struct Instruction {
@ -35,8 +45,7 @@ namespace EightBit {
uint8_t& Y() { return y; }
uint8_t& A() { return a; }
uint8_t& S() { return s; }
StatusFlags& P() { return p; }
uint8_t& P() { return p; }
const Instruction& getInstruction(uint8_t code) const {
return instructions[code];
@ -78,8 +87,8 @@ namespace EightBit {
void OverlayInstructionSet(const std::array<Instruction, 0x100>& overlay);
void OverlayInstructionSet(const std::array<Instruction, 0x100>& overlay, bool includeIllegal);
void UpdateZeroFlag(uint8_t datum) { p.zero = datum == 0; }
void UpdateNegativeFlag(uint8_t datum) { p.negative = (datum & StatusFlags::Negative) != 0; }
void UpdateZeroFlag(uint8_t datum) { clearFlag(P(), ZF, datum); }
void UpdateNegativeFlag(uint8_t datum) { setFlag(P(), NF, datum & NF); }
void UpdateZeroNegativeFlags(uint8_t datum) {
UpdateZeroFlag(datum);
@ -444,8 +453,7 @@ namespace EightBit {
uint8_t y; // index register Y
uint8_t a; // accumulator
uint8_t s; // stack pointer
StatusFlags p = 0; // processor status
uint8_t p; // processor status
std::array<Instruction, 0x100> instructions;

View File

@ -31,6 +31,19 @@ EightBit::Disassembly::Disassembly(MOS6502& targetProcessor, const Symbols& targ
};
}
std::string EightBit::Disassembly::Dump_Flags(uint8_t value) const {
std::string returned;
returned += (value & MOS6502::NF) ? "N" : "-";
returned += (value & MOS6502::VF) ? "O" : "-";
returned += (value & MOS6502::RF) ? "R" : "-";
returned += (value & MOS6502::BF) ? "B" : "-";
returned += (value & MOS6502::DF) ? "D" : "-";
returned += (value & MOS6502::IF) ? "I" : "-";
returned += (value & MOS6502::ZF) ? "Z" : "-";
returned += (value & MOS6502::CF) ? "C" : "-";
return returned;
}
std::string EightBit::Disassembly::Dump_ByteValue(uint8_t value) const {
std::ostringstream output;
output << std::hex << std::setw(2) << std::setfill('0') << (int)value;

View File

@ -146,7 +146,6 @@
<ClInclude Include="..\inc\ProfileLineEventArgs.h" />
<ClInclude Include="..\inc\Profiler.h" />
<ClInclude Include="..\inc\ProfileScopeEventArgs.h" />
<ClInclude Include="..\inc\StatusFlags.h" />
<ClInclude Include="..\inc\Symbols.h" />
<ClInclude Include="stdafx.h" />
</ItemGroup>

View File

@ -44,9 +44,6 @@
<ClInclude Include="..\inc\ProfileScopeEventArgs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\StatusFlags.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\Symbols.h">
<Filter>Header Files</Filter>
</ClInclude>

View File

@ -19,7 +19,7 @@ void EightBit::MOS6502::initialise() {
a = 0;
p = 0;
p.reserved = true;
setFlag(P(), RF);
s = 0xff;
}
@ -57,7 +57,7 @@ void EightBit::MOS6502::GetWord(uint16_t offset, register16_t& output) {
void EightBit::MOS6502::Interrupt(uint16_t vector) {
PushWord(PC());
PushByte(p);
p.interrupt = true;
setFlag(P(), IF);
GetWord(vector, PC());
}
@ -426,13 +426,9 @@ void EightBit::MOS6502::DEC(uint16_t offset) {
}
uint8_t EightBit::MOS6502::ROR(uint8_t data) {
auto carry = p.carry;
auto result = (data >> 1) | ((P() & CF) << 7);
p.carry = (data & 1) != 0;
auto result = (uint8_t)(data >> 1);
if (carry)
result |= 0x80;
setFlag(P(), CF, data & CF);
UpdateZeroNegativeFlags(result);
@ -444,9 +440,9 @@ void EightBit::MOS6502::ROR(uint16_t offset) {
}
uint8_t EightBit::MOS6502::LSR(uint8_t data) {
p.carry = (data & 1) != 0;
auto result = data >> 1;
auto result = (uint8_t)(data >> 1);
setFlag(P(), CF, data & CF);
UpdateZeroNegativeFlags(result);
@ -464,22 +460,20 @@ void EightBit::MOS6502::BIT_immediate(uint8_t data) {
void EightBit::MOS6502::BIT(uint8_t data) {
BIT_immediate(data);
p.negative = (data & 0x80) != 0;
p.overflow = (data & 0x40) != 0;
UpdateNegativeFlag(data);
setFlag(P(), VF, data & VF);
}
void EightBit::MOS6502::TSB(uint16_t address) {
auto content = GetByte(address);
BIT_immediate(content);
uint8_t result = content | a;
SetByte(address, result);
SetByte(address, content | a);
}
void EightBit::MOS6502::TRB(uint16_t address) {
auto content = GetByte(address);
BIT_immediate(content);
uint8_t result = content & ~a;
SetByte(address, result);
SetByte(address, content & ~a);
}
void EightBit::MOS6502::INC(uint16_t offset) {
@ -493,14 +487,9 @@ void EightBit::MOS6502::ROL(uint16_t offset) {
}
uint8_t EightBit::MOS6502::ROL(uint8_t data) {
auto carry = p.carry;
uint8_t result = (data << 1) | (P() & CF);
p.carry = (data & 0x80) != 0;
uint8_t result = data << 1;
if (carry)
result |= 1;
setFlag(P(), CF, data & Bit7);
UpdateZeroNegativeFlags(result);
@ -514,42 +503,38 @@ void EightBit::MOS6502::ASL(uint16_t offset) {
uint8_t EightBit::MOS6502::ASL(uint8_t data) {
uint8_t result = data << 1;
UpdateZeroNegativeFlags(result);
p.carry = (data & 0x80) != 0;
setFlag(P(), CF, (data & 0x80) >> 7);
return result;
}
void EightBit::MOS6502::ORA(uint8_t data) {
a |= data;
UpdateZeroNegativeFlags(a);
UpdateZeroNegativeFlags(a |= data);
}
void EightBit::MOS6502::AND(uint8_t data) {
a &= data;
UpdateZeroNegativeFlags(a);
UpdateZeroNegativeFlags(a &= data);
}
void EightBit::MOS6502::SBC(uint8_t data) {
if (p.decimal)
if (P() & DF)
SBC_d(data);
else
SBC_b(data);
}
void EightBit::MOS6502::SBC_b(uint8_t data) {
auto carry = p.carry ? 0 : 1;
register16_t difference;
difference.word = a - data - carry;
difference.word = a - data - (~P() & CF);
UpdateZeroNegativeFlags(difference.low);
p.overflow = ((a ^ data) & (a ^ difference.low) & 0x80) != 0;
p.carry = difference.high == 0;
setFlag(P(), VF, (a ^ data) & (a ^ difference.low) & 0x80);
clearFlag(P(), CF, difference.high);
a = difference.low;
}
void EightBit::MOS6502::SBC_d(uint8_t data) {
auto carry = p.carry ? 0 : 1;
auto carry = ~P() & CF;
register16_t difference;
difference.word = a - data - carry;
@ -557,8 +542,8 @@ void EightBit::MOS6502::SBC_d(uint8_t data) {
if (level < ProcessorType::Cpu65SC02)
UpdateZeroNegativeFlags(difference.low);
p.overflow = ((a ^ data) & (a ^ difference.low) & 0x80) != 0;
p.carry = difference.high == 0;
setFlag(P(), VF, (a ^ data) & (a ^ difference.low) & 0x80);
clearFlag(P(), CF, difference.high);
auto low = (uint8_t)(lowNibble(a) - lowNibble(data) - carry);
@ -597,46 +582,42 @@ void EightBit::MOS6502::CMP(uint8_t first, uint8_t second) {
register16_t result;
result.word = first - second;
UpdateZeroNegativeFlags(result.low);
p.carry = result.high == 0;
clearFlag(P(), CF, result.high);
}
void EightBit::MOS6502::LDA(uint8_t data) {
a = data;
UpdateZeroNegativeFlags(a);
UpdateZeroNegativeFlags(a = data);
}
void EightBit::MOS6502::LDY(uint8_t data) {
y = data;
UpdateZeroNegativeFlags(y);
UpdateZeroNegativeFlags(y = data);
}
void EightBit::MOS6502::LDX(uint8_t data) {
x = data;
UpdateZeroNegativeFlags(x);
UpdateZeroNegativeFlags(x = data);
}
void EightBit::MOS6502::ADC(uint8_t data) {
if (p.decimal)
if (P() & DF)
ADC_d(data);
else
ADC_b(data);
}
void EightBit::MOS6502::ADC_b(uint8_t data) {
auto carry = (uint8_t)(p.carry ? 1 : 0);
register16_t sum;
sum.word = a + data + carry;
sum.word = a + data + (P() & CF);
UpdateZeroNegativeFlags(sum.low);
p.overflow = (~(a ^ data) & (a ^ sum.low) & 0x80) != 0;
p.carry = sum.high != 0;
setFlag(P(), VF, ~(a ^ data) & (a ^ sum.low) & 0x80);
setFlag(P(), CF, sum.high & CF);
a = sum.low;
}
void EightBit::MOS6502::ADC_d(uint8_t data) {
auto carry = (uint8_t)(p.carry ? 1 : 0);
auto carry = P() & CF;
register16_t sum;
sum.word = a + data + carry;
@ -649,12 +630,12 @@ void EightBit::MOS6502::ADC_d(uint8_t data) {
low += 6;
auto high = (uint8_t)(highNibble(a) + highNibble(data) + (low > 0xf ? 1 : 0));
p.overflow = (~(a ^ data) & (a ^ promoteNibble(high)) & 0x80) != 0;
setFlag(P(), VF, ~(a ^ data) & (a ^ promoteNibble(high)) & 0x80);
if (high > 9)
high += 6;
p.carry = high > 0xf;
setFlag(P(), CF, high > 0xf);
a = (uint8_t)(promoteNibble(high) | lowNibble(low));
if (level >= ProcessorType::Cpu65SC02)
@ -1281,13 +1262,13 @@ void EightBit::MOS6502::TXA_imp() {
//
void EightBit::MOS6502::PHP_imp() {
p.brk = true;
setFlag(P(), BF);
PushByte(p);
}
void EightBit::MOS6502::PLP_imp() {
p = PopByte();
p.reserved = true;
setFlag(P(), RF);
}
void EightBit::MOS6502::PLA_imp() {
@ -1607,9 +1588,9 @@ void EightBit::MOS6502::BRK_imp() {
PC().word++;
PushWord(PC());
PHP_imp();
p.interrupt = true;
setFlag(P(), IF);
if (level >= ProcessorType::Cpu65SC02)
p.decimal = false;
clearFlag(P(), DF);
GetWord(IRQvector, PC());
}
@ -1627,65 +1608,65 @@ void EightBit::MOS6502::STP_imp() {
//
void EightBit::MOS6502::SED_imp() {
p.decimal = true;
setFlag(P(), DF);
}
void EightBit::MOS6502::CLD_imp() {
p.decimal = false;
clearFlag(P(), DF);
}
void EightBit::MOS6502::CLV_imp() {
p.overflow = false;
clearFlag(P(), VF);
}
void EightBit::MOS6502::SEI_imp() {
p.interrupt = true;
setFlag(P(), IF);
}
void EightBit::MOS6502::CLI_imp() {
p.interrupt = false;
clearFlag(P(), IF);
}
void EightBit::MOS6502::CLC_imp() {
p.carry = false;
clearFlag(P(), CF);
}
void EightBit::MOS6502::SEC_imp() {
p.carry = true;
setFlag(P(), CF);
}
//
void EightBit::MOS6502::BMI_rel() {
Branch(p.negative);
Branch((P() & NF) != 0);
}
void EightBit::MOS6502::BPL_rel() {
Branch(!p.negative);
Branch(!(P() & NF));
}
void EightBit::MOS6502::BVC_rel() {
Branch(!p.overflow);
Branch(!(P() & VF));
}
void EightBit::MOS6502::BVS_rel() {
Branch(p.overflow);
Branch((P() & VF) != 0);
}
void EightBit::MOS6502::BCC_rel() {
Branch(!p.carry);
Branch(!(P() & CF));
}
void EightBit::MOS6502::BCS_rel() {
Branch(p.carry);
Branch((P() & CF) != 0);
}
void EightBit::MOS6502::BNE_rel() {
Branch(!p.zero);
Branch(!(P() & ZF));
}
void EightBit::MOS6502::BEQ_rel() {
Branch(p.zero);
Branch((P() & ZF) != 0);
}
void EightBit::MOS6502::BRA_rel() {

View File

@ -82,7 +82,7 @@ void Board::Cpu_ExecutingInstruction_Debug(const EightBit::MOS6502& cpu) {
std::cout << std::hex;
std::cout << "PC=" << std::setw(4) << std::setfill('0') << address << ":";
std::cout << "P=" << (std::string)m_cpu.P() << ", ";
std::cout << "P=" << m_disassembler.Dump_Flags(m_cpu.P()) << ", ";
std::cout << std::setw(2) << std::setfill('0');
std::cout << "A=" << (int)m_cpu.A() << ", ";
std::cout << "X=" << (int)m_cpu.X() << ", ";