Matthew Veetyits all brokeff51cb08 years agoHistory
618 lines · 11.0 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <thread.h>#include "cpu.h" Regr_getregister(Cpu *c, u32int regn){	Regr r;	u8int tmp; 	switch(regn){	case R0:	case R1:	case R2:	case R3:	case R4:	case R5:	case R6:	case R7:	case S0:	case S1:	case S2:	case S3:	case S4:	case S5:	case S6:	case S7:		tmp = regn - 0x10;		r.type = 0;		r.s = &c->g_regs[tmp];		break;	case V0:	case V1:	case V2:	case V3:	case V4:	case V5:	case V6:	case V7:		tmp = regn - 0x20;		r.type = 1;		r.v = &c->v_regs[tmp];		break;	case OP:	case PC:	case SP:	case FL:	case SY:	case TI:	case TR:	case TL:		tmp = regn - 0x30;		r.type = 2;		r.s = &c->c_regs[tmp];		break;	}	return r;} u32int*getregister(Cpu *c, u32int regn){	Regr r;	u32int *rval = nil; 	r = _getregister(c, regn);	if(r.type == 0 || r.type == 2)		rval = r.s;	return rval;} voidexecute(Cpu *c, Inst *inst){	switch(inst->type){	case 0xf:		doimplop(c, inst);		break;	case 0x1:	case 0x4:		sendvectop(c, inst);		break;	case 0x0:		doscalarmemop(c, inst);		break;	case 0x2:		docontrolop(c, inst);		break;	case 0x3:		doscalarmathop(c, inst);		break;	}} voidreadreg(Cpu *c, u32int *r, u32int addr){	u8int b[4]; 	for(int i = 0; i < 4; i++)		b[i] = c->memread(addr+i);	*r = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];} voidwritereg(Cpu *c, u32int *r, u32int addr){	u8int b[4]; 	b[0] = *r>>24 & 0xff;	b[1] = *r>>16 & 0xff;	b[2] = *r>>8 & 0xff;	b[3] = *r & 0xff;	for(int i = 0; i < 4; i++)		c->memwrite(&b[i], addr+i);} voiddoscalarmemop(Cpu *c, Inst *inst){	u32int *reg1, *reg2;	u32int addr;	u8int tmp[4]; 	switch(inst->op){	case 0x10: // loads		reg1 = getregister(c, inst->args[0]);		addr = inst->args[1];		readreg(c, reg1, addr);		break;	case 0x11: // stores		reg1 = getregister(c, inst->args[0]);		addr = inst->args[1];		writereg(c, reg1, addr);		break;	case 0x12: // moves		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, inst->args[1]);		*reg2 = *reg1;		break;	case 0x13: // rloads		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, inst->args[1]);		readreg(c, reg1, *reg2);		break;	case 0x14: // rstores		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, inst->args[1]);		writereg(c, reg1, *reg2);		break;	case 0x15: // push		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, SP);		writereg(c, reg1, *reg2);		(*reg2) += 4;;		break;	case 0x16: // pop		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, SP);		(*reg2) -= 4;		readreg(c, reg1, *reg2);		break;	case 0x17: // loadc		reg1 = getregister(c, inst->args[0]);		*reg1 = inst->args[1];		break;	case 0x18: // clrs		reg1 = getregister(c, inst->args[0]);		*reg1 = 0;		break;	case 0x19: // loadb		reg1 = getregister(c, inst->args[0]);		addr = inst->args[1];		tmp[3] = c->memread(addr);		tmp[0] = tmp[1] = tmp[2] = 0;		*reg1 = tmp[0]<<24 | tmp[1]<<16 | tmp[2]<<8 | tmp[3];		break;	case 0x1a: // storeb		reg1 = getregister(c, inst->args[0]);		addr = inst->args[1];		tmp[0] = *reg1>>24 & 0xff;		tmp[1] = *reg1>>16 & 0xff;		tmp[2] = *reg1>>8 & 0xff;		tmp[3] = *reg1 & 0xff;		c->memwrite(&tmp[3], addr);		break;	case 0x1b: // rloadb		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, inst->args[1]);		tmp[3] = c->memread(*reg2);		tmp[0] = tmp[1] = tmp[2] = 0;		*reg1 = tmp[0]<<24 | tmp[1]<<16 | tmp[2]<<8 | tmp[3];		break;	case 0x1c: //rstoreb		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, inst->args[1]);		tmp[0] = *reg1>>24 & 0xff;		tmp[1] = *reg1>>16 & 0xff;		tmp[2] = *reg1>>8 & 0xff;		tmp[3] = *reg1 & 0xff;		c->memwrite(&tmp[3], *reg2);		break;	}} voiddocontrolop(Cpu *c, Inst *inst){	u32int *reg1;	u32int addr;	u32int *sp, *sy, *fl, *pc, *op, *tr; 	sp = getregister(c, SP);	sy = getregister(c, SY);	fl = getregister(c, FL);	pc = getregister(c, PC);	op = getregister(c, OP);	tr = getregister(c, TR);	switch(inst->op){	case 0x10: // jmp		dprint(smprint("pre jmp: args[0] = %x, pc = %x\n", inst->args[0], *pc));		(*pc) = inst->args[0];		dprint(smprint("post jmp: args[0] = %x, pc = %x\n", inst->args[0], *pc));		break;	case 0x11: // rjmp		(*pc) = *op+inst->args[0];		break;	case 0x12: // jmpr		reg1 = getregister(c, inst->args[0]);		(*pc) = *reg1;		break;	case 0x13: // rjmpr		reg1 = getregister(c, inst->args[0]);		(*pc) = *op+*reg1;		break;	case 0x14: // clrf		*fl = 0;		break;	case 0x15: // cjmp		addr = inst->args[0];		if(*fl > 0){			*fl = 0;			(*pc) = addr;		}		break;	case 0x16: // crjmp		addr = inst->args[0]+*op;		if(*fl > 0){			*fl = 0;			(*pc) = addr;		}		break;	case 0x17: // cjmpr		reg1 = getregister(c, inst->args[0]);		addr = *reg1;		if(*fl > 0){			*fl = 0;			(*pc) = addr;		}		break;	case 0x18: // crjmpr		reg1 = getregister(c, inst->args[0]);		addr = *reg1+*op;		if(*fl > 0){			*fl = 0;			(*pc) = addr;		}		break;	case 0x19: // setsys		addr = inst->args[0];		*sy = addr;		break;	case 0x1a: // syscall		addr = *sy;		writereg(c, pc, *sp);		*sp += 4;		(*pc) = *sy;		break;	case 0x1b: // call		addr = inst->args[0];		writereg(c, pc, *sp);		*sp += 4;		*pc = addr;		break;	case 0x1c: // rcall		addr = inst->args[0]+*op;		writereg(c, pc, *sp);		*sp += 4;		(*pc) = addr;		break;	case 0x1d: // return		if(c->intimerint){			c->intimerint = 0;			*pc = *tr;			*tr = 0;		} else {			readreg(c, &addr, *sp);			(*sp) -= 4;			(*pc) = addr;		}		break;	case 0x1f: // halt		cpuhalt();		break;	case 0x20: // tstart		c->timeron = 1;		timerstart(c);		break;	case 0x21: // tstop		c->timeron = 0;		timerstop(c);		break;	}} voiddoscalarmathop(Cpu *c, Inst *inst){	u32int *reg1, *reg2, *reg3;	u32int *fl; 	fl = getregister(c, FL);	switch(inst->op){	case 0x10: // eqs		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, inst->args[1]);		*fl = *reg1 == *reg2 ? 1 : 0;		break;	case 0x11: // gts		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, inst->args[1]);		*fl = *reg1 > *reg2 ? 1 : 0;		break;	case 0x12: // lts		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, inst->args[1]);		*fl = *reg1 < *reg2 ? 1 : 0;		break;	case 0x13: // adds		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, inst->args[1]);		reg3 = getregister(c, inst->args[2]);		*reg1 = *reg2 + *reg3;		break;	case 0x14: // subs		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, inst->args[1]);		reg3 = getregister(c, inst->args[2]);		*reg1 = *reg2 - *reg3;		break;	case 0x15: // muls		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, inst->args[1]);		reg3 = getregister(c, inst->args[2]);		*reg1 = *reg2 * *reg3;		break;	case 0x16: // divs		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, inst->args[1]);		reg3 = getregister(c, inst->args[2]);		if(*reg3 != 0)			*reg1 = *reg2 / *reg3;		else			*fl = 1;		break;	case 0x17: // mods		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, inst->args[1]);		reg3 = getregister(c, inst->args[2]);		if(*reg3 != 0)			*reg1 = *reg2 % *reg3;		else			*fl = 1;		break;	case 0x18: // nands		reg1 = getregister(c, inst->args[0]);		reg2 = getregister(c, inst->args[1]);		reg3 = getregister(c, inst->args[2]);		*reg1 = ~(*reg2 & *reg3);		break;	}} voidfetchdecode(Cpu *c, Inst *inst){	u32int *pc;	u32int curpc;	u8int t;	u8int len;	u8int i;	u8int b[16];		pc = getregister(c, PC);	// fetch the entire instruction	b[0] = c->memread((*pc)++);	b[1] = c->memread((*pc)++);	len = (b[0] & 0x0f)-2;	t = b[0] & 0xf0;	inst->type = t >> 4;	inst->op = b[1];	dprint(smprint("inst->type = %x, inst->op = %x, len = %x", inst->type, inst->op, len+2));	curpc = *pc;	for(i = 0; i < len; i++)		b[i] = c->memread((*pc)++);	switch(inst->type){	case 0xf:		switch(inst->op){		case 0x11:			inst->args[0] = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3];			break;		case 0x12:			inst->args[0] = b[0];			break;		}		break;	case 0x0:		inst->args[0] = b[0];		switch(inst->op){		case 0x10:		case 0x11:		case 0x17:		case 0x19:		case 0x1a:			inst->args[1] = b[1] << 24 | b[2] << 16 | b[3] << 8 | b[4];			break;		case 0x12:		case 0x13:		case 0x14:		case 0x1b:		case 0x1c:			inst->args[1] = b[1];			break;		}		break;	case 0x1:		inst->args[0] = b[0];		switch(inst->op){		case 0x10:		case 0x11:			inst->args[1] = b[1] << 24 | b[2] << 16 | b[3] << 8 | b[4];			break;		case 0x12:		case 0x13:		case 0x14:			inst->args[1] = b[1];			break;		case 0x15:		case 0x16:		case 0x18:		case 0x19:			inst->args[1] = b[1];			inst->args[2] = b[2];			break;		case 0x20:			inst->args[1] = b[1];			inst->args[2] = b[2] << 24 | b[3] << 16 | b[4] << 8 | b[5];			break;		}		break;	case 0x2:		switch(inst->op){		case 0x10:		case 0x11:		case 0x15:		case 0x16:		case 0x19:		case 0x1b:		case 0x1c:			inst->args[0] = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3];			break;		case 0x12:		case 0x13:		case 0x17:		case 0x18:			inst->args[0] = b[0];			break;		}		break;	case 0x3:	case 0x4:		inst->args[0] = b[0];		inst->args[1] = b[1];		if(inst->op >= 0x13)			inst->args[2] = b[2];		break;	default:		dprint(smprint("pc = %x, inst->type = %x, inst->op = %x", curpc, inst->type, inst->op));		panic("unknown instruction");		break;	}} voidstartexec(Cpu *c, u32int startaddr){	u32int *pc, *ti, *tr;	Inst *inst; 

Lines 1–500 of 618.