Created
April 11, 2012 00:09
-
-
Save banthar/2355847 to your computer and use it in GitHub Desktop.
dcpu vm
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 <stdbool.h> | |
#include <stdint.h> | |
struct dcpu { | |
uint16_t ram[0x10000]; | |
uint16_t reg[8]; | |
uint16_t pc; | |
uint16_t sp; | |
uint16_t o; | |
}; | |
void dcpu_reset(struct dcpu* vm) | |
{ | |
memset(vm,0,sizeof(*vm)); | |
vm->sp=0xffff; | |
} | |
static void load(struct dcpu* vm, int loc) | |
{ | |
switch(loc) | |
{ | |
case 0x00..0x07: | |
return vm->reg[loc]; | |
case 0x08..0x0f: | |
return vm->memory[vm->reg[loc-0x08]]; | |
case 0x10..0x17: | |
return vm->memory[vm->memory[vm->pc++]+vm->reg[loc-0x10]]; | |
case 0x18: | |
return vm->memory[vm->sp++]; | |
case 0x19: | |
return vm->memory[vm->sp]; | |
case 0x1a: | |
return vm->memory[--vm->sp]; | |
case 0x1b: | |
return vm->sp; | |
case 0x1c: | |
return vm->pc; | |
case 0x1d: | |
return vm->o; | |
case 0x1e: | |
return vm->memory[vm->memory[vm->pc++]]; | |
case 0x1f: | |
return vm->memory[vm->pc++]; | |
case 0x20..0x3f: | |
return c-0x20; | |
} | |
} | |
static void store(struct dcpu* vm, int loc, uint16_t value) | |
{ | |
switch(loc) | |
{ | |
case 0x00..0x07: | |
vm->reg[loc]=value; | |
case 0x08..0x0f: | |
vm->memory[vm->reg[loc-0x08]]=value; | |
case 0x10..0x17: | |
vm->memory[vm->memory[vm->pc++]+vm->reg[loc-0x10]]=value; | |
case 0x18: | |
vm->memory[vm->sp++]=value; | |
case 0x19: | |
vm->memory[vm->sp]=value; | |
case 0x1a: | |
vm->memory[--vm->sp]=value; | |
case 0x1b: | |
vm->sp=value; | |
case 0x1c: | |
vm->pc=value; | |
case 0x1d: | |
vm->o=value; | |
case 0x1e: | |
vm->memory[vm->memory[vm->pc++]]=value; | |
case 0x1f: | |
vm->memory[vm->pc++]=value; | |
case 0x20..0x3f: | |
; | |
default: | |
panic(vm,"invalid argument location 0x%02x",loc); | |
} | |
} | |
void dcpu_tick(struct dcpu* vm) | |
{ | |
uint16_t instruction = vm->memory[vm->pc++]; | |
if(instruction&0xf == 0) | |
{ | |
switch((instruction>>4)&0x3f) | |
{ | |
case 0x01: | |
vm->memory[vm->sp--]=vm->pc; | |
vm->pc=load((instruction>>10)&0x3f); | |
break; | |
default: | |
panic(vm,"invalid non-basic opcode 0x%02x",(instruction>>4)&0x3f); | |
} | |
} | |
else | |
{ | |
uint16_t a=load((instruction>>4)&0x3f); | |
uint16_t b=load((instruction>>10)&0x3f); | |
uint32_t c; | |
switch(instruction&0xf) | |
{ | |
case 0x1: | |
store(vm,a,b); | |
break; | |
case 0x2: | |
c=a+b; | |
vm->o=c>>16; | |
store(vm,a,c); | |
break; | |
case 0x3: | |
c=a-b; | |
vm->o=c>>16; | |
store(vm,a,c); | |
break; | |
case 0x4: | |
c=a*b; | |
vm->o=c>>16; | |
store(vm,a,c); | |
break; | |
case 0x5: | |
if(b!=0) { | |
c=a/b; | |
vm->o=(a<<16)/b; | |
} | |
else { | |
c=0; | |
vm->o=0; | |
} | |
store(vm,a,c); | |
break; | |
case 0x6: | |
if(b!=0) { | |
c=a%b; | |
} | |
else { | |
c=0; | |
} | |
store(vm,a,c); | |
break; | |
case 0x7: | |
c=a<<b; | |
vm->o=c>>16; | |
store(vm,a,c); | |
break; | |
case 0x8: | |
c=a>>b; | |
vm->o=(a<<16)>>b; | |
store(vm,a,c); | |
break; | |
case 0x9: | |
c=a&b; | |
store(vm,a,c); | |
break; | |
case 0xa: | |
c=a|b; | |
store(vm,a,c); | |
break; | |
case 0xb: | |
c=a^b; | |
store(vm,a,c); | |
break; | |
case 0xc: | |
vm->pc+=((a==b)?0:1); | |
store(vm,a,c); | |
break; | |
case 0xd: | |
vm->pc+=((a!=b)?0:1); | |
store(vm,a,c); | |
break; | |
case 0xe: | |
vm->pc+=((a>b)?0:1); | |
store(vm,a,c); | |
break; | |
case 0xf: | |
vm->pc+=((a&b)?0:1); | |
store(vm,a,c); | |
break; | |
default: | |
panic(vm,"invalid basic opcode 0x%02x",instruction&0xf); | |
} | |
} | |
} | |
int main(int argc, char*argv) | |
{ | |
struct dcpu vm; | |
dcpu_reset(&vm); | |
while(true) | |
dcpu_tick(&vm); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment