Преглед на файлове

Fix interrupt support

- Passes Klaus Dormann's interrupt tests
master
Nathaniel Walizer преди 1 година
родител
ревизия
be41dcfe91
променени са 2 файла, в които са добавени 142 реда и са изтрити 35 реда
  1. +104
    -28
      e6502.c
  2. +38
    -7
      e6502.h

+ 104
- 28
e6502.c Целия файл

@@ -6,48 +6,81 @@

// Instruction Addressing

typedef uint16_t e6502_Address;
#ifdef E6502_POLL_MEM

typedef uint8_t* e6502_Address;

static inline e6502_Address e6502_mem_adr(e6502_Core* core,
e6502_Mem_Addr adr) {
// return &core->memory[adr];
return adr;
return &core->memory[adr];
}

static inline e6502_Mem_Addr e6502_adr_mem(e6502_Core* core,
e6502_Address adr) {
// return (adr - core->memory);
return adr;
return (adr - core->memory);
}

static inline uint8_t e6502_adr_r8(e6502_Core* core,
e6502_Address adr) {
return &adr[0];
}

static inline uint8_t e6502_adr_r16(e6502_Core* core,
e6502_Address adr) {
return (&adr[0] | ((uint16_t)&adr[1] << 8));
}

static inline void e6502_adr_w8(e6502_Core* core,
e6502_Address adr,
uint8_t val) {
&adr[0] = val;
}

static inline void e6502_adr_w16(e6502_Core* core,
e6502_Address adr,
uint16_t val) {
&adr[0] = val;
&adr[1] = val >> 8;
}

#else // !E6502_POLL_MEM

typedef uint16_t e6502_Address;

static inline e6502_Address e6502_mem_adr(e6502_Core*,
e6502_Mem_Addr adr) {
return adr;
}

static inline e6502_Mem_Addr e6502_adr_mem(e6502_Core*,
e6502_Address adr) {
return adr;
}

static inline uint8_t e6502_adr_r8(e6502_Core* core,
e6502_Address adr) {
// return *adr;
return e6502_r8(core, adr);
}

static inline uint8_t e6502_adr_r16(e6502_Core* core,
e6502_Address adr) {
// return *(uint16_t*)adr;
return e6502_r16(core, adr);
}

static inline void e6502_adr_w8(e6502_Core* core,
e6502_Address adr,
uint8_t val) {
// *adr = val;
e6502_w8(core, adr, val);
}

static inline void e6502_adr_w16(e6502_Core* core,
e6502_Address adr,
uint16_t val) {
// *(uint16_t*)adr = val;
e6502_w16(core, adr,val);
}

#endif // !E6502_POLL_MEM


// Read values after opcodes

@@ -153,7 +186,9 @@ static inline void brk(e6502_Core *core, e6502_Address) {
}

static inline void rti(e6502_Core *core, e6502_Address) {
core->registers.P = e6502_pop8(core) & ~(e6502_Status_B);
core->registers.P = e6502_pop8(core) |
e6502_Status_1 |
e6502_Status_B;
core->registers.PC = e6502_pop16(core);
}

@@ -387,14 +422,14 @@ static inline void jsr(e6502_Core *core, e6502_Address adr) {
core->registers.PC = e6502_adr_mem(core, adr);
}

static inline void rts(e6502_Core *core, e6502_Address) {
core->registers.PC = e6502_pop16(core) + 1;
}

static inline void jmp(e6502_Core *core, e6502_Address adr) {
core->registers.PC = e6502_adr_mem(core, adr);
}

static inline void rts(e6502_Core *core, e6502_Address) {
core->registers.PC = e6502_pop16(core) + 1;
}

