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;
}
}