2017-06-04 20:38:34 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <array>
|
|
|
|
|
#include <functional>
|
2017-08-07 20:02:31 +00:00
|
|
|
|
#include <cassert>
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-09-06 23:58:56 +00:00
|
|
|
|
#include <Bus.h>
|
|
|
|
|
#include <Processor.h>
|
|
|
|
|
#include <Signal.h>
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
namespace EightBit {
|
2017-07-05 16:46:02 +00:00
|
|
|
|
class MOS6502 : public Processor {
|
2017-07-02 21:03:33 +00:00
|
|
|
|
public:
|
2017-07-17 12:46:06 +00:00
|
|
|
|
struct opcode_decoded_t {
|
|
|
|
|
|
|
|
|
|
int aaa;
|
|
|
|
|
int bbb;
|
|
|
|
|
int cc;
|
|
|
|
|
|
|
|
|
|
opcode_decoded_t() {
|
|
|
|
|
aaa = bbb = cc = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
opcode_decoded_t(uint8_t opcode) {
|
|
|
|
|
aaa = (opcode & 0b11100000) >> 5; // 0 - 7
|
|
|
|
|
bbb = (opcode & 0b00011100) >> 2; // 0 - 7
|
|
|
|
|
cc = (opcode & 0b00000011); // 0 - 3
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2017-07-10 14:51:33 +00:00
|
|
|
|
enum StatusBits {
|
2017-07-17 12:46:06 +00:00
|
|
|
|
NF = Bit7, // Negative
|
|
|
|
|
VF = Bit6, // Overflow
|
|
|
|
|
RF = Bit5, // reserved
|
|
|
|
|
BF = Bit4, // Brk
|
|
|
|
|
DF = Bit3, // D (use BCD for arithmetic)
|
|
|
|
|
IF = Bit2, // I (IRQ disable)
|
|
|
|
|
ZF = Bit1, // Zero
|
|
|
|
|
CF = Bit0, // Carry
|
2017-07-10 14:51:33 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-09-06 23:58:56 +00:00
|
|
|
|
MOS6502(Bus& bus);
|
2017-07-02 21:03:33 +00:00
|
|
|
|
|
|
|
|
|
Signal<MOS6502> ExecutingInstruction;
|
2017-07-05 16:46:02 +00:00
|
|
|
|
Signal<MOS6502> ExecutedInstruction;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-08-30 22:17:34 +00:00
|
|
|
|
virtual void triggerIRQ();
|
|
|
|
|
virtual void triggerNMI();
|
|
|
|
|
|
|
|
|
|
virtual int execute(uint8_t opcode);
|
|
|
|
|
int step();
|
|
|
|
|
|
2017-07-07 08:24:58 +00:00
|
|
|
|
uint8_t& X() { return x; }
|
|
|
|
|
uint8_t& Y() { return y; }
|
|
|
|
|
uint8_t& A() { return a; }
|
|
|
|
|
uint8_t& S() { return s; }
|
2017-07-10 14:51:33 +00:00
|
|
|
|
uint8_t& P() { return p; }
|
2017-07-02 21:03:33 +00:00
|
|
|
|
|
2017-09-01 15:01:40 +00:00
|
|
|
|
virtual void initialise() override;
|
|
|
|
|
virtual void reset() override;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
private:
|
2017-07-16 09:05:49 +00:00
|
|
|
|
void adjustZero(uint8_t datum) { clearFlag(P(), ZF, datum); }
|
|
|
|
|
void adjustNegative(uint8_t datum) { setFlag(P(), NF, datum & NF); }
|
2017-07-06 20:32:52 +00:00
|
|
|
|
|
2017-07-16 09:05:49 +00:00
|
|
|
|
void adjustNZ(uint8_t datum) {
|
|
|
|
|
adjustZero(datum);
|
|
|
|
|
adjustNegative(datum);
|
2017-07-06 20:32:52 +00:00
|
|
|
|
}
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-08-30 22:17:34 +00:00
|
|
|
|
void getWord(register16_t& output);
|
|
|
|
|
void getWord(uint16_t offset, register16_t& output);
|
|
|
|
|
void getWord(const register16_t& offset, register16_t& output);
|
|
|
|
|
|
2017-08-28 12:19:17 +00:00
|
|
|
|
virtual void push(uint8_t value) override;
|
|
|
|
|
virtual uint8_t pop() override;
|
2017-06-04 20:38:34 +00:00
|
|
|
|
|
2017-08-30 22:17:34 +00:00
|
|
|
|
void interrupt(uint16_t vector);
|
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
#pragma region 6502 addressing modes
|
|
|
|
|
|
|
|
|
|
#pragma region Addresses
|
|
|
|
|
|
|
|
|
|
void Address_Absolute() {
|
2017-08-28 20:18:08 +00:00
|
|
|
|
fetchWord();
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Address_ZeroPage() {
|
2017-07-17 14:35:24 +00:00
|
|
|
|
MEMPTR().low = fetchByte();
|
2017-07-17 12:46:06 +00:00
|
|
|
|
MEMPTR().high = 0;
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Address_ZeroPageIndirect() {
|
|
|
|
|
Address_ZeroPage();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
getWord(MEMPTR(), MEMPTR());
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Address_Indirect() {
|
|
|
|
|
Address_Absolute();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
getWord(MEMPTR(), MEMPTR());
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Address_ZeroPageX() {
|
|
|
|
|
Address_ZeroPage();
|
2017-07-17 12:46:06 +00:00
|
|
|
|
MEMPTR().low += X();
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Address_ZeroPageY() {
|
|
|
|
|
Address_ZeroPage();
|
2017-07-17 12:46:06 +00:00
|
|
|
|
MEMPTR().low += Y();
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Address_AbsoluteX() {
|
|
|
|
|
Address_Absolute();
|
2017-07-17 12:46:06 +00:00
|
|
|
|
MEMPTR().word += X();
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Address_AbsoluteY() {
|
|
|
|
|
Address_Absolute();
|
2017-07-17 12:46:06 +00:00
|
|
|
|
MEMPTR().word += Y();
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Address_IndexedIndirectX() {
|
|
|
|
|
Address_ZeroPageX();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
getWord(MEMPTR(), MEMPTR());
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Address_IndirectIndexedY() {
|
|
|
|
|
Address_ZeroPageIndirect();
|
2017-07-17 12:46:06 +00:00
|
|
|
|
MEMPTR().word += Y();
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma endregion Addresses
|
|
|
|
|
|
2017-08-06 16:06:48 +00:00
|
|
|
|
#pragma region Addressing modes, read
|
2017-07-11 20:34:01 +00:00
|
|
|
|
|
2017-08-06 16:06:48 +00:00
|
|
|
|
uint8_t AM_A() {
|
2017-07-16 09:40:38 +00:00
|
|
|
|
return A();
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-06 16:06:48 +00:00
|
|
|
|
uint8_t AM_Immediate() {
|
|
|
|
|
return fetchByte();
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-06 16:06:48 +00:00
|
|
|
|
uint8_t AM_Absolute() {
|
2017-07-11 20:34:01 +00:00
|
|
|
|
Address_Absolute();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
return getByte(MEMPTR());
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-06 16:06:48 +00:00
|
|
|
|
uint8_t AM_ZeroPage() {
|
2017-07-11 20:34:01 +00:00
|
|
|
|
Address_ZeroPage();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
return getByte(MEMPTR());
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-06 16:06:48 +00:00
|
|
|
|
uint8_t AM_AbsoluteX() {
|
2017-07-11 20:34:01 +00:00
|
|
|
|
Address_AbsoluteX();
|
2017-09-06 23:58:56 +00:00
|
|
|
|
BUS().ADDRESS() = MEMPTR();
|
|
|
|
|
if (BUS().ADDRESS().low == Mask8)
|
2017-07-15 22:19:46 +00:00
|
|
|
|
++cycles;
|
2017-08-07 20:25:21 +00:00
|
|
|
|
return getByte();
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-06 16:06:48 +00:00
|
|
|
|
uint8_t AM_AbsoluteY() {
|
2017-07-11 20:34:01 +00:00
|
|
|
|
Address_AbsoluteY();
|
2017-09-06 23:58:56 +00:00
|
|
|
|
BUS().ADDRESS() = MEMPTR();
|
|
|
|
|
if (BUS().ADDRESS().low == Mask8)
|
2017-07-15 22:19:46 +00:00
|
|
|
|
++cycles;
|
2017-08-07 20:25:21 +00:00
|
|
|
|
return getByte();
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-06 16:06:48 +00:00
|
|
|
|
uint8_t AM_ZeroPageX() {
|
2017-07-11 20:34:01 +00:00
|
|
|
|
Address_ZeroPageX();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
return getByte(MEMPTR());
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-06 16:06:48 +00:00
|
|
|
|
uint8_t AM_ZeroPageY() {
|
2017-07-11 20:34:01 +00:00
|
|
|
|
Address_ZeroPageY();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
return getByte(MEMPTR());
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-06 16:06:48 +00:00
|
|
|
|
uint8_t AM_IndexedIndirectX() {
|
2017-07-11 20:34:01 +00:00
|
|
|
|
Address_IndexedIndirectX();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
return getByte(MEMPTR());
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-06 16:06:48 +00:00
|
|
|
|
uint8_t AM_IndirectIndexedY() {
|
2017-07-11 20:34:01 +00:00
|
|
|
|
Address_IndirectIndexedY();
|
2017-09-06 23:58:56 +00:00
|
|
|
|
BUS().ADDRESS() = MEMPTR();
|
|
|
|
|
if (BUS().ADDRESS().low == Mask8)
|
2017-07-15 22:19:46 +00:00
|
|
|
|
++cycles;
|
2017-08-07 20:25:21 +00:00
|
|
|
|
return getByte();
|
2017-07-11 20:34:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-06 16:06:48 +00:00
|
|
|
|
#pragma endregion Addressing modes, read
|
|
|
|
|
|
|
|
|
|
#pragma region Addressing modes, write
|
|
|
|
|
|
|
|
|
|
void AM_A(uint8_t value) {
|
|
|
|
|
A() = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AM_Absolute(uint8_t value) {
|
|
|
|
|
Address_Absolute();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
setByte(MEMPTR(), value);
|
2017-08-06 16:06:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AM_ZeroPage(uint8_t value) {
|
|
|
|
|
Address_ZeroPage();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
setByte(MEMPTR(), value);
|
2017-08-06 16:06:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AM_AbsoluteX(uint8_t value) {
|
|
|
|
|
Address_AbsoluteX();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
setByte(MEMPTR(), value);
|
2017-08-06 16:06:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AM_AbsoluteY(uint8_t value) {
|
|
|
|
|
Address_AbsoluteY();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
setByte(MEMPTR(), value);
|
2017-08-06 16:06:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AM_ZeroPageX(uint8_t value) {
|
|
|
|
|
Address_ZeroPageX();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
setByte(MEMPTR(), value);
|
2017-08-06 16:06:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AM_ZeroPageY(uint8_t value) {
|
|
|
|
|
Address_ZeroPageY();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
setByte(MEMPTR(), value);
|
2017-08-06 16:06:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AM_IndexedIndirectX(uint8_t value) {
|
|
|
|
|
Address_IndexedIndirectX();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
setByte(MEMPTR(), value);
|
2017-08-06 16:06:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AM_IndirectIndexedY(uint8_t value) {
|
|
|
|
|
Address_IndirectIndexedY();
|
2017-08-28 17:52:48 +00:00
|
|
|
|
setByte(MEMPTR(), value);
|
2017-08-06 16:06:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma endregion Addressing modes, write
|
2017-07-11 20:34:01 +00:00
|
|
|
|
|
2017-07-13 11:02:44 +00:00
|
|
|
|
#pragma region 6502 addressing mode switching
|
|
|
|
|
|
2017-08-06 16:06:48 +00:00
|
|
|
|
uint8_t AM_00(int bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
switch (bbb) {
|
|
|
|
|
case 0b000:
|
|
|
|
|
return AM_Immediate();
|
|
|
|
|
case 0b001:
|
|
|
|
|
return AM_ZeroPage();
|
|
|
|
|
case 0b011:
|
|
|
|
|
return AM_Absolute();
|
|
|
|
|
case 0b101:
|
|
|
|
|
return AM_ZeroPageX();
|
|
|
|
|
case 0b111:
|
2017-08-06 16:06:48 +00:00
|
|
|
|
return AM_AbsoluteX();
|
|
|
|
|
case 0b010:
|
|
|
|
|
case 0b100:
|
|
|
|
|
case 0b110:
|
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
|
default:
|
|
|
|
|
__assume(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AM_00(int bbb, uint8_t value) {
|
|
|
|
|
switch (bbb) {
|
|
|
|
|
case 0b000:
|
|
|
|
|
assert(false);
|
|
|
|
|
break;
|
|
|
|
|
case 0b001:
|
|
|
|
|
AM_ZeroPage(value);
|
|
|
|
|
break;
|
|
|
|
|
case 0b011:
|
|
|
|
|
AM_Absolute(value);
|
|
|
|
|
break;
|
|
|
|
|
case 0b101:
|
|
|
|
|
AM_ZeroPageX(value);
|
|
|
|
|
break;
|
|
|
|
|
case 0b111:
|
|
|
|
|
AM_AbsoluteX(value);
|
|
|
|
|
break;
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b010:
|
|
|
|
|
case 0b100:
|
|
|
|
|
case 0b110:
|
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
|
default:
|
|
|
|
|
__assume(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-06 16:06:48 +00:00
|
|
|
|
uint8_t AM_01(int bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
switch (bbb) {
|
|
|
|
|
case 0b000:
|
|
|
|
|
return AM_IndexedIndirectX();
|
|
|
|
|
case 0b001:
|
|
|
|
|
return AM_ZeroPage();
|
|
|
|
|
case 0b010:
|
|
|
|
|
return AM_Immediate();
|
|
|
|
|
case 0b011:
|
|
|
|
|
return AM_Absolute();
|
|
|
|
|
case 0b100:
|
2017-08-06 16:06:48 +00:00
|
|
|
|
return AM_IndirectIndexedY();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b101:
|
|
|
|
|
return AM_ZeroPageX();
|
|
|
|
|
case 0b110:
|
2017-08-06 16:06:48 +00:00
|
|
|
|
return AM_AbsoluteY();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b111:
|
2017-08-06 16:06:48 +00:00
|
|
|
|
return AM_AbsoluteX();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
default:
|
|
|
|
|
__assume(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-23 21:30:58 +00:00
|
|
|
|
void AM_01(int bbb, uint8_t value) {
|
2017-08-06 16:06:48 +00:00
|
|
|
|
switch (bbb) {
|
|
|
|
|
case 0b000:
|
|
|
|
|
AM_IndexedIndirectX(value);
|
|
|
|
|
break;
|
|
|
|
|
case 0b001:
|
|
|
|
|
AM_ZeroPage(value);
|
|
|
|
|
break;
|
|
|
|
|
case 0b010:
|
|
|
|
|
assert(false);
|
|
|
|
|
break;
|
|
|
|
|
case 0b011:
|
|
|
|
|
AM_Absolute(value);
|
|
|
|
|
break;
|
|
|
|
|
case 0b100:
|
|
|
|
|
AM_IndirectIndexedY(value);
|
|
|
|
|
break;
|
|
|
|
|
case 0b101:
|
|
|
|
|
AM_ZeroPageX(value);
|
|
|
|
|
break;
|
|
|
|
|
case 0b110:
|
|
|
|
|
AM_AbsoluteY(value);
|
|
|
|
|
break;
|
|
|
|
|
case 0b111:
|
|
|
|
|
AM_AbsoluteX(value);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
__assume(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t AM_10(int bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
switch (bbb) {
|
|
|
|
|
case 0b000:
|
|
|
|
|
return AM_Immediate();
|
|
|
|
|
case 0b001:
|
|
|
|
|
return AM_ZeroPage();
|
|
|
|
|
case 0b010:
|
2017-07-16 09:40:38 +00:00
|
|
|
|
return AM_A();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b011:
|
|
|
|
|
return AM_Absolute();
|
|
|
|
|
case 0b101:
|
|
|
|
|
return AM_ZeroPageX();
|
|
|
|
|
case 0b111:
|
2017-08-06 16:06:48 +00:00
|
|
|
|
return AM_AbsoluteX();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b100:
|
|
|
|
|
case 0b110:
|
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
|
default:
|
|
|
|
|
__assume(0);
|
|
|
|
|
}
|
2017-08-06 16:06:48 +00:00
|
|
|
|
return 0xff;
|
2017-07-13 11:02:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-07 20:25:21 +00:00
|
|
|
|
void AM_10(int bbb, uint8_t value) {
|
2017-08-06 16:06:48 +00:00
|
|
|
|
switch (bbb) {
|
|
|
|
|
case 0b010:
|
|
|
|
|
AM_A(value);
|
|
|
|
|
break;
|
2017-08-07 20:25:21 +00:00
|
|
|
|
case 0b001:
|
2017-08-06 16:06:48 +00:00
|
|
|
|
case 0b011:
|
|
|
|
|
case 0b101:
|
|
|
|
|
case 0b111:
|
2017-08-28 17:52:48 +00:00
|
|
|
|
setByte(MEMPTR(), value);
|
2017-08-06 16:06:48 +00:00
|
|
|
|
break;
|
2017-08-07 20:25:21 +00:00
|
|
|
|
case 0b000:
|
2017-08-06 16:06:48 +00:00
|
|
|
|
case 0b100:
|
|
|
|
|
case 0b110:
|
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
|
default:
|
|
|
|
|
__assume(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t AM_10_x(int bbb) {
|
2017-07-13 11:02:44 +00:00
|
|
|
|
switch (bbb) {
|
|
|
|
|
case 0b000:
|
|
|
|
|
return AM_Immediate();
|
|
|
|
|
case 0b001:
|
|
|
|
|
return AM_ZeroPage();
|
|
|
|
|
case 0b010:
|
2017-07-16 09:40:38 +00:00
|
|
|
|
return AM_A();
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b011:
|
|
|
|
|
return AM_Absolute();
|
|
|
|
|
case 0b101:
|
|
|
|
|
return AM_ZeroPageY();
|
|
|
|
|
case 0b111:
|
2017-08-06 16:06:48 +00:00
|
|
|
|
return AM_AbsoluteY();
|
|
|
|
|
case 0b100:
|
|
|
|
|
case 0b110:
|
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
|
default:
|
|
|
|
|
__assume(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AM_10_x(int bbb, uint8_t value) {
|
|
|
|
|
switch (bbb) {
|
|
|
|
|
case 0b000:
|
|
|
|
|
assert(false);
|
|
|
|
|
break;
|
|
|
|
|
case 0b001:
|
|
|
|
|
AM_ZeroPage(value);
|
|
|
|
|
break;
|
|
|
|
|
case 0b010:
|
|
|
|
|
AM_A(value);
|
|
|
|
|
break;
|
|
|
|
|
case 0b011:
|
|
|
|
|
AM_Absolute(value);
|
|
|
|
|
break;
|
|
|
|
|
case 0b101:
|
|
|
|
|
AM_ZeroPageY(value);
|
|
|
|
|
break;
|
|
|
|
|
case 0b111:
|
|
|
|
|
AM_AbsoluteY(value);
|
|
|
|
|
break;
|
2017-07-13 11:02:44 +00:00
|
|
|
|
case 0b100:
|
|
|
|
|
case 0b110:
|
|
|
|
|
throw std::domain_error("Illegal addressing mode");
|
|
|
|
|
default:
|
|
|
|
|
__assume(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma endregion 6502 addressing mode switching
|
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
#pragma endregion 6502 addressing modes
|
|
|
|
|
|
2017-07-17 20:00:05 +00:00
|
|
|
|
void ASL(int bbb) {
|
2017-08-06 16:06:48 +00:00
|
|
|
|
auto operand = AM_10(bbb);
|
|
|
|
|
ASL(operand);
|
2017-08-07 20:25:21 +00:00
|
|
|
|
AM_10(bbb, operand);
|
2017-07-17 20:00:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ROL(int bbb) {
|
2017-08-06 16:06:48 +00:00
|
|
|
|
auto operand = AM_10(bbb);
|
|
|
|
|
ROL(operand);
|
2017-08-07 20:25:21 +00:00
|
|
|
|
AM_10(bbb, operand);
|
2017-07-17 20:00:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LSR(int bbb) {
|
2017-08-06 16:06:48 +00:00
|
|
|
|
auto operand = AM_10(bbb);
|
|
|
|
|
LSR(operand);
|
2017-08-07 20:25:21 +00:00
|
|
|
|
AM_10(bbb, operand);
|
2017-07-17 20:00:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ROR(int bbb) {
|
2017-08-06 16:06:48 +00:00
|
|
|
|
auto operand = AM_10(bbb);
|
|
|
|
|
ROR(operand);
|
2017-08-07 20:25:21 +00:00
|
|
|
|
AM_10(bbb, operand);
|
2017-07-17 20:00:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void DEC(int bbb) {
|
2017-08-06 16:06:48 +00:00
|
|
|
|
auto operand = AM_10(bbb);
|
|
|
|
|
adjustNZ(--operand);
|
2017-08-07 20:25:21 +00:00
|
|
|
|
AM_10(bbb, operand);
|
2017-07-17 20:00:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void INC(int bbb) {
|
2017-08-06 16:06:48 +00:00
|
|
|
|
auto operand = AM_10(bbb);
|
|
|
|
|
adjustNZ(++operand);
|
2017-08-07 20:25:21 +00:00
|
|
|
|
AM_10(bbb, operand);
|
2017-07-17 20:00:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
void ROR(uint8_t& output);
|
|
|
|
|
|
|
|
|
|
void LSR(uint8_t& output);
|
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void BIT(uint8_t data);
|
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
void ROL(uint8_t& output);
|
2017-07-02 21:03:33 +00:00
|
|
|
|
|
2017-07-11 20:34:01 +00:00
|
|
|
|
void ASL(uint8_t& output);
|
2017-07-02 21:03:33 +00:00
|
|
|
|
|
|
|
|
|
void SBC(uint8_t data);
|
|
|
|
|
void SBC_b(uint8_t data);
|
|
|
|
|
void SBC_d(uint8_t data);
|
|
|
|
|
|
|
|
|
|
void CMP(uint8_t first, uint8_t second);
|
|
|
|
|
|
|
|
|
|
void ADC(uint8_t data);
|
|
|
|
|
void ADC_b(uint8_t data);
|
|
|
|
|
void ADC_d(uint8_t data);
|
|
|
|
|
|
|
|
|
|
void Branch(int8_t displacement);
|
2017-07-14 16:22:28 +00:00
|
|
|
|
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void Branch(bool flag);
|
2017-07-14 16:22:28 +00:00
|
|
|
|
|
|
|
|
|
void PHP();
|
|
|
|
|
void PLP();
|
2017-07-02 21:03:33 +00:00
|
|
|
|
|
|
|
|
|
void JSR_abs();
|
2017-07-14 16:22:28 +00:00
|
|
|
|
void RTI();
|
|
|
|
|
void RTS();
|
2017-07-02 21:03:33 +00:00
|
|
|
|
void JMP_abs();
|
|
|
|
|
void JMP_ind();
|
2017-07-14 16:22:28 +00:00
|
|
|
|
void BRK();
|
2017-07-02 21:03:33 +00:00
|
|
|
|
|
|
|
|
|
const uint16_t PageOne = 0x100;
|
|
|
|
|
const uint16_t IRQvector = 0xfffe;
|
|
|
|
|
const uint16_t RSTvector = 0xfffc;
|
|
|
|
|
const uint16_t NMIvector = 0xfffa;
|
|
|
|
|
|
|
|
|
|
uint8_t x; // index register X
|
|
|
|
|
uint8_t y; // index register Y
|
|
|
|
|
uint8_t a; // accumulator
|
|
|
|
|
uint8_t s; // stack pointer
|
2017-07-10 14:51:33 +00:00
|
|
|
|
uint8_t p; // processor status
|
2017-07-02 21:03:33 +00:00
|
|
|
|
|
2017-07-15 22:19:46 +00:00
|
|
|
|
std::array<int, 0x100> m_timings;
|
2017-07-17 12:46:06 +00:00
|
|
|
|
std::array<opcode_decoded_t, 0x100> m_decodedOpcodes;
|
2017-07-02 21:03:33 +00:00
|
|
|
|
};
|
|
|
|
|
}
|