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:
Rob McMullen 2017-12-16 22:31:48 -08:00
parent 60a354d64c
commit 2d30a08daf
5 changed files with 390 additions and 374 deletions

View File

@ -19,21 +19,21 @@ void step_delay()
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;
int cycles_per_step = (CPU_FREQ / (ONE_SECOND / STEP_DURATION));
for (;;) {
for (cycles %= cycles_per_step; cycles < cycles_per_step;) {
if (mem_dump) save_memory(NULL);
cycles += step_cpu(verbose);
if ((cycle_stop > 0) && (total_cycles >= cycle_stop)) goto end;
if (mem_dump) save_memory(cpu, NULL);
cycles += step_cpu(cpu, verbose);
if ((cycle_stop > 0) && (cpu->total_cycles >= cycle_stop)) goto end;
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);
save_memory(NULL);
save_memory(cpu, NULL);
goto end;
}
}
@ -96,6 +96,7 @@ int main(int argc, char *argv[])
int verbose, interactive, mem_dump, break_pc, fast;
long cycles;
int opt;
CPU *cpu;
verbose = 0;
interactive = 0;
@ -164,7 +165,11 @@ int main(int argc, char *argv[])
usage(argv);
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]);
return EXIT_FAILURE;
}
@ -172,10 +177,9 @@ int main(int argc, char *argv[])
if (interactive) raw_stdin(); // allow individual keystrokes to be detected
init_tables();
init_uart();
reset_cpu(a, x, y, sp, sr, pc);
run_cpu(cycles, verbose, mem_dump, break_pc, fast);
reset_cpu(cpu, a, x, y, sp, sr, pc);
run_cpu(cpu, cycles, verbose, mem_dump, break_pc, fast);
return EXIT_SUCCESS;
}

676
6502.c

File diff suppressed because it is too large Load Diff

40
6502.h
View File

@ -10,18 +10,6 @@
#define RST_VEC 0xFFFC
#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{
bool carry:1; // bit 0
bool zero:1;
@ -38,7 +26,21 @@ union StatusReg { // this means we can access the status register as a byte, or
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 {
ACC,
@ -59,7 +61,7 @@ typedef enum {
typedef struct {
char * mnemonic;
void (*function)();
void (*function)(CPU *);
Mode mode;
uint8_t cycles;
} Instruction;
@ -68,10 +70,12 @@ Instruction instructions[0x100];
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
View File

@ -8,8 +8,8 @@
int n;
void init_uart() {
memory[DATA_ADDR] = 0;
void init_uart(CPU *cpu) {
cpu->memory[DATA_ADDR] = 0;
uart_SR.byte = 0;
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
}
void step_uart() {
if (write_addr == &memory[DATA_ADDR]) {
putchar(memory[DATA_ADDR]);
if (memory[DATA_ADDR] == '\b') printf(" \b");
void step_uart(CPU *cpu) {
if (cpu->write_addr == &cpu->memory[DATA_ADDR]) {
putchar(cpu->memory[DATA_ADDR]);
if (cpu->memory[DATA_ADDR] == '\b') printf(" \b");
fflush(stdout);
write_addr = NULL;
} else if (read_addr == &memory[DATA_ADDR]) {
cpu->write_addr = NULL;
} else if (cpu->read_addr == &cpu->memory[DATA_ADDR]) {
uart_SR.bits.RDRF = 0;
read_addr = NULL;
cpu->read_addr = NULL;
}
/* update input register if empty */
@ -54,6 +54,6 @@ void step_uart() {
}
}
memory[DATA_ADDR] = incoming_char;
memory[CTRL_ADDR] = uart_SR.byte;
cpu->memory[DATA_ADDR] = incoming_char;
cpu->memory[CTRL_ADDR] = uart_SR.byte;
}

View File

@ -1,4 +1,4 @@
CFLAGS = -Wall -Wpedantic -Ofast -std=gnu99
CFLAGS = -Wall -Wpedantic -g -std=gnu99
LDFLAGS = -Ofast
OBJ := 6502-emu.o 6502.o 6850.o