mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2025-02-01 16:31:42 +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);
|
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 {
|
std::string AM_Immediate_dump() const {
|
||||||
return dump_Byte(m_address + 1);
|
return dump_Byte(m_address + 1);
|
||||||
}
|
}
|
||||||
@ -72,7 +76,7 @@ namespace EightBit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string AM_Absolute() const {
|
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 {
|
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 {
|
std::string AM_11(int bbb) const {
|
||||||
switch (bbb) {
|
switch (bbb) {
|
||||||
case 0b000:
|
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);
|
static void dump(std::ostream& out, int value, int width);
|
||||||
|
|
||||||
uint8_t getByte(uint16_t address) const;
|
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_Byte(uint16_t address) const;
|
||||||
std::string dump_DByte(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(uint16_t address) const;
|
||||||
std::string convertAddress(uint8_t address) const;
|
std::string convertAddress(uint8_t address) const;
|
||||||
|
@ -56,9 +56,10 @@ namespace EightBit {
|
|||||||
protected:
|
protected:
|
||||||
virtual void reset() final;
|
virtual void reset() final;
|
||||||
|
|
||||||
virtual void SBC(uint8_t data);
|
virtual uint8_t SUB(uint8_t operand, uint8_t data, int borrow = 0);
|
||||||
void SBC_b(uint8_t data);
|
uint8_t SBC(uint8_t operand, uint8_t data);
|
||||||
void SBC_d(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);
|
virtual void ADC(uint8_t data);
|
||||||
void ADC_b(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
|
// Operations
|
||||||
|
|
||||||
void ASL(int bbb) {
|
void ASL(int bbb) {
|
||||||
|
@ -395,6 +395,9 @@ std::string EightBit::Disassembly::disassemble(uint16_t current) const {
|
|||||||
case 0b101:
|
case 0b101:
|
||||||
output << disassemble_AM_11(bbb, "*LAX");
|
output << disassemble_AM_11(bbb, "*LAX");
|
||||||
break;
|
break;
|
||||||
|
case 0b110:
|
||||||
|
output << disassemble_AM_11_x(bbb, "*DCP");
|
||||||
|
break;
|
||||||
case 0b111:
|
case 0b111:
|
||||||
output << disassemble_AM_11(bbb, "*SBC");
|
output << disassemble_AM_11(bbb, "*SBC");
|
||||||
break;
|
break;
|
||||||
@ -427,6 +430,10 @@ uint8_t EightBit::Disassembly::getByte(uint16_t address) const {
|
|||||||
return processor.BUS().peek(address);
|
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 {
|
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);
|
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 {
|
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,
|
/* 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,
|
/* 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,
|
/* 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,
|
/* C */ 2, 6, 0, 8, 3, 3, 5, 5, 2, 2, 2, 0, 4, 4, 6, 6,
|
||||||
/* D */ 2, 5, 0, 0, 4, 4, 6, 0, 2, 4, 2, 0, 4, 4, 7, 0,
|
/* 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,
|
/* 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,
|
/* 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));
|
CMP(A(), AM_01(decoded.bbb));
|
||||||
break;
|
break;
|
||||||
case 0b111: // SBC
|
case 0b111: // SBC
|
||||||
SBC(AM_01(decoded.bbb));
|
A() = SBC(A(), AM_01(decoded.bbb));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE;
|
UNREACHABLE;
|
||||||
@ -417,8 +417,15 @@ int EightBit::MOS6502::execute(uint8_t cell) {
|
|||||||
case 0b101: // *LAX
|
case 0b101: // *LAX
|
||||||
adjustNZ(X() = A() = AM_11(decoded.bbb));
|
adjustNZ(X() = A() = AM_11(decoded.bbb));
|
||||||
break;
|
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
|
case 0b111: // *SBC
|
||||||
SBC(AM_11(decoded.bbb));
|
A() = SBC(A(), AM_11(decoded.bbb));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::domain_error("Illegal instruction group");
|
throw std::domain_error("Illegal instruction group");
|
||||||
@ -475,47 +482,40 @@ void EightBit::MOS6502::ASL(uint8_t& output) {
|
|||||||
adjustNZ(output <<= 1);
|
adjustNZ(output <<= 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::MOS6502::SBC(uint8_t data) {
|
uint8_t EightBit::MOS6502::SBC(const uint8_t operand, const uint8_t data) {
|
||||||
if (P() & DF)
|
|
||||||
SBC_d(data);
|
|
||||||
else
|
|
||||||
SBC_b(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void EightBit::MOS6502::SBC_b(uint8_t data) {
|
const auto returned = SUB(operand, data, ~P() & CF);
|
||||||
register16_t difference;
|
|
||||||
difference.word = A() - data - (~P() & CF);
|
|
||||||
|
|
||||||
|
const register16_t& difference = MEMPTR();
|
||||||
adjustNZ(difference.low);
|
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);
|
clearFlag(P(), CF, difference.high);
|
||||||
|
|
||||||
A() = difference.low;
|
return returned;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::MOS6502::SBC_d(uint8_t data) {
|
uint8_t EightBit::MOS6502::SUB(const uint8_t operand, const uint8_t data, const int borrow) {
|
||||||
auto carry = ~P() & CF;
|
return P() & DF ? SUB_d(operand, data, borrow) : SUB_b(operand, data, borrow);
|
||||||
|
}
|
||||||
|
|
||||||
register16_t difference;
|
uint8_t EightBit::MOS6502::SUB_b(const uint8_t operand, const uint8_t data, const int borrow) {
|
||||||
difference.word = A() - data - carry;
|
MEMPTR().word = operand - data - borrow;
|
||||||
|
return MEMPTR().low;
|
||||||
|
}
|
||||||
|
|
||||||
adjustNZ(difference.low);
|
uint8_t EightBit::MOS6502::SUB_d(const uint8_t operand, const uint8_t data, const int borrow) {
|
||||||
|
MEMPTR().word = operand - data - borrow;
|
||||||
setFlag(P(), VF, (A() ^ data) & (A() ^ difference.low) & NF);
|
|
||||||
clearFlag(P(), CF, difference.high);
|
|
||||||
|
|
||||||
auto low = (uint8_t)(lowNibble(A()) - lowNibble(data) - carry);
|
|
||||||
|
|
||||||
|
auto low = (uint8_t)(lowNibble(operand) - lowNibble(data) - borrow);
|
||||||
auto lowNegative = (int8_t)low < 0;
|
auto lowNegative = (int8_t)low < 0;
|
||||||
if (lowNegative)
|
if (lowNegative)
|
||||||
low -= 6;
|
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)
|
if ((int8_t)high < 0)
|
||||||
high -= 6;
|
high -= 6;
|
||||||
|
|
||||||
A() = promoteNibble(high) | lowNibble(low);
|
return promoteNibble(high) | lowNibble(low);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::MOS6502::CMP(uint8_t first, uint8_t second) {
|
void EightBit::MOS6502::CMP(uint8_t first, uint8_t second) {
|
||||||
|
@ -13,7 +13,7 @@ namespace EightBit {
|
|||||||
int clockCycles() const { return cycles(); }
|
int clockCycles() const { return cycles(); }
|
||||||
|
|
||||||
protected:
|
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;
|
virtual void ADC(uint8_t data) final;
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -5,8 +5,8 @@ EightBit::Ricoh2A03::Ricoh2A03(Bus& bus)
|
|||||||
: MOS6502(bus) {
|
: MOS6502(bus) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::Ricoh2A03::SBC(uint8_t data) {
|
uint8_t EightBit::Ricoh2A03::SUB(uint8_t operand, uint8_t data, int borrow) {
|
||||||
MOS6502::SBC_b(data);
|
return MOS6502::SUB_b(operand ,data, borrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EightBit::Ricoh2A03::ADC(uint8_t data) {
|
void EightBit::Ricoh2A03::ADC(uint8_t data) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user