forked from rebecca/BSX
1
0
Fork 0
BSX/src/dispatch.c

226 lines
5.5 KiB
C

/*
* lib65816/dispatch.c Release 1p1
* See LICENSE for more details.
*
* Code originally from XGS: Apple IIGS Emulator (dispatch.c)
*
* Originally written and Copyright (C)1996 by Joshua M. Thompson
* Copyright (C) 2006 by Samuel A. Falvo II
*
* Modified for greater portability and virtual hardware independence.
*
* Copyright (C) 2024 by Rebecca Buckingham
* highly modified to integrate with bsx emulator.
*/
#define CPU_DISPATCH
#include "cpu.h"
#include "cpumicro.h"
#include "util.h"
#include <stdint.h>
int dispatch_quit = 0;
dualw A; /* Accumulator */
dualw D; /* Direct Page Register */
byte P; /* Processor Status Register */
int E; /* Emulation Mode Flag */
dualw S; /* Stack Pointer */
dualw X; /* X Index Register */
dualw Y; /* Y Index Register */
byte DB; /* Data Bank Register */
union {
#ifdef WORDS_BIGENDIAN
struct { byte Z,PB,H,L; } B;
struct { word16 Z,PC; } W;
#else
struct { byte L,H,PB,Z; } B;
struct { word16 PC,Z; } W;
#endif
word32 A;
} PC;
duala atmp,opaddr;
dualw wtmp,otmp,operand;
int a1,a2,a3,a4,o1,o2,o3,o4;
void (**cpu_curr_opcode_table)();
extern int cpu_reset,cpu_abort,cpu_nmi,cpu_irq,cpu_stop,cpu_wait,cpu_trace;
extern int cpu_irne64,cpu_irqt5;
extern int cpu_update_period;
extern void (*cpu_opcode_table[1310])();
uint64_t last_update, next_update;
#define RESET_OP 256
#define ABORT_OP 257
#define NMI_OP 258
#define IRQ_OP 259
#define IRNE64_OP 260
#define IRQT5_OP 261
void handleSignal(int type) {
(**cpu_curr_opcode_table[type])();
}
void doUpdate() {
E_UPDATE(cpu_cycle_count);
last_update = cpu_cycle_count;
next_update = last_update + cpu_update_period;
}
void CPU_init(void) {
last_update = 0;
next_update = cpu_update_period;
cpu_cycle_count = 0;
E = 1;
F_setM(1);
F_setX(1);
CPU_modeSwitch();
}
void CPU_step(void) {
if (cpu_cycle_count >= next_update) doUpdate();
int opcode = M_READ_OPCODE(PC.A);
PC.W.PC++;
(**cpu_curr_opcode_table[opcode])();
}
void CPU_run(void) {
while (!dispatch_quit) {
if (cpu_trace) CPU_debug();
if (cpu_reset) { handleSignal(RESET_OP); continue; }
if (cpu_abort) { handleSignal(ABORT_OP); continue; }
if (cpu_nmi) { handleSignal(NMI_OP); continue; }
if (cpu_irq) { handleSignal(IRQ_OP); continue; }
if (cpu_irne64) { handleSignal(IRNE64_OP); continue; }
if (cpu_irqt5) { handleSignal(IRQT5_OP); continue; }
if (cpu_wait) { cpu_cycle_count++; continue; }
if (cpu_stop) continue;
CPU_step();
}
}
// void old_CPU_run(void)
// {
// word32 last_update,next_update;
// int opcode;
// #ifdef LIMIT_INSTRUCTION_COUNT
// long instructionCount = 0;
// #endif
// cpu_cycle_count = 0;
// last_update = 0;
// next_update = cpu_update_period;
// E = 1;
// F_setM(1);
// F_setX(1);
// CPU_modeSwitch();
// dispatch:
// // CPUEvent_elapse( cpu_cycle_count );
// // cpu_cycle_count = 0;
// if (dispatch_quit)
// return;
// // TODO remove this.
// #ifdef LIMIT_INSTRUCTION_COUNT
// instructionCount++;
// if (instructionCount > LIMIT_INSTRUCTION_COUNT)
// return;
// #endif
// // #ifdef E_UPDATE
// if (cpu_cycle_count >= next_update) goto update;
// update_resume:
// // #endif
// #ifdef DEBUG
// if (cpu_trace) goto debug;
// debug_resume:
// #endif
// if (cpu_reset) goto reset;
// if (cpu_stop) goto dispatch;
// if (cpu_abort) goto abort;
// if (cpu_nmi) goto nmi;
// if (cpu_irq) goto irq;
// if (cpu_irne64) goto irne64;
// if (cpu_irqt5) goto irqt5;
// irq_return:
// if (cpu_wait) { cpu_cycle_count++; goto dispatch; }
// opcode = M_READ_OPCODE(PC.A);
// PC.W.PC++;
// #ifdef OLDCYCLES
// cpu_cycle_count += cpu_curr_cycle_table[opcode];
// #endif
// (**cpu_curr_opcode_table[opcode])();
// goto dispatch;
// /* Special cases. Since these don't happen a lot more often than they */
// /* do happen, accessing them this way means most of the time the */
// /* generated code is _not_ branching. Only during the special cases do */
// /* we take the branch penalty (if there is one). */
// // #ifdef E_UPDATE
// update:
// E_UPDATE(cpu_cycle_count);
// last_update = cpu_cycle_count;
// next_update = last_update + cpu_update_period;
// goto update_resume;
// // #endif
// #ifdef DEBUG
// debug:
// CPU_debug();
// goto debug_resume;
// #endif
// reset:
// (**cpu_curr_opcode_table[256])();
// goto dispatch;
// abort:
// (**cpu_curr_opcode_table[257])();
// goto dispatch;
// nmi:
// (**cpu_curr_opcode_table[258])();
// goto dispatch;
// irq:
// if (P & 0x04) goto irq_return;
// (**cpu_curr_opcode_table[259])();
// goto dispatch;
// irne64:
// if (P & 0x04) goto irq_return;
// (**cpu_curr_opcode_table[260])();
// goto dispatch;
// irqt5:
// if (P & 0x04) goto irq_return;
// (**cpu_curr_opcode_table[261])();
// goto dispatch;
// }
/* Recalculate opcode_offset based on the new processor mode */
void CPU_modeSwitch(void) {
int opcode_offset;
if (E) {
opcode_offset = 1048;
} else {
if (F_getX) {
X.B.H = 0;
Y.B.H = 0;
}
opcode_offset = ((~P >> 4) & 0x03) * 262;
}
#ifdef OLDCYCLES
cpu_curr_cycle_table = cpu_cycle_table + opcode_offset;
#endif
cpu_curr_opcode_table = cpu_opcode_table + opcode_offset;
}