Last active
October 22, 2021 01:04
-
-
Save eparadis/0e5fe0aac7bfe005cab65df5d9e4209d to your computer and use it in GitHub Desktop.
sketch of a 8 bit cpu simulator/emulator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdio.h> | |
typedef uint8_t FLAG; | |
typedef uint8_t INSTR; | |
typedef uint8_t REGISTER; | |
typedef uint16_t IP; | |
const FLAG FLAG_HALT = 0x80; | |
const INSTR INSTR_LOAD = 0x08; | |
const INSTR INSTR_STORE = 0x09; | |
const INSTR INSTR_ADDI = 0x0A; | |
const INSTR INSTR_NOP = 0x00; | |
typedef REGISTER (*loader_t)(IP); | |
typedef void (*storer_t)(REGISTER, IP); | |
typedef struct cpu_state { | |
FLAG flags; | |
IP ip; | |
REGISTER rA; | |
} cpu_state; | |
struct cpu_state cpu( | |
cpu_state *curr_state, | |
loader_t load, | |
storer_t store, | |
loader_t io_read, | |
storer_t io_write | |
) { | |
cpu_state new_state; | |
INSTR instruction = load( curr_state->ip); | |
switch( instruction) { | |
case INSTR_LOAD: { | |
REGISTER upper_addr = load( curr_state->ip + 1); | |
REGISTER lower_addr = load( curr_state->ip + 2); | |
new_state.rA = load( upper_addr << 8 | lower_addr); | |
new_state.ip = curr_state->ip + 3; | |
break; | |
} | |
case INSTR_STORE: { | |
REGISTER upper_addr = load( curr_state->ip + 1); | |
REGISTER lower_addr = load( curr_state->ip + 2); | |
store( curr_state->rA, upper_addr << 8 | lower_addr); | |
new_state.ip = curr_state->ip + 3; | |
break; | |
} | |
case INSTR_ADDI: { | |
REGISTER addend = load( curr_state->ip + 1); | |
new_state.rA = curr_state->rA + addend; | |
new_state.ip = curr_state->ip + 2; | |
break; | |
} | |
case INSTR_NOP: { | |
new_state.ip = curr_state->ip + 1; | |
break; | |
} | |
default: { | |
new_state.flags |= FLAG_HALT; | |
break; | |
} | |
} | |
return new_state; | |
} | |
uint8_t ram[128]; | |
REGISTER load( IP addr) { | |
printf("DEBUG[LOAD] addr:%.4x\n", addr); | |
return ram[addr % 128]; | |
} | |
void store( REGISTER value, IP addr) { | |
printf("DEBUG[STORE] addr:%.4x value:%.4x\n", addr, value); | |
ram[addr % 128] = value; | |
} | |
void debug_state( cpu_state state) { | |
printf("DEBUG[CPU] flags:%.2x ip:%.4x rA:%.2x\n", state.flags, state.ip, state.rA); | |
} | |
void debug_dump(uint8_t *block, uint16_t start, uint16_t end) { | |
for( uint16_t i = start; i <= end; i += 1) { | |
printf("%.2x ", block[i]); | |
if( i % 16 == 15) { | |
printf("\n"); | |
} | |
} | |
} | |
void zero_addresses(uint8_t *block, uint16_t start, uint16_t end) { | |
for( uint16_t i = start; i <= end; i += 1) { | |
block[i] = 0; | |
} | |
} | |
int main( ) { | |
zero_addresses(ram, 0, 127); | |
ram[0] = INSTR_ADDI; | |
ram[1] = 0x03; | |
ram[2] = INSTR_STORE; | |
ram[3] = 0x00; | |
ram[4] = 0x1F; | |
ram[5] = INSTR_LOAD; | |
ram[6] = 0x00; | |
ram[7] = 0x1E; | |
ram[8] = 0xAA; // illegal instr to cause halt | |
struct cpu_state state; | |
struct cpu_state next_state; | |
state.ip = 0; | |
state.flags = 0; | |
state.rA = 0; | |
while( (state.flags & FLAG_HALT) == 0) { | |
debug_state(state); | |
next_state = cpu( &state, &load, &store, &load, &store); | |
state = next_state; | |
} | |
debug_state(state); | |
debug_dump(ram, 0, 0x0F); | |
debug_dump(ram, 0x1E, 0x1F); | |
} |
I got it a little closer to real C. Still doesn’t compile.
I pulled this into repl.it
to hammer out all the syntax (and conceptual) errors it had. I'll probably open a proper repo for it now that it compiles and shows some actual promise.
OK now i really need to do something with this because I obviously can't let it go.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can you tell I don’t actually write C very often? Yeah.
I wrote this on a machine without a compiler. It definitely won’t build as written.
I wrote this when I woke up in the middle of the night and couldn’t get back to sleep, so no guarantee it makes any sense at all.