mirror of
https://github.com/DavidBuchanan314/6502-emu.git
synced 2024-09-28 03:55:19 +00:00
Created CPU struct to allow multiple instances of running processors at the same time
* note: this is not multithreading; it simply allows a program to step through more than one CPU in the same process
This commit is contained in:
parent
60a354d64c
commit
2d30a08daf
24
6502-emu.c
24
6502-emu.c
@ -19,21 +19,21 @@ void step_delay()
|
|||||||
nanosleep(&req, &rem);
|
nanosleep(&req, &rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_cpu(long cycle_stop, int verbose, int mem_dump, int break_pc, int fast)
|
void run_cpu(CPU * cpu, long cycle_stop, int verbose, int mem_dump, int break_pc, int fast)
|
||||||
{
|
{
|
||||||
long cycles = 0;
|
long cycles = 0;
|
||||||
int cycles_per_step = (CPU_FREQ / (ONE_SECOND / STEP_DURATION));
|
int cycles_per_step = (CPU_FREQ / (ONE_SECOND / STEP_DURATION));
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for (cycles %= cycles_per_step; cycles < cycles_per_step;) {
|
for (cycles %= cycles_per_step; cycles < cycles_per_step;) {
|
||||||
if (mem_dump) save_memory(NULL);
|
if (mem_dump) save_memory(cpu, NULL);
|
||||||
cycles += step_cpu(verbose);
|
cycles += step_cpu(cpu, verbose);
|
||||||
if ((cycle_stop > 0) && (total_cycles >= cycle_stop)) goto end;
|
if ((cycle_stop > 0) && (cpu->total_cycles >= cycle_stop)) goto end;
|
||||||
step_uart();
|
step_uart();
|
||||||
|
|
||||||
if (break_pc >= 0 && PC == (uint16_t)break_pc) {
|
if (break_pc >= 0 && cpu->PC == (uint16_t)break_pc) {
|
||||||
fprintf(stderr, "break at %04x\n", break_pc);
|
fprintf(stderr, "break at %04x\n", break_pc);
|
||||||
save_memory(NULL);
|
save_memory(cpu, NULL);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,6 +96,7 @@ int main(int argc, char *argv[])
|
|||||||
int verbose, interactive, mem_dump, break_pc, fast;
|
int verbose, interactive, mem_dump, break_pc, fast;
|
||||||
long cycles;
|
long cycles;
|
||||||
int opt;
|
int opt;
|
||||||
|
CPU *cpu;
|
||||||
|
|
||||||
verbose = 0;
|
verbose = 0;
|
||||||
interactive = 0;
|
interactive = 0;
|
||||||
@ -164,7 +165,11 @@ int main(int argc, char *argv[])
|
|||||||
usage(argv);
|
usage(argv);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (load_rom(argv[optind], load_addr) != 0) {
|
|
||||||
|
cpu = create_cpu();
|
||||||
|
init_uart(cpu);
|
||||||
|
|
||||||
|
if (load_rom(cpu, argv[optind], load_addr) != 0) {
|
||||||
printf("Error loading \"%s\".\n", argv[optind]);
|
printf("Error loading \"%s\".\n", argv[optind]);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
@ -172,10 +177,9 @@ int main(int argc, char *argv[])
|
|||||||
if (interactive) raw_stdin(); // allow individual keystrokes to be detected
|
if (interactive) raw_stdin(); // allow individual keystrokes to be detected
|
||||||
|
|
||||||
init_tables();
|
init_tables();
|
||||||
init_uart();
|
|
||||||
|
|
||||||
reset_cpu(a, x, y, sp, sr, pc);
|
reset_cpu(cpu, a, x, y, sp, sr, pc);
|
||||||
run_cpu(cycles, verbose, mem_dump, break_pc, fast);
|
run_cpu(cpu, cycles, verbose, mem_dump, break_pc, fast);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
40
6502.h
40
6502.h
@ -10,18 +10,6 @@
|
|||||||
#define RST_VEC 0xFFFC
|
#define RST_VEC 0xFFFC
|
||||||
#define IRQ_VEC 0xFFFE
|
#define IRQ_VEC 0xFFFE
|
||||||
|
|
||||||
uint8_t memory[1<<16];
|
|
||||||
uint8_t A;
|
|
||||||
uint8_t X;
|
|
||||||
uint8_t Y;
|
|
||||||
uint16_t PC;
|
|
||||||
uint8_t SP; // points to first empty stack location
|
|
||||||
uint8_t extra_cycles;
|
|
||||||
uint64_t total_cycles;
|
|
||||||
|
|
||||||
void * read_addr;
|
|
||||||
void * write_addr;
|
|
||||||
|
|
||||||
struct StatusBits{
|
struct StatusBits{
|
||||||
bool carry:1; // bit 0
|
bool carry:1; // bit 0
|
||||||
bool zero:1;
|
bool zero:1;
|
||||||
@ -38,7 +26,21 @@ union StatusReg { // this means we can access the status register as a byte, or
|
|||||||
uint8_t byte;
|
uint8_t byte;
|
||||||
};
|
};
|
||||||
|
|
||||||
union StatusReg SR;
|
typedef struct {
|
||||||
|
uint8_t memory[1<<16];
|
||||||
|
uint8_t A;
|
||||||
|
uint8_t X;
|
||||||
|
uint8_t Y;
|
||||||
|
uint16_t PC;
|
||||||
|
uint8_t SP; // points to first empty stack location
|
||||||
|
uint8_t extra_cycles;
|
||||||
|
uint64_t total_cycles;
|
||||||
|
union StatusReg SR;
|
||||||
|
|
||||||
|
void * read_addr;
|
||||||
|
void * write_addr;
|
||||||
|
int jumping; // used to check that we don't need to increment the PC after a jump
|
||||||
|
} CPU;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ACC,
|
ACC,
|
||||||
@ -59,7 +61,7 @@ typedef enum {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char * mnemonic;
|
char * mnemonic;
|
||||||
void (*function)();
|
void (*function)(CPU *);
|
||||||
Mode mode;
|
Mode mode;
|
||||||
uint8_t cycles;
|
uint8_t cycles;
|
||||||
} Instruction;
|
} Instruction;
|
||||||
@ -68,10 +70,12 @@ Instruction instructions[0x100];
|
|||||||
|
|
||||||
void init_tables();
|
void init_tables();
|
||||||
|
|
||||||
void reset_cpu(int _a, int _x, int _y, int _sp, int _sr, int _pc);
|
void reset_cpu(CPU *cpu, int _a, int _x, int _y, int _sp, int _sr, int _pc);
|
||||||
|
|
||||||
int load_rom(char * filename, int load_addr);
|
int load_rom(CPU *cpu, char * filename, int load_addr);
|
||||||
|
|
||||||
int step_cpu(int verbose);
|
int step_cpu(CPU *cpu, int verbose);
|
||||||
|
|
||||||
void save_memory(char * filename);
|
void save_memory(CPU *cpu, char * filename);
|
||||||
|
|
||||||
|
CPU * create_cpu();
|
||||||
|
22
6850.c
22
6850.c
@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
void init_uart() {
|
void init_uart(CPU *cpu) {
|
||||||
memory[DATA_ADDR] = 0;
|
cpu->memory[DATA_ADDR] = 0;
|
||||||
|
|
||||||
uart_SR.byte = 0;
|
uart_SR.byte = 0;
|
||||||
uart_SR.bits.TDRE = 1; // we are always ready to output data
|
uart_SR.bits.TDRE = 1; // we are always ready to output data
|
||||||
@ -26,15 +26,15 @@ int stdin_ready() {
|
|||||||
return poll(&fds, 1, 0) == 1; // timeout = 0
|
return poll(&fds, 1, 0) == 1; // timeout = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
void step_uart() {
|
void step_uart(CPU *cpu) {
|
||||||
if (write_addr == &memory[DATA_ADDR]) {
|
if (cpu->write_addr == &cpu->memory[DATA_ADDR]) {
|
||||||
putchar(memory[DATA_ADDR]);
|
putchar(cpu->memory[DATA_ADDR]);
|
||||||
if (memory[DATA_ADDR] == '\b') printf(" \b");
|
if (cpu->memory[DATA_ADDR] == '\b') printf(" \b");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
write_addr = NULL;
|
cpu->write_addr = NULL;
|
||||||
} else if (read_addr == &memory[DATA_ADDR]) {
|
} else if (cpu->read_addr == &cpu->memory[DATA_ADDR]) {
|
||||||
uart_SR.bits.RDRF = 0;
|
uart_SR.bits.RDRF = 0;
|
||||||
read_addr = NULL;
|
cpu->read_addr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update input register if empty */
|
/* update input register if empty */
|
||||||
@ -54,6 +54,6 @@ void step_uart() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memory[DATA_ADDR] = incoming_char;
|
cpu->memory[DATA_ADDR] = incoming_char;
|
||||||
memory[CTRL_ADDR] = uart_SR.byte;
|
cpu->memory[CTRL_ADDR] = uart_SR.byte;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user