Add cpu idling and int checks to instructions, refactor branching
This commit is contained in:
@@ -27,24 +27,6 @@ void Spc700::Reset(bool hard) {
|
|||||||
reset_wanted_ = true;
|
reset_wanted_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Spc700::BootIplRom() {
|
|
||||||
PC = 0xFFC0;
|
|
||||||
A = 0;
|
|
||||||
X = 0;
|
|
||||||
Y = 0;
|
|
||||||
int i = 0;
|
|
||||||
while (PC != 0xFFC0 + 0x3F) {
|
|
||||||
uint8_t opcode = read(PC);
|
|
||||||
ExecuteInstructions(opcode);
|
|
||||||
PC++;
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if (i > 1000) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Spc700::RunOpcode() {
|
void Spc700::RunOpcode() {
|
||||||
if (reset_wanted_) {
|
if (reset_wanted_) {
|
||||||
// based on 6502, brk without writes
|
// based on 6502, brk without writes
|
||||||
|
|||||||
@@ -130,8 +130,6 @@ class Spc700 {
|
|||||||
|
|
||||||
void Reset(bool hard = false);
|
void Reset(bool hard = false);
|
||||||
|
|
||||||
void BootIplRom();
|
|
||||||
|
|
||||||
void RunOpcode();
|
void RunOpcode();
|
||||||
|
|
||||||
void ExecuteInstructions(uint8_t opcode);
|
void ExecuteInstructions(uint8_t opcode);
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ void Cpu::RunOpcode() {
|
|||||||
|
|
||||||
SetSP(sp);
|
SetSP(sp);
|
||||||
|
|
||||||
SetInterruptFlag(true);
|
E = 1;
|
||||||
SetInterruptFlag(true);
|
SetInterruptFlag(true);
|
||||||
SetDecimalFlag(false);
|
SetDecimalFlag(false);
|
||||||
SetFlags(status); // updates x and m flags, clears
|
SetFlags(status); // updates x and m flags, clears
|
||||||
@@ -346,21 +346,21 @@ void Cpu::ExecuteInstruction(uint8_t opcode) {
|
|||||||
case 0x90: // BCC Branch if carry clear
|
case 0x90: // BCC Branch if carry clear
|
||||||
{
|
{
|
||||||
operand = FetchByte();
|
operand = FetchByte();
|
||||||
BCC(operand);
|
DoBranch(!GetCarryFlag());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xB0: // BCS Branch if carry set
|
case 0xB0: // BCS Branch if carry set
|
||||||
{
|
{
|
||||||
operand = FetchByte();
|
operand = FetchByte();
|
||||||
BCS(operand);
|
DoBranch(GetCarryFlag());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xF0: // BEQ Branch if equal (zero set)
|
case 0xF0: // BEQ Branch if equal (zero set)
|
||||||
{
|
{
|
||||||
operand = FetchByte();
|
operand = FetchByte();
|
||||||
BEQ(operand);
|
DoBranch(GetZeroFlag());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,29 +398,27 @@ void Cpu::ExecuteInstruction(uint8_t opcode) {
|
|||||||
|
|
||||||
case 0x30: // BMI Branch if minus (negative set)
|
case 0x30: // BMI Branch if minus (negative set)
|
||||||
{
|
{
|
||||||
operand = FetchByte();
|
DoBranch(GetNegativeFlag());
|
||||||
BMI(operand);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xD0: // BNE Branch if not equal (zero clear)
|
case 0xD0: // BNE Branch if not equal (zero clear)
|
||||||
{
|
{
|
||||||
operand = FetchSignedByte();
|
DoBranch(!GetZeroFlag());
|
||||||
BNE(operand);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x10: // BPL Branch if plus (negative clear)
|
case 0x10: // BPL Branch if plus (negative clear)
|
||||||
{
|
{
|
||||||
operand = FetchSignedByte();
|
operand = FetchByte();
|
||||||
BPL(operand);
|
DoBranch(!GetNegativeFlag());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x80: // BRA Branch always
|
case 0x80: // BRA Branch always
|
||||||
{
|
{
|
||||||
operand = FetchByte();
|
operand = FetchByte();
|
||||||
BRA(operand);
|
DoBranch(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,7 +429,7 @@ void Cpu::ExecuteInstruction(uint8_t opcode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 0x82: // BRL Branch always long
|
case 0x82: // BRL Branch always long
|
||||||
{ // operand = FetchSignedWord();
|
{
|
||||||
operand = FetchWord();
|
operand = FetchWord();
|
||||||
BRL(operand);
|
BRL(operand);
|
||||||
break;
|
break;
|
||||||
@@ -440,14 +438,14 @@ void Cpu::ExecuteInstruction(uint8_t opcode) {
|
|||||||
case 0x50: // BVC Branch if overflow clear
|
case 0x50: // BVC Branch if overflow clear
|
||||||
{
|
{
|
||||||
operand = FetchByte();
|
operand = FetchByte();
|
||||||
BVC(operand);
|
DoBranch(!GetOverflowFlag());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x70: // BVS Branch if overflow set
|
case 0x70: // BVS Branch if overflow set
|
||||||
{
|
{
|
||||||
operand = FetchByte();
|
operand = FetchByte();
|
||||||
BVS(operand);
|
DoBranch(GetOverflowFlag());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -796,7 +794,7 @@ void Cpu::ExecuteInstruction(uint8_t opcode) {
|
|||||||
}
|
}
|
||||||
case 0x5C: // JMP Absolute Long
|
case 0x5C: // JMP Absolute Long
|
||||||
{
|
{
|
||||||
JML(AbsoluteLong());
|
JML(FetchWord());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x6C: // JMP Absolute Indirect
|
case 0x6C: // JMP Absolute Indirect
|
||||||
@@ -827,7 +825,7 @@ void Cpu::ExecuteInstruction(uint8_t opcode) {
|
|||||||
|
|
||||||
case 0x22: // JSL Absolute Long
|
case 0x22: // JSL Absolute Long
|
||||||
{
|
{
|
||||||
JSL(AbsoluteLong());
|
JSL(FetchWord());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1023,8 +1021,16 @@ void Cpu::ExecuteInstruction(uint8_t opcode) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 0x42:
|
||||||
|
WDM();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x44:
|
||||||
|
MVP();
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x54:
|
case 0x54:
|
||||||
// MVN();
|
MVN();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xEA: // NOP
|
case 0xEA: // NOP
|
||||||
@@ -1604,14 +1610,12 @@ uint8_t Cpu::GetInstructionLength(uint8_t opcode) {
|
|||||||
case 0x00: // BRK
|
case 0x00: // BRK
|
||||||
case 0x02: // COP
|
case 0x02: // COP
|
||||||
PC = next_pc_;
|
PC = next_pc_;
|
||||||
|
PB = next_pb_;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// TODO: Handle JMPs in logging.
|
|
||||||
case 0x20: // JSR Absolute
|
case 0x20: // JSR Absolute
|
||||||
case 0x4C: // JMP Absolute
|
case 0x4C: // JMP Absolute
|
||||||
case 0x6C: // JMP Absolute Indirect
|
case 0x6C: // JMP Absolute Indirect
|
||||||
case 0x5C: // JMP Absolute Indexed Indirect
|
|
||||||
case 0x22: // JSL Absolute Long
|
|
||||||
case 0x7C: // JMP Absolute Indexed Indirect
|
case 0x7C: // JMP Absolute Indexed Indirect
|
||||||
case 0xFC: // JSR Absolute Indexed Indirect
|
case 0xFC: // JSR Absolute Indexed Indirect
|
||||||
case 0xDC: // JMP Absolute Indirect Long
|
case 0xDC: // JMP Absolute Indirect Long
|
||||||
@@ -1620,6 +1624,12 @@ uint8_t Cpu::GetInstructionLength(uint8_t opcode) {
|
|||||||
PC = next_pc_;
|
PC = next_pc_;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case 0x22: // JSL Absolute Long
|
||||||
|
case 0x5C: // JMP Absolute Indexed Indirect
|
||||||
|
PC = next_pc_;
|
||||||
|
PB = next_pb_;
|
||||||
|
return 0;
|
||||||
|
|
||||||
case 0x80: // BRA Relative
|
case 0x80: // BRA Relative
|
||||||
PC += next_pc_;
|
PC += next_pc_;
|
||||||
return 2;
|
return 2;
|
||||||
|
|||||||
@@ -250,6 +250,16 @@ class Cpu : public Loggable, public core::ExperimentFlags {
|
|||||||
return (high << 16) | low;
|
return (high << 16) | low;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DoBranch(bool check) {
|
||||||
|
if (!check) CheckInt();
|
||||||
|
uint8_t value = FetchByte();
|
||||||
|
if (check) {
|
||||||
|
CheckInt();
|
||||||
|
callbacks_.idle(false); // taken branch: 1 extra cycle
|
||||||
|
next_pc_ += (int8_t)value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Addressing Modes
|
// Addressing Modes
|
||||||
|
|
||||||
@@ -519,13 +529,13 @@ class Cpu : public Loggable, public core::ExperimentFlags {
|
|||||||
void JMP(uint16_t address);
|
void JMP(uint16_t address);
|
||||||
|
|
||||||
// JML: Jump long
|
// JML: Jump long
|
||||||
void JML(uint32_t address);
|
void JML(uint16_t address);
|
||||||
|
|
||||||
// JSR: Jump to subroutine
|
// JSR: Jump to subroutine
|
||||||
void JSR(uint16_t address);
|
void JSR(uint16_t address);
|
||||||
|
|
||||||
// JSL: Jump to subroutine long
|
// JSL: Jump to subroutine long
|
||||||
void JSL(uint32_t address);
|
void JSL(uint16_t address);
|
||||||
|
|
||||||
// LDA: Load accumulator
|
// LDA: Load accumulator
|
||||||
void LDA(uint16_t address, bool immediate = false, bool direct_page = false,
|
void LDA(uint16_t address, bool immediate = false, bool direct_page = false,
|
||||||
@@ -541,10 +551,10 @@ class Cpu : public Loggable, public core::ExperimentFlags {
|
|||||||
void LSR(uint16_t address, bool accumulator = false);
|
void LSR(uint16_t address, bool accumulator = false);
|
||||||
|
|
||||||
// MVN: Block move next
|
// MVN: Block move next
|
||||||
void MVN(uint16_t source, uint16_t dest, uint16_t length);
|
void MVN();
|
||||||
|
|
||||||
// MVP: Block move previous
|
// MVP: Block move previous
|
||||||
void MVP(uint16_t source, uint16_t dest, uint16_t length);
|
void MVP();
|
||||||
|
|
||||||
// NOP: No operation
|
// NOP: No operation
|
||||||
void NOP();
|
void NOP();
|
||||||
@@ -769,6 +779,7 @@ class Cpu : public Loggable, public core::ExperimentFlags {
|
|||||||
|
|
||||||
uint16_t last_call_frame_;
|
uint16_t last_call_frame_;
|
||||||
uint16_t next_pc_;
|
uint16_t next_pc_;
|
||||||
|
uint8_t next_pb_;
|
||||||
|
|
||||||
memory::CpuCallbacks callbacks_;
|
memory::CpuCallbacks callbacks_;
|
||||||
memory::Memory& memory;
|
memory::Memory& memory;
|
||||||
|
|||||||
@@ -10,13 +10,12 @@ namespace emu {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 65816 Instruction Set
|
* 65816 Instruction Set
|
||||||
*
|
|
||||||
* TODO: STP, WDM
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Cpu::ADC(uint16_t operand) {
|
void Cpu::ADC(uint16_t operand) {
|
||||||
bool C = GetCarryFlag();
|
bool C = GetCarryFlag();
|
||||||
if (GetAccumulatorSize()) { // 8-bit mode
|
if (GetAccumulatorSize()) { // 8-bit mode
|
||||||
|
CheckInt();
|
||||||
uint16_t result = static_cast<uint16_t>(A & 0xFF) +
|
uint16_t result = static_cast<uint16_t>(A & 0xFF) +
|
||||||
static_cast<uint16_t>(operand) + (C ? 1 : 0);
|
static_cast<uint16_t>(operand) + (C ? 1 : 0);
|
||||||
SetCarryFlag(result > 0xFF); // Update the carry flag
|
SetCarryFlag(result > 0xFF); // Update the carry flag
|
||||||
@@ -50,6 +49,7 @@ void Cpu::ADC(uint16_t operand) {
|
|||||||
void Cpu::AND(uint32_t value, bool isImmediate) {
|
void Cpu::AND(uint32_t value, bool isImmediate) {
|
||||||
uint16_t operand;
|
uint16_t operand;
|
||||||
if (GetAccumulatorSize()) { // 8-bit mode
|
if (GetAccumulatorSize()) { // 8-bit mode
|
||||||
|
CheckInt();
|
||||||
operand = isImmediate ? value : ReadByte(value);
|
operand = isImmediate ? value : ReadByte(value);
|
||||||
A &= operand;
|
A &= operand;
|
||||||
SetZeroFlag(A == 0);
|
SetZeroFlag(A == 0);
|
||||||
@@ -71,13 +71,24 @@ void Cpu::ANDAbsoluteLong(uint32_t address) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::ASL(uint16_t address) {
|
void Cpu::ASL(uint16_t address) {
|
||||||
uint8_t value = ReadByte(address);
|
if (GetAccumulatorSize()) { // 8-bit mode
|
||||||
SetCarryFlag(!(value & 0x80)); // Set carry flag if bit 7 is set
|
uint8_t value = ReadByte(address);
|
||||||
value <<= 1; // Shift left
|
callbacks_.idle(false);
|
||||||
value &= 0xFE; // Clear bit 0
|
SetCarryFlag(value & 0x80);
|
||||||
WriteByte(address, value);
|
value <<= 1;
|
||||||
SetNegativeFlag(!value);
|
CheckInt();
|
||||||
SetZeroFlag(value);
|
WriteByte(address, value);
|
||||||
|
SetZeroFlag(value == 0);
|
||||||
|
SetNegativeFlag(value & 0x80);
|
||||||
|
} else { // 16-bit mode
|
||||||
|
uint16_t value = ReadWord(address);
|
||||||
|
callbacks_.idle(false);
|
||||||
|
SetCarryFlag(value & 0x8000);
|
||||||
|
value <<= 1;
|
||||||
|
WriteWord(address, value);
|
||||||
|
SetZeroFlag(value == 0);
|
||||||
|
SetNegativeFlag(value & 0x8000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::BCC(int8_t offset) {
|
void Cpu::BCC(int8_t offset) {
|
||||||
@@ -99,6 +110,7 @@ void Cpu::BEQ(int8_t offset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::BIT(uint16_t address) {
|
void Cpu::BIT(uint16_t address) {
|
||||||
|
CheckInt();
|
||||||
uint8_t value = ReadByte(address);
|
uint8_t value = ReadByte(address);
|
||||||
SetNegativeFlag(value & 0x80);
|
SetNegativeFlag(value & 0x80);
|
||||||
SetOverflowFlag(value & 0x40);
|
SetOverflowFlag(value & 0x40);
|
||||||
@@ -107,39 +119,43 @@ void Cpu::BIT(uint16_t address) {
|
|||||||
|
|
||||||
void Cpu::BMI(int8_t offset) {
|
void Cpu::BMI(int8_t offset) {
|
||||||
if (GetNegativeFlag()) { // If the negative flag is set
|
if (GetNegativeFlag()) { // If the negative flag is set
|
||||||
next_pc_ = offset;
|
next_pc_ = PC + offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::BNE(int8_t offset) {
|
void Cpu::BNE(int8_t offset) {
|
||||||
if (!GetZeroFlag()) { // If the zero flag is clear
|
if (!GetZeroFlag()) { // If the zero flag is clear
|
||||||
// PC += offset;
|
// PC += offset;
|
||||||
next_pc_ = offset;
|
next_pc_ = PC + offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::BPL(int8_t offset) {
|
void Cpu::BPL(int8_t offset) {
|
||||||
if (!GetNegativeFlag()) { // If the negative flag is clear
|
if (!GetNegativeFlag()) { // If the negative flag is clear
|
||||||
next_pc_ = offset;
|
next_pc_ = PC + offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::BRA(int8_t offset) { next_pc_ = offset; }
|
void Cpu::BRA(int8_t offset) { next_pc_ = PC + offset; }
|
||||||
|
|
||||||
void Cpu::BRK() {
|
void Cpu::BRK() {
|
||||||
// ReadOpcode();
|
// ReadOpcode();
|
||||||
next_pc_ += 2; // Increment the program counter by 2
|
next_pc_ = PC + 2; // Increment the program counter by 2
|
||||||
ReadByte(PC); // Read the next byte
|
ReadByte(PC); // Read the next byte
|
||||||
PushByte(PB);
|
PushByte(PB);
|
||||||
PushByte(PC); // ,false
|
PushByte(PC); // ,false
|
||||||
PushByte(status);
|
PushByte(status);
|
||||||
SetInterruptFlag(true);
|
SetInterruptFlag(true);
|
||||||
SetDecimalFlag(false);
|
SetDecimalFlag(false);
|
||||||
PB = 0;
|
next_pb_ = 0;
|
||||||
PC = ReadWord(0xFFE6); // ,true
|
next_pc_ = ReadWord(0xFFE6); // ,true
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::BRL(int16_t offset) { next_pc_ = offset; }
|
void Cpu::BRL(int16_t offset) {
|
||||||
|
next_pc_ = PC + offset;
|
||||||
|
CheckInt();
|
||||||
|
callbacks_.idle(false);
|
||||||
|
}
|
||||||
|
|
||||||
void Cpu::BVC(int8_t offset) {
|
void Cpu::BVC(int8_t offset) {
|
||||||
if (!GetOverflowFlag()) { // If the overflow flag is clear
|
if (!GetOverflowFlag()) { // If the overflow flag is clear
|
||||||
@@ -153,19 +169,32 @@ void Cpu::BVS(int8_t offset) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::CLC() { status &= ~0x01; }
|
void Cpu::CLC() {
|
||||||
|
AdrImp();
|
||||||
|
status &= ~0x01;
|
||||||
|
}
|
||||||
|
|
||||||
void Cpu::CLD() { status &= ~0x08; }
|
void Cpu::CLD() {
|
||||||
|
AdrImp();
|
||||||
|
status &= ~0x08;
|
||||||
|
}
|
||||||
|
|
||||||
void Cpu::CLI() { status &= ~0x04; }
|
void Cpu::CLI() {
|
||||||
|
AdrImp();
|
||||||
|
status &= ~0x04;
|
||||||
|
}
|
||||||
|
|
||||||
void Cpu::CLV() { status &= ~0x40; }
|
void Cpu::CLV() {
|
||||||
|
AdrImp();
|
||||||
|
status &= ~0x40;
|
||||||
|
}
|
||||||
|
|
||||||
// n Set if MSB of result is set; else cleared
|
// n Set if MSB of result is set; else cleared
|
||||||
// z Set if result is zero; else cleared
|
// z Set if result is zero; else cleared
|
||||||
// c Set if no borrow; else cleared
|
// c Set if no borrow; else cleared
|
||||||
void Cpu::CMP(uint32_t value, bool isImmediate) {
|
void Cpu::CMP(uint32_t value, bool isImmediate) {
|
||||||
if (GetAccumulatorSize()) { // 8-bit
|
if (GetAccumulatorSize()) { // 8-bit
|
||||||
|
CheckInt();
|
||||||
uint8_t result;
|
uint8_t result;
|
||||||
if (isImmediate) {
|
if (isImmediate) {
|
||||||
result = A - (value & 0xFF);
|
result = A - (value & 0xFF);
|
||||||
@@ -191,7 +220,7 @@ void Cpu::CMP(uint32_t value, bool isImmediate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::COP() {
|
void Cpu::COP() {
|
||||||
next_pc_ += 2; // Increment the program counter by 2
|
next_pc_ = PC + 2; // Increment the program counter by 2
|
||||||
PushWord(next_pc_);
|
PushWord(next_pc_);
|
||||||
PushByte(status);
|
PushByte(status);
|
||||||
SetInterruptFlag(true);
|
SetInterruptFlag(true);
|
||||||
@@ -201,10 +230,13 @@ void Cpu::COP() {
|
|||||||
next_pc_ = ReadWord(0xFFE4);
|
next_pc_ = ReadWord(0xFFE4);
|
||||||
}
|
}
|
||||||
SetDecimalFlag(false);
|
SetDecimalFlag(false);
|
||||||
|
next_pb_ = 0;
|
||||||
|
next_pc_ = ReadWord(0xFFE4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::CPX(uint32_t value, bool isImmediate) {
|
void Cpu::CPX(uint32_t value, bool isImmediate) {
|
||||||
if (GetIndexSize()) { // 8-bit
|
if (GetIndexSize()) { // 8-bit
|
||||||
|
CheckInt();
|
||||||
uint8_t memory_value = isImmediate ? value : ReadByte(value);
|
uint8_t memory_value = isImmediate ? value : ReadByte(value);
|
||||||
compare(X, memory_value);
|
compare(X, memory_value);
|
||||||
} else { // 16-bit
|
} else { // 16-bit
|
||||||
@@ -215,6 +247,7 @@ void Cpu::CPX(uint32_t value, bool isImmediate) {
|
|||||||
|
|
||||||
void Cpu::CPY(uint32_t value, bool isImmediate) {
|
void Cpu::CPY(uint32_t value, bool isImmediate) {
|
||||||
if (GetIndexSize()) { // 8-bit
|
if (GetIndexSize()) { // 8-bit
|
||||||
|
CheckInt();
|
||||||
uint8_t memory_value = isImmediate ? value : ReadByte(value);
|
uint8_t memory_value = isImmediate ? value : ReadByte(value);
|
||||||
compare(Y, memory_value);
|
compare(Y, memory_value);
|
||||||
} else { // 16-bit
|
} else { // 16-bit
|
||||||
@@ -225,6 +258,7 @@ void Cpu::CPY(uint32_t value, bool isImmediate) {
|
|||||||
|
|
||||||
void Cpu::DEC(uint32_t address, bool accumulator) {
|
void Cpu::DEC(uint32_t address, bool accumulator) {
|
||||||
if (accumulator) {
|
if (accumulator) {
|
||||||
|
AdrImp();
|
||||||
if (GetAccumulatorSize()) { // 8-bit
|
if (GetAccumulatorSize()) { // 8-bit
|
||||||
A = (A - 1) & 0xFF;
|
A = (A - 1) & 0xFF;
|
||||||
SetZeroFlag(A == 0);
|
SetZeroFlag(A == 0);
|
||||||
@@ -240,12 +274,15 @@ void Cpu::DEC(uint32_t address, bool accumulator) {
|
|||||||
if (GetAccumulatorSize()) {
|
if (GetAccumulatorSize()) {
|
||||||
uint8_t value = ReadByte(address);
|
uint8_t value = ReadByte(address);
|
||||||
value--;
|
value--;
|
||||||
|
callbacks_.idle(false);
|
||||||
|
CheckInt();
|
||||||
WriteByte(address, value);
|
WriteByte(address, value);
|
||||||
SetZeroFlag(value == 0);
|
SetZeroFlag(value == 0);
|
||||||
SetNegativeFlag(value & 0x80);
|
SetNegativeFlag(value & 0x80);
|
||||||
} else {
|
} else {
|
||||||
uint16_t value = ReadWord(address);
|
uint16_t value = ReadWord(address);
|
||||||
value--;
|
value--;
|
||||||
|
callbacks_.idle(false);
|
||||||
WriteWord(address, value);
|
WriteWord(address, value);
|
||||||
SetZeroFlag(value == 0);
|
SetZeroFlag(value == 0);
|
||||||
SetNegativeFlag(value & 0x8000);
|
SetNegativeFlag(value & 0x8000);
|
||||||
@@ -253,6 +290,7 @@ void Cpu::DEC(uint32_t address, bool accumulator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::DEX() {
|
void Cpu::DEX() {
|
||||||
|
AdrImp();
|
||||||
if (GetIndexSize()) { // 8-bit
|
if (GetIndexSize()) { // 8-bit
|
||||||
X = static_cast<uint8_t>(X - 1);
|
X = static_cast<uint8_t>(X - 1);
|
||||||
SetZeroFlag(X == 0);
|
SetZeroFlag(X == 0);
|
||||||
@@ -265,6 +303,7 @@ void Cpu::DEX() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::DEY() {
|
void Cpu::DEY() {
|
||||||
|
AdrImp();
|
||||||
if (GetIndexSize()) { // 8-bit
|
if (GetIndexSize()) { // 8-bit
|
||||||
Y = static_cast<uint8_t>(Y - 1);
|
Y = static_cast<uint8_t>(Y - 1);
|
||||||
SetZeroFlag(Y == 0);
|
SetZeroFlag(Y == 0);
|
||||||
@@ -278,6 +317,7 @@ void Cpu::DEY() {
|
|||||||
|
|
||||||
void Cpu::EOR(uint32_t address, bool isImmediate) {
|
void Cpu::EOR(uint32_t address, bool isImmediate) {
|
||||||
if (GetAccumulatorSize()) {
|
if (GetAccumulatorSize()) {
|
||||||
|
CheckInt();
|
||||||
A ^= isImmediate ? address : ReadByte(address);
|
A ^= isImmediate ? address : ReadByte(address);
|
||||||
SetZeroFlag(A == 0);
|
SetZeroFlag(A == 0);
|
||||||
SetNegativeFlag(A & 0x80);
|
SetNegativeFlag(A & 0x80);
|
||||||
@@ -290,6 +330,7 @@ void Cpu::EOR(uint32_t address, bool isImmediate) {
|
|||||||
|
|
||||||
void Cpu::INC(uint32_t address, bool accumulator) {
|
void Cpu::INC(uint32_t address, bool accumulator) {
|
||||||
if (accumulator) {
|
if (accumulator) {
|
||||||
|
AdrImp();
|
||||||
if (GetAccumulatorSize()) { // 8-bit
|
if (GetAccumulatorSize()) { // 8-bit
|
||||||
A = (A + 1) & 0xFF;
|
A = (A + 1) & 0xFF;
|
||||||
SetZeroFlag(A == 0);
|
SetZeroFlag(A == 0);
|
||||||
@@ -305,12 +346,15 @@ void Cpu::INC(uint32_t address, bool accumulator) {
|
|||||||
if (GetAccumulatorSize()) {
|
if (GetAccumulatorSize()) {
|
||||||
uint8_t value = ReadByte(address);
|
uint8_t value = ReadByte(address);
|
||||||
value++;
|
value++;
|
||||||
|
callbacks_.idle(false);
|
||||||
|
CheckInt();
|
||||||
WriteByte(address, value);
|
WriteByte(address, value);
|
||||||
SetNegativeFlag(value & 0x80);
|
SetNegativeFlag(value & 0x80);
|
||||||
SetZeroFlag(value == 0);
|
SetZeroFlag(value == 0);
|
||||||
} else {
|
} else {
|
||||||
uint16_t value = ReadWord(address);
|
uint16_t value = ReadWord(address);
|
||||||
value++;
|
value++;
|
||||||
|
callbacks_.idle(false);
|
||||||
WriteWord(address, value);
|
WriteWord(address, value);
|
||||||
SetNegativeFlag(value & 0x8000);
|
SetNegativeFlag(value & 0x8000);
|
||||||
SetZeroFlag(value == 0);
|
SetZeroFlag(value == 0);
|
||||||
@@ -318,6 +362,7 @@ void Cpu::INC(uint32_t address, bool accumulator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::INX() {
|
void Cpu::INX() {
|
||||||
|
AdrImp();
|
||||||
if (GetIndexSize()) { // 8-bit
|
if (GetIndexSize()) { // 8-bit
|
||||||
X = static_cast<uint8_t>(X + 1);
|
X = static_cast<uint8_t>(X + 1);
|
||||||
SetZeroFlag(X == 0);
|
SetZeroFlag(X == 0);
|
||||||
@@ -330,6 +375,7 @@ void Cpu::INX() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::INY() {
|
void Cpu::INY() {
|
||||||
|
AdrImp();
|
||||||
if (GetIndexSize()) { // 8-bit
|
if (GetIndexSize()) { // 8-bit
|
||||||
Y = static_cast<uint8_t>(Y + 1);
|
Y = static_cast<uint8_t>(Y + 1);
|
||||||
SetZeroFlag(Y == 0);
|
SetZeroFlag(Y == 0);
|
||||||
@@ -345,21 +391,26 @@ void Cpu::JMP(uint16_t address) {
|
|||||||
next_pc_ = address; // Set program counter to the new address
|
next_pc_ = address; // Set program counter to the new address
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::JML(uint32_t address) {
|
void Cpu::JML(uint16_t address) {
|
||||||
next_pc_ = static_cast<uint16_t>(address & 0xFFFF);
|
CheckInt();
|
||||||
// Set the PBR to the upper 8 bits of the address
|
next_pc_ = address;
|
||||||
PB = static_cast<uint8_t>((address >> 16) & 0xFF);
|
uint8_t new_pb = ReadByte(PC + 2);
|
||||||
|
next_pb_ = new_pb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::JSR(uint16_t address) {
|
void Cpu::JSR(uint16_t address) {
|
||||||
|
callbacks_.idle(false);
|
||||||
PushWord(PC); // Push the program counter onto the stack
|
PushWord(PC); // Push the program counter onto the stack
|
||||||
next_pc_ = address; // Set program counter to the new address
|
next_pc_ = address; // Set program counter to the new address
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::JSL(uint32_t address) {
|
void Cpu::JSL(uint16_t address) {
|
||||||
PushLong(PC); // Push the program counter onto the stack as a long
|
PushByte(PB);
|
||||||
// value (24 bits)
|
callbacks_.idle(false);
|
||||||
|
uint8_t new_pb = ReadByte(PC + 2);
|
||||||
|
PushWord(PC);
|
||||||
next_pc_ = address; // Set program counter to the new address
|
next_pc_ = address; // Set program counter to the new address
|
||||||
|
next_pb_ = new_pb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::LDA(uint16_t address, bool isImmediate, bool direct_page,
|
void Cpu::LDA(uint16_t address, bool isImmediate, bool direct_page,
|
||||||
@@ -369,6 +420,7 @@ void Cpu::LDA(uint16_t address, bool isImmediate, bool direct_page,
|
|||||||
bank = 0;
|
bank = 0;
|
||||||
}
|
}
|
||||||
if (GetAccumulatorSize()) {
|
if (GetAccumulatorSize()) {
|
||||||
|
CheckInt();
|
||||||
A = isImmediate ? address : ReadByte((bank << 16) | address);
|
A = isImmediate ? address : ReadByte((bank << 16) | address);
|
||||||
SetZeroFlag(A == 0);
|
SetZeroFlag(A == 0);
|
||||||
SetNegativeFlag(A & 0x80);
|
SetNegativeFlag(A & 0x80);
|
||||||
@@ -381,6 +433,7 @@ void Cpu::LDA(uint16_t address, bool isImmediate, bool direct_page,
|
|||||||
|
|
||||||
void Cpu::LDX(uint16_t address, bool isImmediate) {
|
void Cpu::LDX(uint16_t address, bool isImmediate) {
|
||||||
if (GetIndexSize()) {
|
if (GetIndexSize()) {
|
||||||
|
CheckInt();
|
||||||
X = isImmediate ? address : ReadByte(address);
|
X = isImmediate ? address : ReadByte(address);
|
||||||
SetZeroFlag(X == 0);
|
SetZeroFlag(X == 0);
|
||||||
SetNegativeFlag(X & 0x80);
|
SetNegativeFlag(X & 0x80);
|
||||||
@@ -393,6 +446,7 @@ void Cpu::LDX(uint16_t address, bool isImmediate) {
|
|||||||
|
|
||||||
void Cpu::LDY(uint16_t address, bool isImmediate) {
|
void Cpu::LDY(uint16_t address, bool isImmediate) {
|
||||||
if (GetIndexSize()) {
|
if (GetIndexSize()) {
|
||||||
|
CheckInt();
|
||||||
Y = isImmediate ? address : ReadByte(address);
|
Y = isImmediate ? address : ReadByte(address);
|
||||||
SetZeroFlag(Y == 0);
|
SetZeroFlag(Y == 0);
|
||||||
SetNegativeFlag(Y & 0x80);
|
SetNegativeFlag(Y & 0x80);
|
||||||
@@ -405,6 +459,7 @@ void Cpu::LDY(uint16_t address, bool isImmediate) {
|
|||||||
|
|
||||||
void Cpu::LSR(uint16_t address, bool accumulator) {
|
void Cpu::LSR(uint16_t address, bool accumulator) {
|
||||||
if (accumulator) {
|
if (accumulator) {
|
||||||
|
AdrImp();
|
||||||
if (GetAccumulatorSize()) { // 8-bit
|
if (GetAccumulatorSize()) { // 8-bit
|
||||||
SetCarryFlag(A & 0x01);
|
SetCarryFlag(A & 0x01);
|
||||||
A >>= 1;
|
A >>= 1;
|
||||||
@@ -418,46 +473,73 @@ void Cpu::LSR(uint16_t address, bool accumulator) {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint8_t value = ReadByte(address);
|
|
||||||
SetCarryFlag(value & 0x01);
|
|
||||||
value >>= 1;
|
|
||||||
WriteByte(address, value);
|
|
||||||
SetNegativeFlag(false);
|
|
||||||
SetZeroFlag(value == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Cpu::MVN(uint16_t source, uint16_t dest, uint16_t length) {
|
if (GetAccumulatorSize()) {
|
||||||
for (uint16_t i = 0; i < length; i++) {
|
uint8_t value = ReadByte(address);
|
||||||
WriteByte(dest, ReadByte(source));
|
callbacks_.idle(false);
|
||||||
source++;
|
SetCarryFlag(value & 0x01);
|
||||||
dest++;
|
value >>= 1;
|
||||||
|
CheckInt();
|
||||||
|
WriteByte(address, value);
|
||||||
|
SetNegativeFlag(false);
|
||||||
|
SetZeroFlag(value == 0);
|
||||||
|
} else {
|
||||||
|
uint16_t value = ReadWord(address);
|
||||||
|
SetCarryFlag(value & 0x0001);
|
||||||
|
value >>= 1;
|
||||||
|
WriteWord(address, value);
|
||||||
|
SetNegativeFlag(false);
|
||||||
|
SetZeroFlag(value == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::MVP(uint16_t source, uint16_t dest, uint16_t length) {
|
void Cpu::MVN() {
|
||||||
for (uint16_t i = 0; i < length; i++) {
|
uint8_t dest = ReadByte(PC + 1);
|
||||||
WriteByte(dest, ReadByte(source));
|
uint8_t src = ReadByte(PC + 2);
|
||||||
source--;
|
next_pc_ = PC + 3;
|
||||||
dest--;
|
DB = dest;
|
||||||
|
WriteByte((dest << 16) | Y, ReadByte((src << 16) | X));
|
||||||
|
A--;
|
||||||
|
X++;
|
||||||
|
Y++;
|
||||||
|
if (A != 0xFFFF) {
|
||||||
|
next_pc_ -= 3;
|
||||||
}
|
}
|
||||||
|
if (GetIndexSize()) {
|
||||||
|
X &= 0xFF;
|
||||||
|
Y &= 0xFF;
|
||||||
|
}
|
||||||
|
callbacks_.idle(false);
|
||||||
|
CheckInt();
|
||||||
|
callbacks_.idle(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cpu::MVP() {
|
||||||
|
uint8_t dest = ReadByte(PC + 1);
|
||||||
|
uint8_t src = ReadByte(PC + 2);
|
||||||
|
next_pc_ = PC + 3;
|
||||||
|
DB = dest;
|
||||||
|
WriteByte((dest << 16) | Y, ReadByte((src << 16) | X));
|
||||||
|
A--;
|
||||||
|
X--;
|
||||||
|
Y--;
|
||||||
|
if (A != 0xFFFF) {
|
||||||
|
next_pc_ -= 3;
|
||||||
|
}
|
||||||
|
if (GetIndexSize()) {
|
||||||
|
X &= 0xFF;
|
||||||
|
Y &= 0xFF;
|
||||||
|
}
|
||||||
|
callbacks_.idle(false);
|
||||||
|
CheckInt();
|
||||||
|
callbacks_.idle(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::NOP() { AdrImp(); }
|
void Cpu::NOP() { AdrImp(); }
|
||||||
|
|
||||||
// void cpu_ora(uint32_t low, uint32_t high) {
|
|
||||||
// if (cpu->mf) {
|
|
||||||
// CheckInt();
|
|
||||||
// uint8_t value = cpu_read(cpu, low);
|
|
||||||
// cpu->a = (cpu->a & 0xff00) | ((cpu->a | value) & 0xff);
|
|
||||||
// } else {
|
|
||||||
// uint16_t value = cpu_readWord(cpu, low, high, true);
|
|
||||||
// cpu->a |= value;
|
|
||||||
// }
|
|
||||||
// cpu_setZN(cpu, cpu->a, cpu->mf);
|
|
||||||
// }
|
|
||||||
|
|
||||||
void Cpu::ORA(uint16_t address, bool isImmediate) {
|
void Cpu::ORA(uint16_t address, bool isImmediate) {
|
||||||
if (GetAccumulatorSize()) {
|
if (GetAccumulatorSize()) {
|
||||||
|
CheckInt();
|
||||||
A |= isImmediate ? address : ReadByte(address);
|
A |= isImmediate ? address : ReadByte(address);
|
||||||
SetZeroFlag(A == 0);
|
SetZeroFlag(A == 0);
|
||||||
SetNegativeFlag(A & 0x80);
|
SetNegativeFlag(A & 0x80);
|
||||||
@@ -615,6 +697,7 @@ void Cpu::REP() {
|
|||||||
|
|
||||||
void Cpu::ROL(uint32_t address, bool accumulator) {
|
void Cpu::ROL(uint32_t address, bool accumulator) {
|
||||||
if (accumulator) {
|
if (accumulator) {
|
||||||
|
AdrImp();
|
||||||
if (GetAccumulatorSize()) { // 8-bit
|
if (GetAccumulatorSize()) { // 8-bit
|
||||||
uint8_t carry = GetCarryFlag() ? 0x01 : 0x00;
|
uint8_t carry = GetCarryFlag() ? 0x01 : 0x00;
|
||||||
SetCarryFlag(A & 0x80);
|
SetCarryFlag(A & 0x80);
|
||||||
@@ -633,18 +716,33 @@ void Cpu::ROL(uint32_t address, bool accumulator) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t value = ReadByte(address);
|
if (GetAccumulatorSize()) {
|
||||||
uint8_t carry = GetCarryFlag() ? 0x01 : 0x00;
|
uint8_t value = ReadByte(address);
|
||||||
SetCarryFlag(value & 0x80);
|
callbacks_.idle(false);
|
||||||
value <<= 1;
|
uint8_t carry = GetCarryFlag() ? 0x01 : 0x00;
|
||||||
value |= carry;
|
SetCarryFlag(value & 0x80);
|
||||||
WriteByte(address, value);
|
value <<= 1;
|
||||||
SetNegativeFlag(value & 0x80);
|
value |= carry;
|
||||||
SetZeroFlag(value == 0);
|
CheckInt();
|
||||||
|
WriteByte(address, value);
|
||||||
|
SetNegativeFlag(value & 0x80);
|
||||||
|
SetZeroFlag(value == 0);
|
||||||
|
} else {
|
||||||
|
uint16_t value = ReadWord(address);
|
||||||
|
callbacks_.idle(false);
|
||||||
|
uint8_t carry = GetCarryFlag() ? 0x01 : 0x00;
|
||||||
|
SetCarryFlag(value & 0x8000);
|
||||||
|
value <<= 1;
|
||||||
|
value |= carry;
|
||||||
|
WriteWord(address, value);
|
||||||
|
SetNegativeFlag(value & 0x8000);
|
||||||
|
SetZeroFlag(value == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::ROR(uint32_t address, bool accumulator) {
|
void Cpu::ROR(uint32_t address, bool accumulator) {
|
||||||
if (accumulator) {
|
if (accumulator) {
|
||||||
|
AdrImp();
|
||||||
if (GetAccumulatorSize()) { // 8-bit
|
if (GetAccumulatorSize()) { // 8-bit
|
||||||
uint8_t carry = GetCarryFlag() ? 0x80 : 0x00;
|
uint8_t carry = GetCarryFlag() ? 0x80 : 0x00;
|
||||||
SetCarryFlag(A & 0x01);
|
SetCarryFlag(A & 0x01);
|
||||||
@@ -663,27 +761,54 @@ void Cpu::ROR(uint32_t address, bool accumulator) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t value = ReadByte(address);
|
if (GetAccumulatorSize()) {
|
||||||
uint8_t carry = GetCarryFlag() ? 0x80 : 0x00;
|
uint8_t value = ReadByte(address);
|
||||||
SetCarryFlag(value & 0x01);
|
callbacks_.idle(false);
|
||||||
value >>= 1;
|
uint8_t carry = GetCarryFlag() ? 0x80 : 0x00;
|
||||||
value |= carry;
|
SetCarryFlag(value & 0x01);
|
||||||
WriteByte(address, value);
|
value >>= 1;
|
||||||
SetNegativeFlag(value & 0x80);
|
value |= carry;
|
||||||
SetZeroFlag(value == 0);
|
CheckInt();
|
||||||
|
WriteByte(address, value);
|
||||||
|
SetNegativeFlag(value & 0x80);
|
||||||
|
SetZeroFlag(value == 0);
|
||||||
|
} else {
|
||||||
|
uint16_t value = ReadWord(address);
|
||||||
|
callbacks_.idle(false);
|
||||||
|
uint8_t carry = GetCarryFlag() ? 0x8000 : 0x00;
|
||||||
|
SetCarryFlag(value & 0x0001);
|
||||||
|
value >>= 1;
|
||||||
|
value |= carry;
|
||||||
|
WriteWord(address, value);
|
||||||
|
SetNegativeFlag(value & 0x8000);
|
||||||
|
SetZeroFlag(value == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::RTI() {
|
void Cpu::RTI() {
|
||||||
|
callbacks_.idle(false);
|
||||||
|
callbacks_.idle(false);
|
||||||
status = PopByte();
|
status = PopByte();
|
||||||
PC = PopWord();
|
next_pc_ = PopWord();
|
||||||
|
CheckInt();
|
||||||
|
next_pb_ = PopByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::RTL() {
|
void Cpu::RTL() {
|
||||||
|
callbacks_.idle(false);
|
||||||
|
callbacks_.idle(false);
|
||||||
next_pc_ = PopWord();
|
next_pc_ = PopWord();
|
||||||
PB = PopByte();
|
CheckInt();
|
||||||
|
next_pb_ = PopByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::RTS() { last_call_frame_ = PopWord(); }
|
void Cpu::RTS() {
|
||||||
|
callbacks_.idle(false);
|
||||||
|
callbacks_.idle(false);
|
||||||
|
last_call_frame_ = PopWord();
|
||||||
|
CheckInt();
|
||||||
|
callbacks_.idle(false);
|
||||||
|
}
|
||||||
|
|
||||||
void Cpu::SBC(uint32_t value, bool isImmediate) {
|
void Cpu::SBC(uint32_t value, bool isImmediate) {
|
||||||
uint16_t operand;
|
uint16_t operand;
|
||||||
@@ -702,6 +827,7 @@ void Cpu::SBC(uint32_t value, bool isImmediate) {
|
|||||||
SetZeroFlag(A == 0);
|
SetZeroFlag(A == 0);
|
||||||
SetNegativeFlag(A & 0x8000);
|
SetNegativeFlag(A & 0x8000);
|
||||||
} else { // 8-bit mode
|
} else { // 8-bit mode
|
||||||
|
CheckInt();
|
||||||
operand = isImmediate ? value : ReadByte(value);
|
operand = isImmediate ? value : ReadByte(value);
|
||||||
uint8_t result = A - operand - (GetCarryFlag() ? 0 : 1);
|
uint8_t result = A - operand - (GetCarryFlag() ? 0 : 1);
|
||||||
SetCarryFlag(!(result > 0xFF)); // Update the carry flag
|
SetCarryFlag(!(result > 0xFF)); // Update the carry flag
|
||||||
@@ -718,11 +844,20 @@ void Cpu::SBC(uint32_t value, bool isImmediate) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::SEC() { status |= 0x01; }
|
void Cpu::SEC() {
|
||||||
|
AdrImp();
|
||||||
|
status |= 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
void Cpu::SED() { status |= 0x08; }
|
void Cpu::SED() {
|
||||||
|
AdrImp();
|
||||||
|
status |= 0x08;
|
||||||
|
}
|
||||||
|
|
||||||
void Cpu::SEI() { status |= 0x04; }
|
void Cpu::SEI() {
|
||||||
|
AdrImp();
|
||||||
|
status |= 0x04;
|
||||||
|
}
|
||||||
|
|
||||||
void Cpu::SEP() {
|
void Cpu::SEP() {
|
||||||
auto byte = FetchByte();
|
auto byte = FetchByte();
|
||||||
@@ -733,6 +868,7 @@ void Cpu::SEP() {
|
|||||||
|
|
||||||
void Cpu::STA(uint32_t address) {
|
void Cpu::STA(uint32_t address) {
|
||||||
if (GetAccumulatorSize()) {
|
if (GetAccumulatorSize()) {
|
||||||
|
CheckInt();
|
||||||
WriteByte(address, static_cast<uint8_t>(A));
|
WriteByte(address, static_cast<uint8_t>(A));
|
||||||
} else {
|
} else {
|
||||||
WriteWord(address, A);
|
WriteWord(address, A);
|
||||||
@@ -747,6 +883,7 @@ void Cpu::STP() {
|
|||||||
|
|
||||||
void Cpu::STX(uint16_t address) {
|
void Cpu::STX(uint16_t address) {
|
||||||
if (GetIndexSize()) {
|
if (GetIndexSize()) {
|
||||||
|
CheckInt();
|
||||||
WriteByte(address, static_cast<uint8_t>(X));
|
WriteByte(address, static_cast<uint8_t>(X));
|
||||||
} else {
|
} else {
|
||||||
WriteWord(address, X);
|
WriteWord(address, X);
|
||||||
@@ -755,6 +892,7 @@ void Cpu::STX(uint16_t address) {
|
|||||||
|
|
||||||
void Cpu::STY(uint16_t address) {
|
void Cpu::STY(uint16_t address) {
|
||||||
if (GetIndexSize()) {
|
if (GetIndexSize()) {
|
||||||
|
CheckInt();
|
||||||
WriteByte(address, static_cast<uint8_t>(Y));
|
WriteByte(address, static_cast<uint8_t>(Y));
|
||||||
} else {
|
} else {
|
||||||
WriteWord(address, Y);
|
WriteWord(address, Y);
|
||||||
@@ -763,6 +901,7 @@ void Cpu::STY(uint16_t address) {
|
|||||||
|
|
||||||
void Cpu::STZ(uint16_t address) {
|
void Cpu::STZ(uint16_t address) {
|
||||||
if (GetAccumulatorSize()) {
|
if (GetAccumulatorSize()) {
|
||||||
|
CheckInt();
|
||||||
WriteByte(address, 0x00);
|
WriteByte(address, 0x00);
|
||||||
} else {
|
} else {
|
||||||
WriteWord(address, 0x0000);
|
WriteWord(address, 0x0000);
|
||||||
@@ -770,46 +909,82 @@ void Cpu::STZ(uint16_t address) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::TAX() {
|
void Cpu::TAX() {
|
||||||
X = A;
|
AdrImp();
|
||||||
|
if (GetIndexSize()) {
|
||||||
|
X = A & 0xFF;
|
||||||
|
} else {
|
||||||
|
X = A;
|
||||||
|
}
|
||||||
SetZeroFlag(X == 0);
|
SetZeroFlag(X == 0);
|
||||||
SetNegativeFlag(X & 0x80);
|
SetNegativeFlag(X & 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::TAY() {
|
void Cpu::TAY() {
|
||||||
Y = A;
|
AdrImp();
|
||||||
|
if (GetIndexSize()) {
|
||||||
|
Y = A & 0xFF;
|
||||||
|
} else {
|
||||||
|
Y = A;
|
||||||
|
}
|
||||||
SetZeroFlag(Y == 0);
|
SetZeroFlag(Y == 0);
|
||||||
SetNegativeFlag(Y & 0x80);
|
SetNegativeFlag(Y & 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::TCD() {
|
void Cpu::TCD() {
|
||||||
|
AdrImp();
|
||||||
D = A;
|
D = A;
|
||||||
SetZeroFlag(D == 0);
|
SetZeroFlag(D == 0);
|
||||||
SetNegativeFlag(D & 0x80);
|
SetNegativeFlag(D & 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::TCS() { SetSP(A); }
|
void Cpu::TCS() {
|
||||||
|
AdrImp();
|
||||||
|
SetSP(A);
|
||||||
|
}
|
||||||
|
|
||||||
void Cpu::TDC() {
|
void Cpu::TDC() {
|
||||||
|
AdrImp();
|
||||||
A = D;
|
A = D;
|
||||||
SetZeroFlag(A == 0);
|
SetZeroFlag(A == 0);
|
||||||
SetNegativeFlag(A & 0x80);
|
SetNegativeFlag(A & 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::TRB(uint16_t address) {
|
void Cpu::TRB(uint16_t address) {
|
||||||
uint8_t value = ReadByte(address);
|
if (GetAccumulatorSize()) {
|
||||||
SetZeroFlag((A & value) == 0);
|
uint8_t value = ReadByte(address);
|
||||||
value &= ~A;
|
callbacks_.idle(false);
|
||||||
WriteByte(address, value);
|
SetZeroFlag((A & value) == 0);
|
||||||
|
value &= ~A;
|
||||||
|
CheckInt();
|
||||||
|
WriteByte(address, value);
|
||||||
|
} else {
|
||||||
|
uint16_t value = ReadWord(address);
|
||||||
|
callbacks_.idle(false);
|
||||||
|
SetZeroFlag((A & value) == 0);
|
||||||
|
value &= ~A;
|
||||||
|
WriteWord(address, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::TSB(uint16_t address) {
|
void Cpu::TSB(uint16_t address) {
|
||||||
uint8_t value = ReadByte(address);
|
if (GetAccumulatorSize()) {
|
||||||
SetZeroFlag((A & value) == 0);
|
uint8_t value = ReadByte(address);
|
||||||
value |= A;
|
callbacks_.idle(false);
|
||||||
WriteByte(address, value);
|
SetZeroFlag((A & value) == 0);
|
||||||
|
value |= A;
|
||||||
|
CheckInt();
|
||||||
|
WriteByte(address, value);
|
||||||
|
} else {
|
||||||
|
uint16_t value = ReadWord(address);
|
||||||
|
callbacks_.idle(false);
|
||||||
|
SetZeroFlag((A & value) == 0);
|
||||||
|
value |= A;
|
||||||
|
WriteWord(address, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::TSC() {
|
void Cpu::TSC() {
|
||||||
|
AdrImp();
|
||||||
A = SP();
|
A = SP();
|
||||||
SetZeroFlag(A == 0);
|
SetZeroFlag(A == 0);
|
||||||
SetNegativeFlag(A & 0x80);
|
SetNegativeFlag(A & 0x80);
|
||||||
@@ -817,14 +992,22 @@ void Cpu::TSC() {
|
|||||||
|
|
||||||
void Cpu::TSX() {
|
void Cpu::TSX() {
|
||||||
AdrImp();
|
AdrImp();
|
||||||
X = SP();
|
if (GetIndexSize()) {
|
||||||
|
X = SP() & 0xFF;
|
||||||
|
} else {
|
||||||
|
X = SP();
|
||||||
|
}
|
||||||
SetZeroFlag(X == 0);
|
SetZeroFlag(X == 0);
|
||||||
SetNegativeFlag(X & 0x80);
|
SetNegativeFlag(X & 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::TXA() {
|
void Cpu::TXA() {
|
||||||
AdrImp();
|
AdrImp();
|
||||||
A = X;
|
if (GetAccumulatorSize()) {
|
||||||
|
A = X & 0xFF;
|
||||||
|
} else {
|
||||||
|
A = X;
|
||||||
|
}
|
||||||
SetZeroFlag(A == 0);
|
SetZeroFlag(A == 0);
|
||||||
SetNegativeFlag(A & 0x80);
|
SetNegativeFlag(A & 0x80);
|
||||||
}
|
}
|
||||||
@@ -836,14 +1019,22 @@ void Cpu::TXS() {
|
|||||||
|
|
||||||
void Cpu::TXY() {
|
void Cpu::TXY() {
|
||||||
AdrImp();
|
AdrImp();
|
||||||
Y = X;
|
if (GetIndexSize()) {
|
||||||
|
Y = X & 0xFF;
|
||||||
|
} else {
|
||||||
|
Y = X;
|
||||||
|
}
|
||||||
SetZeroFlag(X == 0);
|
SetZeroFlag(X == 0);
|
||||||
SetNegativeFlag(X & 0x80);
|
SetNegativeFlag(X & 0x80);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::TYA() {
|
void Cpu::TYA() {
|
||||||
AdrImp();
|
AdrImp();
|
||||||
A = Y;
|
if (GetAccumulatorSize()) {
|
||||||
|
A = Y & 0xFF;
|
||||||
|
} else {
|
||||||
|
A = Y;
|
||||||
|
}
|
||||||
SetZeroFlag(A == 0);
|
SetZeroFlag(A == 0);
|
||||||
SetNegativeFlag(A & 0x80);
|
SetNegativeFlag(A & 0x80);
|
||||||
}
|
}
|
||||||
@@ -865,6 +1056,11 @@ void Cpu::WAI() {
|
|||||||
callbacks_.idle(false);
|
callbacks_.idle(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Cpu::WDM() {
|
||||||
|
CheckInt();
|
||||||
|
ReadByte(PC);
|
||||||
|
}
|
||||||
|
|
||||||
void Cpu::XBA() {
|
void Cpu::XBA() {
|
||||||
uint8_t lowByte = A & 0xFF;
|
uint8_t lowByte = A & 0xFF;
|
||||||
uint8_t highByte = (A >> 8) & 0xFF;
|
uint8_t highByte = (A >> 8) & 0xFF;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ void TransferByte(SNES* snes, MemoryImpl* memory, uint16_t aAdr, uint8_t aBank,
|
|||||||
uint8_t Read(MemoryImpl* memory, uint16_t address);
|
uint8_t Read(MemoryImpl* memory, uint16_t address);
|
||||||
void Write(MemoryImpl* memory, uint16_t address, uint8_t data);
|
void Write(MemoryImpl* memory, uint16_t address, uint8_t data);
|
||||||
void StartDma(MemoryImpl* memory, uint8_t val, bool hdma);
|
void StartDma(MemoryImpl* memory, uint8_t val, bool hdma);
|
||||||
void DoDma(MemoryImpl* memory, int cycles);
|
void DoDma(SNES* snes, MemoryImpl* memory, int cycles);
|
||||||
|
|
||||||
} // namespace dma
|
} // namespace dma
|
||||||
} // namespace memory
|
} // namespace memory
|
||||||
|
|||||||
Reference in New Issue
Block a user