Created
March 18, 2018 08:09
-
-
Save risent/11bbae13d09ee7a9831aded85e6ea074 to your computer and use it in GitHub Desktop.
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
// 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