#include<stdio.h> #include<stdlib.h> #define RUNNING 1 #define STOPPED 2 #define DEBUG 1 /* ** al1.c ** ** 110600 - JAH ** ** Emulates an imaginary cpu (poorly) ** will later be part of a larger GA ** type effort */ typedef struct t_cpu { \tint ip; \tchar *mem; \tint *reg; \tvoid (*ops[255])(); \tvoid (*cycle)(); \tvoid (*regcheck)(); \tint memsize; \tunsigned char numregs; \tint numops; \tint state; } cpu; void cycle(cpu *); void read(cpu *); void store(cpu *); void add(cpu *); void mul(cpu *); void nop(cpu *); void jmp(cpu *); void set(cpu *); void regcheck(cpu *, int); void init(cpu *,int,unsigned char); int main(int argc, char *argv[]){ \tcpu cpu1; \tint i; \tif(argc != 3){ \t\tprintf("Bad user! No biscuit!\ "); \t\texit(1); \t} \tinit(&cpu1, atoi(argv[1]), (unsigned char)atoi(argv[2])); \twhile(cpu1.state == RUNNING){ \t\tcpu1.cycle(&cpu1); \t\ti++; \t} \tprintf("\ \ Final cycle count: %d\ ",i); } void init(cpu *cpu1, int memsize, unsigned char numregs){ \tint i; \t/* Allocate space to be used as "memory" */ \tcpu1->mem = (char *)malloc(memsize * sizeof(char)); \tcpu1->memsize = memsize; \t/* Fill the memory up with noise */ \tsrand((unsigned int)time(NULL)); \tfor(i=0; i<memsize; i++){ \t\t/*cpu1->mem[i] = (int)(rand() * (2 ^ (sizeof(int) * 8 - 1)));*/ \t\tcpu1->mem[i] = 1 + (int)(10.0 * rand() / (RAND_MAX + 1.0)); \t} \tif(DEBUG)printf("Setting cpu1->memsize to: %d\ ",cpu1->memsize); \t/* Allocate space to be used as registers */ \tcpu1->reg = (int *)malloc(numregs * sizeof(int)); \tcpu1->numregs = numregs; \tif(DEBUG)printf("Setting cpu1->numregs to: %d\ ",cpu1->numregs); \t/* Set up the ops table -- this should be dynamic */ \tcpu1->numops = 7; \tcpu1->ops[0] = &read; \tcpu1->ops[1] = &store; \tcpu1->ops[2] = &add; \tcpu1->ops[3] = &mul; \tcpu1->ops[4] = &nop; \tcpu1->ops[5] = &jmp; \tcpu1->ops[6] = &set; \tcpu1->cycle = &cycle; \tcpu1->regcheck = ®check; \t/* Set initial state */ \tcpu1->state = RUNNING; \tif(DEBUG)printf("Setting cpu1->state to: %d\ ",cpu1->state); } /* ** Actually "do" a cycle. ** ** Execute the instruction at the current ip or stop. */ void cycle(cpu *self){ \tif(self->mem[self->ip] >= 0 && self->mem[self->ip] < self->numops){ \t\tself->ops[self->mem[self->ip]](self); \t} else { \t\tif(DEBUG)printf("IP:[%04x] :: Instruction violation -- %d.\ ", self->ip, self->mem[self->ip]); \t\tself->state = STOPPED; \t} } /* ** The read op */ void read(cpu *self){ \tint *p; \tint lreg; \tif(DEBUG)printf("IP:[%04x] :: READ\ ", self->ip); \t/* increment ip past read op */ \tself->ip++; \t/* determine the target register and increment ip */ \tlreg = self->mem[self->ip]; \tself->regcheck(self,lreg); \tif(self->state != RUNNING)return; \tif(DEBUG)printf("IP:[%04x] :: ---- lreg: %d\ ", self->ip, lreg); \tself->ip++; \t/* read the value into the target register */ \tp = (int *)&self->mem[self->ip]; \tself->reg[lreg] = *p; \tif(DEBUG)printf("IP:[%04x] :: ---- VALU: %d\ ", self->ip, *p); \t/* increment ip past the data */ \tself->ip += sizeof(int); \tif(DEBUG)printf("IP:[%04x] :: ---- DONE\ ", self->ip); } /* ** The store op */ void store(cpu *self){ \tint *p; \tint lreg; \tif(DEBUG)printf("IP:[%04x] :: STORE\ ", self->ip); \t/* increment ip past store op */ \tself->ip++; \t/* determine the target register and increment ip */ \tlreg = self->mem[self->ip]; \tself->regcheck(self,lreg); \tif(self->state != RUNNING)return; \tif(DEBUG)printf("IP:[%04x] :: ---- lreg: %d\ ", self->ip, lreg); \tself->ip++; \t/* write the register's contents at the target location */ \tp = (int *)&self->mem[self->ip]; \t*p = self->reg[lreg]; \tif(DEBUG)printf("IP:[%04x] :: ---- VALU: %d\ ", self->ip, *p); \t/* increment ip past the data */ \tself->ip += sizeof(int); \tif(DEBUG)printf("IP:[%04x] :: ---- DONE\ ", self->ip); } /* ** The add op */ void add(cpu *self){ \tint lreg1; \tint lreg2; \tif(DEBUG)printf("IP:[%04x] :: ADD\ ", self->ip); \t/* increment ip past store op */ \tself->ip++; \t/* determine the target register and increment ip */ \tlreg1 = self->mem[self->ip]; \tself->regcheck(self,lreg1); \tif(self->state != RUNNING)return; \tif(DEBUG)printf("IP:[%04x] :: --- REG1: %d\ ", self->ip, lreg1); \tself->ip++; \t/* determine the donor register and increment ip */ \tlreg2 = self->mem[self->ip]; \tself->regcheck(self,lreg2); \tif(self->state != RUNNING)return; \tif(DEBUG)printf("IP:[%04x] :: --- REG2: %d\ ", self->ip, lreg2); \tself->ip++; \t/* add */ \tif(DEBUG)printf("IP:[%04x] :: --- %d + %d\ ", self->ip, self->reg[lreg1],self->reg[lreg2]); \tself->reg[lreg1] = self->reg[lreg1] + self->reg[lreg2]; \tif(DEBUG)printf("IP:[%04x] :: --- =: %d\ ", self->ip, self->reg[lreg1]); } /* ** The mul op */ void mul(cpu *self){ \tint lreg1; \tint lreg2; \tif(DEBUG)printf("IP:[%04x] :: MUL\ ", self->ip); \t/* increment ip past store op */ \tself->ip++; \t/* determine the target register and increment ip */ \tlreg1 = self->mem[self->ip]; \tself->regcheck(self,lreg1); \tif(self->state != RUNNING)return; \tif(DEBUG)printf("IP:[%04x] :: --- REG1: %d\ ", self->ip, lreg1); \tself->ip++; \t/* determine the donor register and increment ip */ \tlreg2 = self->mem[self->ip]; \tself->regcheck(self,lreg2); \tif(self->state != RUNNING)return; \tif(DEBUG)printf("IP:[%04x] :: --- REG2: %d\ ", self->ip, lreg2); \tself->ip++; \t/* multiply */ \tif(DEBUG)printf("IP:[%04x] :: --- %d * %d\ ", self->ip, self->reg[lreg1],self->reg[lreg2]); \tself->reg[lreg1] = self->reg[lreg1] * self->reg[lreg2]; \tif(DEBUG)printf("IP:[%04x] :: --- =: %d\ ", self->ip, self->reg[lreg1]); } void nop(cpu *self){ \tif(DEBUG)printf("IP:[%04x] :: NOP\ ", self->ip); \t/* increment ip past nop */ \tself->ip++; \tif(DEBUG)printf("IP:[%04x] :: --- DONE\ ", self->ip); } void jmp(cpu *self){ \tif(DEBUG)printf("IP:[%04x] :: JMP\ ", self->ip); \t/* increment ip past jmp op */ \tself->ip++; \t/* Jump */ \tif(DEBUG)printf("IP:[%04x] :: --- TARGET: %d\ ", self->ip, self->mem[self->ip]); \tself->ip+=self->mem[self->ip]; \tif(DEBUG)printf("IP:[%04x] :: --- DONE\ ", self->ip); } void set(cpu *self){ \tint *p; \tint lreg; \tif(DEBUG)printf("IP:[%04x] :: SET\ ", self->ip); \t/* increment ip past jmp op */ \tself->ip++; \t/* read the register to be set */ \tlreg = self->mem[self->ip]; \tself->regcheck(self,lreg); \tif(self->state != RUNNING)return; \tif(DEBUG)printf("IP:[%04x] :: --- REG: %d\ ", self->ip, lreg); \tself->ip++; \t/* read the value and set the reg */ \tp = (int *)&self->mem[self->ip]; \tself->reg[lreg] = *p; \tif(DEBUG)printf("IP:[%04x] :: --- VALU: %d\ ", self->ip, self->reg[lreg]); \t/* increment ip past the data */ \tself->ip += sizeof(int); \tif(DEBUG)printf("IP:[%04x] :: --- DONE\ ", self->ip); } void regcheck(cpu *self, int reg){ \tif(reg > self->numregs || reg < 0){ \t\tself->state = STOPPED; \t\tif(DEBUG)printf("IP:[%04x] :: Register Violation\ ", self->ip, reg); \t} }
Extra
Links