6502-sim/cpu.c
2023-06-15 17:08:20 +00:00

235 lines
5.2 KiB
C

#include <assert.h>
#include "cpu.h"
#include "opcodes.h"
extern void reset6502(void);
extern void step6502(void);
uint8_t cpu_memory[65536] = {
[0xfffc] = 0x0,
[0xfffd] = 0x0,
};
uint8_t read6502(uint16_t address)
{
return cpu_memory[address];
}
void write6502(uint16_t address, uint8_t value)
{
cpu_memory[address] = value;
}
extern uint16_t pc;
extern uint8_t sp, a, x, y, status;
cpu_history_t cpu_history[65536] = { 0 };
int cpu_history_len;
int cpu_history_ix;
void cpu_get_state(cpu_state_t * state) {
*state = (cpu_state_t){
.a = a,
.y = y,
.x = x,
.pc = pc,
.sp = sp,
.status = status,
};
}
static inline void update_history(void)
{
instruction_t instruction = decode_ins[cpu_memory[pc]];
addressing_mode_t addressing_mode = addressing_modes[instruction.mode];
if (cpu_history_len < 65536)
cpu_history_len++;
cpu_history[cpu_history_ix] = (cpu_history_t){
.state = (cpu_state_t){
.a = a,
.y = y,
.x = x,
.pc = pc,
.sp = sp,
.status = status,
},
.pc_mem = { cpu_memory[pc], cpu_memory[pc+1], cpu_memory[pc+2] },
.value = (addressing_mode.func)(pc),
};
cpu_history_ix = (cpu_history_ix + 1) & 0xffff;
}
void cpu_reset(void)
{
reset6502();
cpu_history_len = 0;
cpu_history_ix = 0;
}
void cpu_step(void)
{
update_history();
step6502();
}
static uint8_t * mem = cpu_memory;
uint16_t absolute(uint16_t _pc)
{
uint16_t effective = ((uint16_t)mem[_pc + 2] << 8) | ((uint16_t)mem[_pc + 1] << 0);
return effective;
}
uint16_t absolute_indexed_indirect(uint16_t _pc)
{
uint16_t effective = (((uint16_t)mem[_pc + 2] << 8) | ((uint16_t)mem[_pc + 1] << 0))
+ x;
uint16_t indirect = ((uint16_t)mem[effective + 1] << 8)
| ((uint16_t)mem[effective + 0] << 0);
return indirect;
}
uint16_t absolute_indexed_with_x(uint16_t _pc)
{
uint16_t effective = (((uint16_t)mem[_pc + 2] << 8) | ((uint16_t)mem[_pc + 1] << 0))
+ x;
return effective;
}
uint16_t absolute_indexed_with_y(uint16_t _pc)
{
uint16_t effective = (((uint16_t)mem[_pc + 2] << 8) | ((uint16_t)mem[_pc + 1] << 0))
+ y;
return effective;
}
uint16_t absolute_indirect(uint16_t _pc)
{
uint16_t effective = (((uint16_t)mem[_pc + 2] << 8) | ((uint16_t)mem[_pc + 1] << 0))
+ y;
uint16_t indirect = ((uint16_t)mem[effective + 1] << 8)
| ((uint16_t)mem[effective + 0] << 0);
return indirect;
}
uint16_t accumulator(uint16_t _pc)
{
return a;
}
uint16_t immediate(uint16_t _pc)
{
return (uint8_t)mem[_pc + 1];
}
uint16_t implied(uint16_t _pc)
{
return 0; // ???
}
uint16_t program_counter_relative(uint16_t _pc)
{
uint16_t effective = _pc + 2 + ((int8_t)mem[_pc + 1]);
return effective;
}
uint16_t stack(uint16_t _pc)
{
uint16_t effective = (0x01 << 8) | (sp << 0);
return effective;
}
uint16_t zero_page(uint16_t _pc)
{
uint16_t effective = (0x00 << 8) | ((uint16_t)mem[_pc + 1] << 0);
return effective;
}
uint16_t zero_page_indexed_indirect(uint16_t _pc)
{
uint8_t base = x + ((uint8_t)mem[_pc + 1] << 0);
uint16_t effective = (0x00 << 8) | base;
uint16_t indirect = ((uint16_t)mem[effective + 1] << 8)
| ((uint16_t)mem[effective + 0] << 0);
return indirect;
}
uint16_t zero_page_indexed_with_x(uint16_t _pc)
{
uint8_t base = x + ((uint8_t)mem[_pc + 1] << 0);
uint16_t effective = (0x00 << 8) | base;
return effective;
}
uint16_t zero_page_indexed_with_y(uint16_t _pc)
{
uint8_t base = y + ((uint8_t)mem[_pc + 1] << 0);
uint16_t effective = (0x00 << 8) | base;
return effective;
}
uint16_t zero_page_indirect(uint16_t _pc)
{
uint8_t base = ((uint8_t)mem[_pc + 1] << 0);
uint16_t effective = (0x00 << 8) | base;
uint16_t indirect = ((uint16_t)mem[effective + 1] << 8)
| ((uint16_t)mem[effective + 0] << 0);
return indirect;
}
uint16_t zero_page_indirect_indexed_with_y(uint16_t _pc)
{
uint8_t base = ((uint8_t)mem[_pc + 1] << 0);
uint16_t indirect = ((uint16_t)mem[base + 1] << 8)
| ((uint16_t)mem[base + 0] << 0);
uint16_t effective = indirect + y;
return effective;
}
addressing_mode_t addressing_modes[16] = {
[A] = { .alen = 2, .olen = 2, .func = absolute },
[AII] = { .alen = 2, .olen = 2, .func = absolute_indexed_indirect },
[AIX] = { .alen = 2, .olen = 2, .func = absolute_indexed_with_x },
[AIY] = { .alen = 2, .olen = 2, .func = absolute_indexed_with_y },
[AI] = { .alen = 2, .olen = 2, .func = absolute_indirect },
[ACC] = { .alen = 0, .olen = 1, .func = accumulator },
[IMM] = { .alen = 1, .olen = 1, .func = immediate },
[I] = { .alen = 0, .olen = 0, .func = implied },
[R] = { .alen = 1, .olen = 2, .func = program_counter_relative },
[S] = { .alen = 0, .olen = 2, .func = stack },
[ZP] = { .alen = 1, .olen = 2, .func = zero_page },
[ZPII] = { .alen = 1, .olen = 2, .func = zero_page_indexed_indirect },
[ZPX] = { .alen = 1, .olen = 2, .func = zero_page_indexed_with_x },
[ZPY] = { .alen = 1, .olen = 2, .func = zero_page_indexed_with_y },
[ZPI] = { .alen = 1, .olen = 2, .func = zero_page_indirect },
[ZPIY] = { .alen = 1, .olen = 2, .func = zero_page_indirect_indexed_with_y },
};