static inline void bit(e6502_Core *core, e6502_Address adr) {
uint8_t val = e6502_adr_r8(core, adr);
core->registers.P &= ~(e6502_Status_Z |
@@ -865,6 +900,26 @@ int e6502_dump_regs(e6502_Core* core, FILE* file) {
}
#endif


static void e6502_irq(e6502_Core* core) {
if (!(core->registers.P & e6502_Status_I)) {
e6502_push16(core, core->registers.PC);
e6502_push8(core, (core->registers.P & ~e6502_Status_B) |
e6502_Status_1);
core->registers.P |= e6502_Status_I;
core->registers.PC = e6502_r16(core, e6502_IRQ_Vec);
}
}

static void e6502_nmi(e6502_Core* core) {
e6502_push16(core, core->registers.PC);
e6502_push8(core, (core->registers.P & ~e6502_Status_B) |
e6502_Status_1);
core->registers.P |= e6502_Status_I;
core->registers.PC = e6502_r16(core, e6502_NMI_Vec);
}


int e6502_run(e6502_Core* core,
int remaining,
int* run,
@@ -895,20 +950,31 @@ int e6502_run(e6502_Core* core,
e6502_Address adr = instr->address(core);
#ifdef E6502_DEBUG
uint16_t size = core->registers.PC - last_pc;
uint16_t val = 0;
if (size > 1) {
if (size == 2) val = e6502_r8(core, last_pc + 1);
else val = e6502_r16(core, last_pc + 1);
}
e6502_dump_regs(core, stdout);
fprintf(stdout, "$%04x: $%02x", last_pc, opcode);
if (size > 1) {
fprintf(stdout, size == 2 ? " $%02x" : " $%04x",
val);
}
fputc('\n', stdout);
#endif
instr->operator(core, adr);
core->cycle += instr->cycles;
i_count++;
#ifdef E6502_DEBUG
fprintf(stdout, "$%04x: $%02x", last_pc, opcode);
if (size == 2) {
fprintf(stdout, " $%02x", e6502_r8(core, last_pc + 1));
} else if (size == 3) {
fprintf(stdout, " $%02x%02x", e6502_r8(core, last_pc + 2), e6502_r8(core, last_pc + 1));

if ( (core->pins & e6502_Pin_NMI) &&
!(core->pins & e6502_NMI_Serviced)) {
core->pins |= e6502_NMI_Serviced;
e6502_nmi(core);
} else if ( (core->pins & e6502_Pin_IRQ) &&
!(core->registers.P & e6502_Status_I)) {
e6502_irq(core);
}
fputc('\n', stdout);
e6502_dump_regs(core, stdout);
#endif
}
}
if (run) {
@@ -917,15 +983,25 @@ int e6502_run(e6502_Core* core,
return status;
}

void e6502_init(e6502_Core* core, e6502_Read read,
e6502_Write write, void* context) {
core->bus_read = read;
core->bus_write = write;
core->bus_context = context;
}

void e6502_reset(e6502_Core* core) {
core->registers.PC = e6502_r16(core, e6502_Reset_Vec);
core->registers.S -= 3;
core->registers.P |= (e6502_Status_B | e6502_Status_1);
}

void e6502_init(e6502_Core* core, e6502_Read read,
e6502_Write write, void* context) {
core->bus_read = read;
core->bus_write = write;
core->bus_context = context;
void e6502_set_nmi(e6502_Core* core, int active) {
if (active) core->pins |= e6502_Pin_NMI;
else core->pins &= ~(e6502_Pin_NMI | e6502_NMI_Serviced);
}

void e6502_set_irq(e6502_Core* core, int active) {
if (active) core->pins |= e6502_Pin_IRQ;
else core->pins &= ~e6502_Pin_IRQ;
}

+ 38
- 7
e6502.h Целия файл

@@ -12,6 +12,13 @@ typedef enum {
e6502_Status_N = 0b10000000,
} e6502_Status_Flag;

typedef enum {
e6502_Pin_NMI = 0b01,
e6502_Pin_IRQ = 0b10,

e6502_NMI_Serviced = 0b10000000
} e6502_Pin;

typedef struct {
uint16_t PC;
uint8_t S;
@@ -23,14 +30,21 @@ typedef struct {

typedef uint16_t e6502_Mem_Addr;

#ifndef E6502_POLL_MEM
typedef uint8_t(e6502_Read)(void*, e6502_Mem_Addr);
typedef void(e6502_Write)(void*, e6502_Mem_Addr, uint8_t);
#endif

typedef struct {
e6502_Registers registers;
e6502_Pin pins;
#ifdef E6502_POLL_MEM
uint8_t memory[65536];
#else
e6502_Read* bus_read;
e6502_Write* bus_write;
void* bus_context;
#endif
int cycle;
} e6502_Core;

@@ -40,27 +54,34 @@ typedef struct {
#define e6502_Reset_Vec (0xFFFCU)
#define e6502_NMI_Vec (0xFFFAU)

void e6502_init(e6502_Core*, e6502_Read, e6502_Write, void*);
#ifdef E6502_POLL_MEM

/*
uint8_t e6502_r8(e6502_Core* core, e6502_Mem_Addr adr);
static inline uint8_t e6502_r8(e6502_Core* core,
e6502_Mem_Addr adr) {
return core->memory[adr];
}

void e6502_w8(e6502_Core* core, e6502_Mem_Addr adr, uint8_t val);
*/
static inline void e6502_w8(e6502_Core* core,
e6502_Mem_Addr adr,
uint8_t val) {
core->memory[adr] = val;
}

#else

static inline uint8_t e6502_r8(e6502_Core* core,
e6502_Mem_Addr adr) {
// return core->memory[adr];
return core->bus_read(core->bus_context, adr);
}

static inline void e6502_w8(e6502_Core* core,
e6502_Mem_Addr adr,
uint8_t val) {
// core->memory[adr] = val;
return core->bus_write(core->bus_context, adr, val);
}

#endif

static inline uint16_t e6502_r16(e6502_Core* core,
e6502_Mem_Addr adr) {
return e6502_r8(core, adr) |
@@ -93,9 +114,19 @@ static inline uint16_t e6502_pop16(e6502_Core* core) {
}


#ifdef E6502_POLL_MEM
void e6502_init(e6502_Core*);
#else
void e6502_init(e6502_Core*, e6502_Read, e6502_Write, void*);
#endif

int e6502_run(e6502_Core* core,
int remaining,
int* run,
int instructions);

void e6502_reset(e6502_Core* core);

void e6502_set_irq(e6502_Core* core, int active);

void e6502_set_nmi(e6502_Core* core, int active);

Loading…
Отказ
Запис