Skip to content

Instantly share code, notes, and snippets.

@risent
Created March 18, 2018 08:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save risent/11bbae13d09ee7a9831aded85e6ea074 to your computer and use it in GitHub Desktop.
Save risent/11bbae13d09ee7a9831aded85e6ea074 to your computer and use it in GitHub Desktop.
// demo_cpu.c
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define ISROM(a) ((a) < 16)
#define ISRAM(a) ((a) >= 16 && (a) < 20)
#define ISOUT(a) ((a) == 25)
#define ISIN(a) ((a) == 26)
#define CHIP_ROM_R 0
#define CHIP_RAM_R 1
#define CHIP_RAM_W 2
#define CHIP_IO 3
#define RAM_SELECT 16
struct array {
uint8_t word: 4;
};
struct demo_cpu {
uint8_t data: 4, chip: 2, control: 5;
uint8_t r0: 4, r1: 4, carry: 1;
uint8_t inst: 4, pc: 5;
struct array rom[16], ram[4];
uint8_t in: 4, out: 4;
};
static inline void flush(struct demo_cpu *cpu) {
// commit io as prepared by cpu
switch(cpu->chip) {
case CHIP_ROM_R:
if(ISROM(cpu->control)) {
cpu->data = cpu->rom[cpu->control].word;
printf("read %d from %d\n", cpu->data, cpu->control);
}
break;
case CHIP_RAM_W:
if(ISRAM(cpu->control)) {
cpu->ram[cpu->control & 3].word = cpu->data;
printf("wrote %d to %d\n", cpu->data, cpu->control);
}
break;
case CHIP_RAM_R:
if(ISRAM(cpu->control)) {
cpu->data = cpu->ram[cpu->control & 3].word;
printf("read %d from %d\n", cpu->data, cpu->control);
}
break;
case CHIP_IO:
if(ISIN(cpu->control)) {
cpu->data = cpu->in;
printf("read %d from IN\n", cpu->data);
} else if(ISOUT(cpu->control)) {
cpu->out = cpu->data;
printf("wrote %d to OUT\n", cpu->out);
}
}
}
const char *inst_str[] = {
"sto_r0", "sto_r1", "ld_r0", "ld_r1",
"mvi_r0", "mvi_r1", "lmp", "jc",
"in", "mov_r1_r0", "mov_r0_r1", "out",
"jnc", "add_r1", "asl", "rar",
};
static inline void fetch(struct demo_cpu *cpu) {
// get next instruction
cpu->chip = CHIP_ROM_R;
cpu->control = cpu->pc++;
flush(cpu);
cpu->inst = cpu->data;
printf("fetched %s\n", inst_str[cpu->inst]);
}
void sto_r0(struct demo_cpu *cpu) {
// fetch 2. word
cpu->chip = CHIP_ROM_R;
cpu->control = cpu->pc++;
flush(cpu);
// use 2. word as address
cpu->control = cpu->data | RAM_SELECT;
cpu->data = cpu->r0;
cpu->chip = CHIP_RAM_W;
flush(cpu);
}
void sto_r1(struct demo_cpu *cpu) {
// fetch 2. word
cpu->chip = CHIP_ROM_R;
cpu->control = cpu->pc++;
flush(cpu);
// use 2. word as address
cpu->control = cpu->data | RAM_SELECT;
cpu->data = cpu->r1;
cpu->chip = CHIP_RAM_W;
flush(cpu);
}
void ld_r0(struct demo_cpu *cpu) {
// fetch 2. word
cpu->chip = CHIP_ROM_R;
cpu->control = cpu->pc++;
flush(cpu);
// use 2. word as address
cpu->control = cpu->data | RAM_SELECT;
cpu->chip = CHIP_RAM_R;
flush(cpu);
cpu->r0 = cpu->data;
}
void ld_r1(struct demo_cpu *cpu) {
// fetch 2. word
cpu->chip = CHIP_ROM_R;
cpu->control = cpu->pc++;
flush(cpu);
// use 2. word as address
cpu->control = cpu->data | RAM_SELECT;
cpu->chip = CHIP_RAM_R;
flush(cpu);
cpu->r1 = cpu->data;
}
void mvi_r0(struct demo_cpu *cpu) {
// fetch 2. word
cpu->chip = CHIP_ROM_R;
cpu->control = cpu->pc++;
flush(cpu);
// store data in r0
cpu->r0 = cpu->data;
}
void mvi_r1(struct demo_cpu *cpu) {
// fetch 2. word
cpu->chip = CHIP_ROM_R;
cpu->control = cpu->pc++;
flush(cpu);
// store data in r1
cpu->r1 = cpu->data;
}
void lmp(struct demo_cpu *cpu) {
// fetch 2. word
cpu->chip = CHIP_ROM_R;
cpu->control = cpu->pc++;
flush(cpu);
// store data in pc
cpu->pc = cpu->data;
}
void jc(struct demo_cpu *cpu) {
// fetch 2. word
cpu->chip = CHIP_ROM_R;
cpu->control = cpu->pc++;
flush(cpu);
// jump if carry
if(cpu->carry == true)
cpu->pc = cpu->data;
}
void jnc(struct demo_cpu *cpu) {
// fetch 2. word
cpu->chip = CHIP_ROM_R;
cpu->control = cpu->pc++;
flush(cpu);
// jump if not carry
if(cpu->carry == false)
cpu->pc = cpu->data;
}
void out(struct demo_cpu *cpu) {
// write r0 to OUT register
cpu->data = cpu->r0;
cpu->chip = CHIP_IO;
cpu->control = 25;
flush(cpu);
}
void in(struct demo_cpu *cpu) {
// read r0 from IN register
cpu->chip = CHIP_IO;
cpu->control = 26;
cpu->r0 = cpu->data;
flush(cpu);
}
void mov_r1_r0(struct demo_cpu *cpu) {
cpu->r1 = cpu->r0;
}
void mov_r0_r1(struct demo_cpu *cpu) {
cpu->r0 = cpu->r1;
}
void add_r1(struct demo_cpu *cpu) {
cpu->r0 += cpu->r1;
if(cpu->r1 + cpu->r0 > 0xf)
cpu->carry = 1;
}
void asl(struct demo_cpu *cpu) {
cpu->carry = cpu->r0 >> 3;
cpu->r0 <<= 1;
}
void rar(struct demo_cpu *cpu) {
cpu->carry = cpu->r0;
cpu->r0 >>= 1;
}
void (*inst[16])(struct demo_cpu*) = {
sto_r0, sto_r1, ld_r0, ld_r1,
mvi_r0, mvi_r1, lmp, jc,
in, mov_r1_r0, mov_r0_r1, out,
jnc, add_r1, asl, rar,
};
int main(void) {
struct demo_cpu cpu = {
.pc = 0,
.rom = {
{5}, {7}, {1}, {1},
{2}, {0}, {11},
{2}, {1}, {11},
{2}, {2}, {11},
{2}, {3}, {11}
},
.ram = {{0}},
};
while(ISROM(cpu.pc)) {
fetch(&cpu);
inst[cpu.inst](&cpu);
}
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment