Undocumented instruction: DCP added

Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon 2018-01-01 21:05:42 +00:00
parent 5f54f61514
commit 345ab2e2c6
6 changed files with 151 additions and 35 deletions

View File

@ -59,6 +59,10 @@ namespace EightBit {
return AM_11_dump(bbb) + "\t" + instruction + " " + AM_11(bbb);
}
std::string disassemble_AM_11_x(int bbb, const std::string& instruction) const {
return AM_11_x_dump(bbb) + "\t" + instruction + " " + AM_11_x(bbb);
}
std::string AM_Immediate_dump() const {
return dump_Byte(m_address + 1);
}
@ -72,7 +76,7 @@ namespace EightBit {
}
std::string AM_Absolute() const {
return "$" + dump_WordValue(processor.BUS().peekWord(m_address + 1));
return "$" + dump_Word(m_address + 1);
}
std::string AM_ZeroPage_dump() const {
@ -330,6 +334,29 @@ namespace EightBit {
}
}
std::string AM_11_x_dump(int bbb) const {
switch (bbb) {
case 0b000:
return AM_IndexedIndirectX_dump();
case 0b001:
return AM_ZeroPage_dump();
case 0b010:
return AM_Immediate_dump();
case 0b011:
return AM_Absolute_dump();
case 0b100:
return AM_IndirectIndexedY_dump();
case 0b101:
return AM_ZeroPageX_dump();
case 0b110:
return AM_AbsoluteY_dump();
case 0b111:
return AM_AbsoluteX_dump();
default:
UNREACHABLE;
}
}
std::string AM_11(int bbb) const {
switch (bbb) {
case 0b000:
@ -353,12 +380,37 @@ namespace EightBit {
}
}
std::string AM_11_x(int bbb) const {
switch (bbb) {
case 0b000:
return AM_IndexedIndirectX();
case 0b001:
return AM_ZeroPage();
case 0b010:
return AM_Immediate();
case 0b011:
return AM_Absolute();
case 0b100:
return AM_IndirectIndexedY();
case 0b101:
return AM_ZeroPageX();
case 0b110:
return AM_AbsoluteY();
case 0b111:
return AM_AbsoluteX();
default:
UNREACHABLE;
}
}
static void dump(std::ostream& out, int value, int width);
uint8_t getByte(uint16_t address) const;
uint16_t getWord(uint16_t address) const;
std::string dump_Byte(uint16_t address) const;
std::string dump_DByte(uint16_t address) const;
std::string dump_Word(uint16_t address) const;
std::string convertAddress(uint16_t address) const;
std::string convertAddress(uint8_t address) const;

View File

@ -56,9 +56,10 @@ namespace EightBit {
protected:
virtual void reset() final;
virtual void SBC(uint8_t data);
void SBC_b(uint8_t data);
void SBC_d(uint8_t data);
virtual uint8_t SUB(uint8_t operand, uint8_t data, int borrow = 0);
uint8_t SBC(uint8_t operand, uint8_t data);
uint8_t SUB_b(uint8_t operand, uint8_t data, int borrow);
uint8_t SUB_d(uint8_t operand, uint8_t data, int borrow);
virtual void ADC(uint8_t data);
void ADC_b(uint8_t data);
@ -484,6 +485,58 @@ namespace EightBit {
}
}
uint8_t AM_11_x(int bbb) {
switch (bbb) {
case 0b000:
return AM_IndexedIndirectX();
case 0b001:
return AM_ZeroPage();
case 0b010:
return AM_Immediate();
case 0b011:
return AM_Absolute();
case 0b100:
return AM_IndirectIndexedY();
case 0b101:
return AM_ZeroPageX();
case 0b110:
return AM_AbsoluteY();
case 0b111:
return AM_AbsoluteX();
default:
UNREACHABLE;
}
}
void AM_11_x(int bbb, uint8_t value) {
switch (bbb) {
case 0b000:
AM_IndexedIndirectX(value);
break;
case 0b001:
AM_ZeroPage(value);
break;
case 0b010:
throw std::domain_error("Illegal addressing mode");
case 0b011:
AM_Absolute(value);
break;
case 0b100:
AM_IndirectIndexedY(value);
break;
case 0b101:
AM_ZeroPageX(value);
break;
case 0b110:
AM_AbsoluteY(value);
case 0b111:
AM_AbsoluteX(value);
break;
default:
UNREACHABLE;
}
}
// Operations
void ASL(int bbb) {

View File

@ -395,6 +395,9 @@ std::string EightBit::Disassembly::disassemble(uint16_t current) const {
case 0b101:
output << disassemble_AM_11(bbb, "*LAX");
break;
case 0b110:
output << disassemble_AM_11_x(bbb, "*DCP");
break;
case 0b111:
output << disassemble_AM_11(bbb, "*SBC");
break;
@ -427,6 +430,10 @@ uint8_t EightBit::Disassembly::getByte(uint16_t address) const {
return processor.BUS().peek(address);
}
uint16_t EightBit::Disassembly::getWord(uint16_t address) const {
return processor.BUS().peekWord(address);
}
////
std::string EightBit::Disassembly::dump_Byte(uint16_t address) const {
@ -437,6 +444,10 @@ std::string EightBit::Disassembly::dump_DByte(uint16_t address) const {
return dump_Byte(address) + " " + dump_Byte(address + 1);
}
std::string EightBit::Disassembly::dump_Word(uint16_t address) const {
return dump_WordValue(getWord(address));
}
////
std::string EightBit::Disassembly::convertAddress(uint16_t address) const {

View File

@ -17,8 +17,8 @@ EightBit::MOS6502::MOS6502(Bus& bus)
/* 9 */ 2, 6, 0, 0, 4, 4, 4, 4, 2, 5, 2, 0, 0, 5, 0, 0,
/* A */ 2, 6, 2, 6, 3, 3, 3, 3, 2, 2, 2, 0, 4, 4, 4, 4,
/* B */ 2, 5, 0, 5, 4, 4, 4, 4, 2, 4, 2, 0, 4, 4, 4, 4,
/* C */ 2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 0, 4, 4, 6, 0,
/* D */ 2, 5, 0, 0, 4, 4, 6, 0, 2, 4, 2, 0, 4, 4, 7, 0,
/* C */ 2, 6, 0, 8, 3, 3, 5, 5, 2, 2, 2, 0, 4, 4, 6, 6,
/* D */ 2, 5, 0, 7, 4, 4, 6, 6, 2, 4, 2, 6, 4, 4, 7, 6,
/* E */ 2, 6, 0, 0, 3, 3, 5, 0, 2, 2, 2, 2, 4, 4, 6, 0,
/* F */ 2, 5, 0, 0, 4, 4, 6, 0, 2, 4, 2, 0, 4, 4, 7, 0,
};
@ -315,7 +315,7 @@ int EightBit::MOS6502::execute(uint8_t cell) {
CMP(A(), AM_01(decoded.bbb));
break;
case 0b111: // SBC
SBC(AM_01(decoded.bbb));
A() = SBC(A(), AM_01(decoded.bbb));
break;
default:
UNREACHABLE;
@ -417,8 +417,15 @@ int EightBit::MOS6502::execute(uint8_t cell) {
case 0b101: // *LAX
adjustNZ(X() = A() = AM_11(decoded.bbb));
break;
case 0b110: { // *DCP
const auto operand = AM_11_x(decoded.bbb);
const auto result = SUB(operand, 1);
setByte(result);
CMP(A(), result);
}
break;
case 0b111: // *SBC
SBC(AM_11(decoded.bbb));
A() = SBC(A(), AM_11(decoded.bbb));
break;
default:
throw std::domain_error("Illegal instruction group");
@ -475,47 +482,40 @@ void EightBit::MOS6502::ASL(uint8_t& output) {
adjustNZ(output <<= 1);
}
void EightBit::MOS6502::SBC(uint8_t data) {
if (P() & DF)
SBC_d(data);
else
SBC_b(data);
}
uint8_t EightBit::MOS6502::SBC(const uint8_t operand, const uint8_t data) {
void EightBit::MOS6502::SBC_b(uint8_t data) {
register16_t difference;
difference.word = A() - data - (~P() & CF);
const auto returned = SUB(operand, data, ~P() & CF);
const register16_t& difference = MEMPTR();
adjustNZ(difference.low);
setFlag(P(), VF, (A() ^ data) & (A() ^ difference.low) & NF);
setFlag(P(), VF, (operand ^ data) & (operand ^ difference.low) & NF);
clearFlag(P(), CF, difference.high);
A() = difference.low;
return returned;
}
void EightBit::MOS6502::SBC_d(uint8_t data) {
auto carry = ~P() & CF;
uint8_t EightBit::MOS6502::SUB(const uint8_t operand, const uint8_t data, const int borrow) {
return P() & DF ? SUB_d(operand, data, borrow) : SUB_b(operand, data, borrow);
}
register16_t difference;
difference.word = A() - data - carry;
uint8_t EightBit::MOS6502::SUB_b(const uint8_t operand, const uint8_t data, const int borrow) {
MEMPTR().word = operand - data - borrow;
return MEMPTR().low;
}
adjustNZ(difference.low);
setFlag(P(), VF, (A() ^ data) & (A() ^ difference.low) & NF);
clearFlag(P(), CF, difference.high);
auto low = (uint8_t)(lowNibble(A()) - lowNibble(data) - carry);
uint8_t EightBit::MOS6502::SUB_d(const uint8_t operand, const uint8_t data, const int borrow) {
MEMPTR().word = operand - data - borrow;
auto low = (uint8_t)(lowNibble(operand) - lowNibble(data) - borrow);
auto lowNegative = (int8_t)low < 0;
if (lowNegative)
low -= 6;
uint8_t high = highNibble(A()) - highNibble(data) - (lowNegative ? 1 : 0);
uint8_t high = highNibble(operand) - highNibble(data) - (lowNegative ? 1 : 0);
if ((int8_t)high < 0)
high -= 6;
A() = promoteNibble(high) | lowNibble(low);
return promoteNibble(high) | lowNibble(low);
}
void EightBit::MOS6502::CMP(uint8_t first, uint8_t second) {

View File

@ -13,7 +13,7 @@ namespace EightBit {
int clockCycles() const { return cycles(); }
protected:
virtual void SBC(uint8_t data) final;
virtual uint8_t SUB(uint8_t operand, uint8_t data, int borrow) final;
virtual void ADC(uint8_t data) final;
};
}

View File

@ -5,8 +5,8 @@ EightBit::Ricoh2A03::Ricoh2A03(Bus& bus)
: MOS6502(bus) {
}
void EightBit::Ricoh2A03::SBC(uint8_t data) {
MOS6502::SBC_b(data);
uint8_t EightBit::Ricoh2A03::SUB(uint8_t operand, uint8_t data, int borrow) {
return MOS6502::SUB_b(operand ,data, borrow);
}
void EightBit::Ricoh2A03::ADC(uint8_t data) {