Skip to content

Instantly share code, notes, and snippets.

@banthar
Created April 11, 2012 00:09
Show Gist options
  • Save banthar/2355847 to your computer and use it in GitHub Desktop.
Save banthar/2355847 to your computer and use it in GitHub Desktop.
dcpu vm
#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