mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-01-21 21:30:31 +00:00
Undocumented instruction: DCP added
Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
parent
5f54f61514
commit
345ab2e2c6
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user