Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

VM instruction implementation without huge switch()?

Name: Anonymous 2014-06-09 23:26

How would one go about making a virtual machine without using a huge and clumsy switch( opcode ) statement?

The architecture I'm implementing (DCPU-16) has about 35-40 different instructions.

Name: L. A. Calculus !jYCj6s4P.g 2014-06-10 7:17

WHO TAUGHT U RETOIDS HOW 2 DESIGN PROGRAMS?

#include <stdio.h>
#include <stdlib.h>

enum {
NOPERATIONS = 40
};

enum {
SUCCESS, CONTINUE, ARITY, INVALID_OPCODE
};

struct cpu {
unsigned char *mem;
int ip;
int size;
/* ... */
};

int nop(struct cpu *cp, const unsigned char *p, int n)
{
return 1;
}

int set(struct cpu *cp, const unsigned char *p, int n)
{
unsigned index;

if (n < 5)
return -ARITY;
index = p[1] << 8 | p[2];
cp->mem[index] = p[3];
cp->mem[index + 1] = p[4];
return 5;
}

int (*operations[NOPERATIONS]) (struct cpu *, const unsigned char *, int) = {
nop, set /* , ... */
};

int cpu_tick(struct cpu *cp)
{
int n, op;

if (cp->ip == cp->size)
return SUCCESS;

op = cp->mem[cp->ip];
if (op >= NOPERATIONS || operations[op] == NULL)
return INVALID_OPCODE;

if ((n = operations[op](cp, &cp->mem[cp->ip], cp->size - cp->ip)) < 0)
return -n;

cp->ip += n;
return CONTINUE;
}

int main(void)
{
unsigned char b[] = { 0, 0, 1, 0, 0, 69, 96, 0 };
struct cpu cpu;
int e;

cpu.mem = b;
cpu.ip = 0;
cpu.size = (int) (sizeof b / sizeof b[0]);

while ((e = cpu_tick(&cpu)) == CONTINUE)
;

switch (e) {
case INVALID_OPCODE:
fprintf(stderr, "invalid opcode: %d\n", cpu.mem[cpu.ip]);
return EXIT_FAILURE;
case ARITY:
fprintf(stderr, "invalid arity to op %d\n", cpu.mem[cpu.ip]);
return EXIT_FAILURE;
case SUCCESS:
printf("%d %d\n", b[0], b[1]);
return 0;
default:
fprintf(stderr, "TELL DA RETOID WHO WROTE DIS EMULATOR 2 REED"
" DA FUKIN STANDARD.\n");
return EXIT_FAILURE;
}
}

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List