909 lines · 16.3 KB · C
RawDownload
#include "pdp11.h" jmp_buf nextinst; word coremem[MEMSIZE];byte *corememb = (byte*) coremem;word r[8], ksp, usp;word psw;u32int sr, dr;int running;int waiting;word trapvec;Interrupt *intrq; void setpsw(word npsw, int setprev);void execute(word inst); wordgetintr(void){	int pl;	word vec; 	pl = (psw>>5)&07;	if(intrq == nil || intrq->br <= pl)		return 0;	vec = intrq->vec;	intrq->asserted = 0;	intrq = intrq->next;	return vec;} voidhandleintr(word vec){	word pc, sw; 	pc = r[PC];	sw = psw;	r[PC] = readphys(tophys(vec, RO, KERNEL), WORD);	setpsw(readphys(tophys(vec+2, RO, KERNEL), WORD), 1);	r[SP] -= 2;	writew(r[SP], sw);	r[SP] -= 2;	writew(r[SP], pc);//	print("trap through %o: %06uo %06uo (sp: %06uo), %06uo %06uo\n", vec, pc, sw, r[SP], r[PC], psw);} voidreqintr(Interrupt *intr){	Interrupt **i; 	if(intr->asserted)		return;	intr->asserted++; 	for(i = &intrq; *i; i = &(*i)->next)		if((*i)->br < intr->br)			break;		else if((*i)->br == intr->br)			if((*i)->vec > intr->vec)				break; 	intr->next = *i;	*i = intr;} voidprintintrq(Interrupt *intr){	if(intr){		print("[ %uo %uo ]->", intr->br, intr->vec);		printintrq(intr->next);	}else		print("nil\n");} wordfetch(void){	word inst;	mmr2 = r[PC];	inst = readw(r[PC]);	r[PC] += 2;	return inst;} voidtrap(word vec){	trapvec = vec;	longjmp(nextinst, 0);} voidrun(void){	running = 1;	waiting = 0;	trapvec = 0;	setjmp(nextinst);	while(running){		if(trapvec){//			print("TRAP at %uo through %uo (psw: %06uo)\n", r[PC]-2, trapvec, psw);			handleintr(trapvec);			trapvec = 0;			waiting = 0;			continue;		}		if(!waiting)			execute(fetch());		trapvec = getintr();		yield();	}} voidsavesp(void){	if((psw&PSW_CM) == 0)		ksp = r[SP];	else		usp = r[SP];} voidloadsp(void){	if((psw&PSW_CM) == 0)		r[SP] = ksp;	else		r[SP] = usp;} voidsetpsw(word npsw, int setprev){	savesp();	if(setprev)		psw = (npsw&~PSW_PM) | ((psw&PSW_CM) >> 2);	else		psw = npsw;	psw &= ~07400;	loadsp();} static wordreadcpu(u32int addr, int type){	switch(addr){	case 0777570:		return GETVAL(sr, addr, type);	case 0777776:		return GETVAL(psw, addr, type);	default:		print("can't read from %uo\n", addr);		return 0;	}} static voidwritecpu(u32int addr, word val, int type){	word npsw;	switch(addr){	case 0777570:		dr = SETVAL(dr, val, addr, type);		break;	case 0777776:		npsw = SETVAL(psw, val, addr, type);		setpsw(npsw, 0);		break;	default:		print("can't write to %uo\n", addr);	}} voidstatusfsread(Req *rq){	char *s; 	savesp();	s = smprint("%06o %06o %06o %06o %06o %06o %06o %06o %06o %06o",		r[0], r[1], r[2], r[3], r[4], r[5], ksp, usp, r[7], psw);	readbuf(rq, s, strlen(s));	free(s);} voidinitcpu(void){	int i; 	psw = 0340;	for(i = 0; i < 8; i++)		r[i] = 0;	ksp = usp = 0;	intrq = nil;	ioreadtbl[ADDRTOIDX(0777776)] = readcpu;	ioreadtbl[ADDRTOIDX(0777570)] = readcpu;	iowritetbl[ADDRTOIDX(0777776)] = writecpu;	iowritetbl[ADDRTOIDX(0777570)] = writecpu; 	dirtab[Qstatus].read = statusfsread;} u32intgetaddr(int am, int type){	word i;	word ret;	int inc; 	ret = 0;	i = am&07;	inc = 2;	if(type == BYTE && i != PC && i != SP)		inc = 1;	switch((am>>3)&07){	case 0:		return REGADDR + i;	case 1:		return r[i];	case 2:		ret = r[i];		r[i] += inc;		break;	case 3:		ret = readw(r[i]);		r[i] += 2;		break;	case 4:		r[i] -= inc;		return r[i];	case 5:		r[i] -= 2;		return readw(r[i]);	case 6:		ret = readw(r[PC]);		r[PC] += 2;		ret += r[i];		break;	case 7:		ret = readw(r[PC]);		r[PC] += 2;		ret += r[i];		ret = readw(ret);		break;	}	return ret;} voidexecute(word inst){	int type;	word sign, mask;	int m1, m2, rn;	u32int src, dst;	word val, val2;	sword sval, sval2;	int res;	sword broff;	int prevmode; 	type = (inst & 0100000) ? BYTE : WORD;	if(type == WORD){		sign = 0100000;		mask =  0177777;	}else{		sign = 0200;		mask  = 0377;	}	rn = (inst>>6) & 07;	m1 = (inst>>6) & 077;	m2 = inst & 077;	broff = (sbyte) inst;	broff <<= 1; 	switch(inst & 0070000){	case 0000000:		break; 	/* MOV(B) */	case 0010000:		src = getaddr(m1, type);		dst = getaddr(m2, type);		val = readmem(src, type);		if(type == BYTE && (m2 & 070) == 0){			val = (sbyte) val;			type = WORD;			sign = 0100000;		}		psw &= ~(PSW_N | PSW_Z | PSW_V);		if(val & sign) psw |= PSW_N;		if(val == 0) psw |= PSW_Z;		writemem(dst, val, type);		return; 	/* CMP(B) */	case 0020000:		src = getaddr(m1, type);		dst = getaddr(m2, type);		val = readmem(src, type);		val2 = readmem(dst, type);		res = val + ((~val2 + 1) & mask);		psw &= ~(PSW_N | PSW_Z | PSW_V | PSW_C);		if(res & sign) psw |= PSW_N;		if((res&mask) == 0) psw |= PSW_Z;		if((res&sign) == (val2&sign) &&		   (val&sign) != (val2&sign))			psw |= PSW_V;		if(val2 > val) psw |= PSW_C;		return; 	/* BIT(B) */	case 0030000:			src = getaddr(m1, type);		dst = getaddr(m2, type);		val = readmem(src, type);		val2 = readmem(dst, type);		val2 &= val;		psw &= ~(PSW_N | PSW_Z | PSW_V);		if(val2&sign) psw |= PSW_N;		if(val2 == 0) psw |= PSW_Z;		return; 	/* BIC(B) */	case 0040000:			src = getaddr(m1, type);		dst = getaddr(m2, type);		val = readmem(src, type);		val2 = readmem(dst, type);		val2 &= ~val;		psw &= ~(PSW_N | PSW_Z | PSW_V);		if(val2&sign) psw |= PSW_N;		if(val2 == 0) psw |= PSW_Z;		writemem(dst, val2, type);		return; 	/* BIS(B) */	case 0050000:			src = getaddr(m1, type);		dst = getaddr(m2, type);		val = readmem(src, type);		val2 = readmem(dst, type);		val2 |= val;		psw &= ~(PSW_N | PSW_Z | PSW_V);		if(val2&sign) psw |= PSW_N;		if(val2 == 0) psw |= PSW_Z;		writemem(dst, val2, type);		return; 	/* ADD/SUB */	case 0060000:		src = getaddr(m1, WORD);		dst = getaddr(m2, WORD);		val = readmem(src, WORD);		val2 = readmem(dst, WORD);		psw &= ~(PSW_N | PSW_Z | PSW_V | PSW_C);		if(inst&0100000){			res = val2 + ((~val + 1) & 0177777);			if((res&0100000) == (val2&0100000) &&			   (val&0100000) != (val2&0100000))				psw |= PSW_V;			if(val2 < val) psw |= PSW_C;		}else{			res  = val + val2;			if((res&0100000) != (val2&0100000) &&			   (val&0100000) == (val2&0100000))				psw |= PSW_V;			if(res & ~0177777) psw |= PSW_C;		}		if(res & 0100000) psw |= PSW_N;		if((res&0177777) == 0) psw |= PSW_Z;		writemem(dst, res, WORD);		return;	} 	switch(inst&0777000){	/* MUL */	case 0070000:		src = getaddr(m2, WORD);		sval = r[rn];		sval2 = readmem(src, WORD);		res = sval * sval2;		if(rn%2 == 0) r[rn++] = res >> 16;		r[rn] = res;		psw &= ~(PSW_N | PSW_Z | PSW_V | PSW_C);		if(res < 0) psw |= PSW_N;		if(res == 0) psw |= PSW_Z;		if(res < -0100000 || res >= 0100000) psw |= PSW_C;		return; 	/* DIV */	case 0071000:{		int num, quot, rem; 		src = getaddr(m2, WORD);		sval = readmem(src, WORD);		psw &= ~(PSW_N | PSW_Z | PSW_V | PSW_C);		if(sval == 0) goto zero;		if(rn%2 != 0) goto undef;		num = r[rn]<<16;		num |= r[rn+1];		quot = num / sval;		rem = num % sval;		if((quot&~0177777) != 0 && (quot&~0177777) != ~0177777) goto undef;		if(quot < 0) psw |= PSW_N;		if(quot == 0) psw |= PSW_Z;		r[rn] = quot;		r[rn+1] = rem;		return;	zero:		psw |= PSW_C;	undef:		psw |= PSW_V;		return;} 	/* ASH */	case 0072000:		src = getaddr(m2, WORD);		sval2 = readmem(src, WORD) & 077;		if(sval2 & 040) sval2 |= ~077;		sval = r[rn];		psw &= ~(PSW_N | PSW_Z | PSW_V | PSW_C);		if(sval2 < 0){			if((sval >> -sval2-1) & 01) psw |= PSW_C;			sval >>= -sval2;		}else if(sval2 > 0){			mask = (sword)0100000 >> sval2;			if((sval&mask) != 0 && (sval&mask) != mask) psw |= PSW_V;			if((sval << sval2-1) & 0100000) psw |= PSW_C;			sval <<= sval2;		}		if(sval < 0) psw |= PSW_N;		if(sval == 0) psw |= PSW_Z;		r[rn] = sval;		return; 	/* ASHC */	case 0073000:{		int reg, mask; 		src = getaddr(m2, WORD);		sval = readmem(src, WORD) & 077;		if(sval & 040) sval |= ~077;		reg = r[rn]<<16;		reg |= r[rn+1];		psw &= ~(PSW_N | PSW_Z | PSW_V | PSW_C);		if(sval < 0){			if((sval >> -sval-1) & 01) psw |= PSW_C;			reg >>= -sval;		}else if(sval > 0){			mask = (sword)020000000000 >> sval;			if((reg&mask) != 0 && (reg&mask) != mask) psw |= PSW_V;			if((reg << sval-1) & 020000000000) psw |= PSW_C;			reg <<= sval;		}		if(reg < 0) psw |= PSW_N;		if(reg == 0) psw |= PSW_Z;		r[rn++] = reg>>16;		r[rn] = reg;		return;} 	/* XOR */	case 0074000:		dst = getaddr(m2, WORD);		val = r[rn];		val2 = readmem(dst, WORD);		val2 ^= val;		psw &= ~(PSW_N | PSW_Z | PSW_V);		if(val2&0100000) psw |= PSW_N;		if(val2 == 0) psw |= PSW_Z;		writemem(dst, val2, WORD);		return; 	/* SOB */	case 0077000:		if(--r[rn] != 0)			r[PC] -= m2 << 1;		return; 	/* JSR */	case 0004000:		if((m2 & 070) == 0)			trap(TRAP_INST);		val2 = getaddr(m2, WORD);		val = r[rn];		dst = getaddr(046, WORD);		writemem(dst, val, WORD);		r[rn] = r[PC];		r[PC] = val2;		return;	} 	switch(inst&0077700){	/* CLR(B) */

Lines 1–500 of 909.