forked from Apple-2-HW/arduino-appleii
210 lines
5.3 KiB
C++
210 lines
5.3 KiB
C++
// μ6502 v2.0 - Barebones 6502 Emulator By Damian Peckett
|
|
// dpeckett.com, <damian.peckett@gmail.com>
|
|
|
|
//Other constants
|
|
#define SR_FIXED_BITS 0x20
|
|
#define SR_CARRY 0x01
|
|
#define SR_ZERO 0x02
|
|
#define SR_INT 0x04
|
|
#define SR_DEC 0x08
|
|
#define SR_BRK 0x10
|
|
#define SR_OVER 0x40
|
|
#define SR_NEG 0x80
|
|
|
|
//Stack pointer base address
|
|
#define STP_BASE 0x100
|
|
|
|
// CPU registers
|
|
unsigned short PC;
|
|
unsigned char STP = 0xFD, A = 0x00, X = 0x00, Y = 0x00, SR = SR_FIXED_BITS;
|
|
|
|
void run() {
|
|
// Opcode Addresses, Labels As Values
|
|
static const void* opcodes[] = {
|
|
&&BRK, &&ORA_INDX, &&UNDF, &&UNDF, &&UNDF, &&ORA_ZPG, &&ASL_ZPG, &&UNDF, &&PHP, &&ORA_IMM, &&ASL_A, &&UNDF, &&UNDF, &&ORA_ABS, &&ASL_ABS, &&UNDF,
|
|
&&BPL_REL, &&ORA_INDY, &&UNDF, &&UNDF, &&UNDF, &&ORA_ZPGX, &&ASL_ZPGX, &&UNDF, &&CLC, &&ORA_ABSY, &&UNDF, &&UNDF, &&UNDF, &&ORA_ABSX, &&ASL_ABSX, &&UNDF,
|
|
&&JSR_ABS, &&AND_INDX, &&UNDF, &&UNDF, &&BIT_ZPG, &&AND_ZPG, &&ROL_ZPG, &&UNDF, &&PLP, &&AND_IMM, &&ROL_A, &&UNDF, &&BIT_ABS, &&AND_ABS, &&ROL_ABS, &&UNDF
|
|
};
|
|
|
|
unsigned char value8, result8;
|
|
unsigned short value16, result16;
|
|
unsigned short ptr;
|
|
|
|
// Load the reset vector
|
|
PC = read16(0xFFFC);
|
|
|
|
// Begin Execution
|
|
goto *opcodes[read8(PC++)];
|
|
|
|
// Instruction interpreter
|
|
BRK:
|
|
push16(PC+1);
|
|
push8(SR|SR_BRK);
|
|
SR |= SR_INT;
|
|
PC = read16(0xFFFE);
|
|
goto *opcodes[read8(PC++)];
|
|
ORA_INDX:
|
|
A |= read8(a_indx());
|
|
flagZero(A);
|
|
flagNegative(A);
|
|
goto *opcodes[read8(PC++)];
|
|
ORA_ZPG:
|
|
A |= read8(a_zpg());
|
|
flagZero(A);
|
|
flagNegative(A);
|
|
goto *opcodes[read8(PC++)];
|
|
ASL_ZPG:
|
|
ptr = a_zpg();
|
|
value16 = read8(ptr);
|
|
result16 = value16<<1;
|
|
flagZero(result16&0x00FF);
|
|
flagNegative(result16&0x00FF);
|
|
flagCarry(result16);
|
|
write8(ptr, result16&0x00FF);
|
|
goto *opcodes[read8(PC++)];
|
|
PHP:
|
|
push8(SR|SR_BRK);
|
|
goto *opcodes[read8(PC++)];
|
|
ORA_IMM:
|
|
A |= read8(a_imm());
|
|
flagZero(A);
|
|
flagNegative(A);
|
|
goto *opcodes[read8(PC++)];
|
|
ASL_A:
|
|
value16 = A;
|
|
result16 = value16<<1;
|
|
flagZero(result16&0x00FF);
|
|
flagNegative(result16&0x00FF);
|
|
flagCarry(result16);
|
|
A = result16&0x00FF;
|
|
goto *opcodes[read8(PC++)];
|
|
ORA_ABS:
|
|
A |= read8(a_abs());
|
|
flagZero(A);
|
|
flagNegative(A);
|
|
goto *opcodes[read8(PC++)];
|
|
ASL_ABS:
|
|
ptr = a_abs();
|
|
value16 = read8(ptr);
|
|
result16 = value16<<1;
|
|
flagZero(result16&0x00FF);
|
|
flagNegative(result16&0x00FF);
|
|
flagCarry(result16);
|
|
write8(ptr, result16&0x00FF);
|
|
goto *opcodes[read8(PC++)];
|
|
BPL_REL:
|
|
if(!(SR&SR_NEG)) PC += a_rel();
|
|
goto *opcodes[read8(PC++)];
|
|
ORA_INDY:
|
|
A |= read8(a_indy());
|
|
flagZero(A);
|
|
flagNegative(A);
|
|
goto *opcodes[read8(PC++)];
|
|
ORA_ZPGX:
|
|
A |= read8(a_zpgx());
|
|
flagZero(A);
|
|
flagNegative(A);
|
|
goto *opcodes[read8(PC++)];
|
|
ASL_ZPGX:
|
|
ptr = a_zpgx();
|
|
value16 = read8(ptr);
|
|
result16 = value16<<1;
|
|
flagZero(result16&0x00FF);
|
|
flagNegative(result16&0x00FF);
|
|
flagCarry(result16);
|
|
write8(ptr, result16&0x00FF);
|
|
goto *opcodes[read8(PC++)];
|
|
CLC:
|
|
SR &= ~SR_CARRY;
|
|
goto *opcodes[read8(PC++)];
|
|
ORA_ABSY:
|
|
A |= read8(a_absy());
|
|
flagZero(A);
|
|
flagNegative(A);
|
|
goto *opcodes[read8(PC++)];
|
|
ORA_ABSX:
|
|
A |= read8(a_absx());
|
|
flagZero(A);
|
|
flagNegative(A);
|
|
goto *opcodes[read8(PC++)];
|
|
ASL_ABSX:
|
|
ptr = a_absx();
|
|
value16 = read8(ptr);
|
|
result16 = value16<<1;
|
|
flagZero(result16&0x00FF);
|
|
flagNegative(result16&0x00FF);
|
|
flagCarry(result16);
|
|
write8(ptr, result16&0x00FF);
|
|
goto *opcodes[read8(PC++)];
|
|
JSR_ABS:
|
|
push16(PC-1);
|
|
PC = a_abs();
|
|
goto *opcodes[read8(PC++)];
|
|
AND_INDX:
|
|
A &= read8(a_indx());
|
|
flagZero(A);
|
|
flagNegative(A);
|
|
goto *opcodes[read8(PC++)];
|
|
BIT_ZPG:
|
|
value8 = read8(a_zpg());
|
|
result8 = A & value8;
|
|
flagZero(result8);
|
|
SR = (SR&0x3F) | (value8&0xC0);
|
|
goto *opcodes[read8(PC++)];
|
|
AND_ZPG:
|
|
A &= read8(a_zpg());
|
|
flagZero(A);
|
|
flagNegative(A);
|
|
goto *opcodes[read8(PC++)];
|
|
ROL_ZPG:
|
|
ptr = a_zpg();
|
|
value16 = read8(ptr);
|
|
result16 = (value16 << 1) | (SR&SR_CARRY);
|
|
flagZero(result16&0x00FF);
|
|
flagNegative(result16&0x00FF);
|
|
flagCarry(result16);
|
|
write8(ptr, result16&0x00FF);
|
|
goto *opcodes[read8(PC++)];
|
|
PLP:
|
|
SR = pull8() | SR_FIXED_BITS;
|
|
goto *opcodes[read8(PC++)];
|
|
AND_IMM:
|
|
A &= read8(a_imm());
|
|
flagZero(A);
|
|
flagNegative(A);
|
|
goto *opcodes[read8(PC++)];
|
|
ROL_A:
|
|
value16 = A;
|
|
result16 = (value16 << 1) | (SR&SR_CARRY);
|
|
flagZero(result16&0x00FF);
|
|
flagNegative(result16&0x00FF);
|
|
flagCarry(result16);
|
|
A = result16&0x00FF;
|
|
goto *opcodes[read8(PC++)];
|
|
BIT_ABS:
|
|
value8 = read8(a_abs());
|
|
result8 = A & value8;
|
|
flagZero(result8);
|
|
SR = (SR&0x3F) | (value8&0xC0);
|
|
goto *opcodes[read8(PC++)];
|
|
AND_ABS:
|
|
A &= read8(a_abs());
|
|
flagZero(A);
|
|
flagNegative(A);
|
|
goto *opcodes[read8(PC++)];
|
|
ROL_ABS:
|
|
ptr = a_abs();
|
|
value16 = read8(ptr);
|
|
result16 = (value16 << 1) | (SR&SR_CARRY);
|
|
flagZero(result16&0x00FF);
|
|
flagNegative(result16&0x00FF);
|
|
flagCarry(result16);
|
|
write8(ptr, result16&0x00FF);
|
|
goto *opcodes[read8(PC++)];
|
|
|
|
// -- Undefined Opcodes
|
|
UNDF:
|
|
// Raise an error
|
|
goto *opcodes[read8(PC++)];
|
|
}
|