plan 9 kernel history: overview | file list | diff list

1992/0721/ss/trap.c (diff list | history)

1992/0720/sys/src/9/ss/trap.c:9,141992/0721/sys/src/9/ss/trap.c:9,15 (short | long | prev | next)
1990/1223    
 
1991/0717    
void	noted(Ureg**, ulong); 
1990/1223    
void	rfnote(Ureg**); 
1992/0721    
int	domuldiv(ulong, Ureg*); 
1990/1223    
 
1990/1226    
extern	void traplink(void); 
extern	void syslink(void); 
1992/0720/sys/src/9/ss/trap.c:27,321992/0721/sys/src/9/ss/trap.c:28,34
1991/12171    
	"fp: exception", 
1990/1226    
	"data access exception", 
	"tag overflow", 
1992/0721    
	"watchpoint detected", 
1990/1223    
}; 
 
char* 
1992/0720/sys/src/9/ss/trap.c:37,531992/0721/sys/src/9/ss/trap.c:39,61
1991/1218    
	char *t; 
1990/1223    
 
1991/1218    
	switch(tbr){ 
1992/0721    
	case 36: 
1991/1218    
		return "trap: cp disabled"; 
1992/0721    
	case 37: 
		return "trap: unimplemented instruction"; 
1991/1113    
	case 40: 
1991/1218    
		return "trap: cp exception"; 
1992/0721    
	case 42: 
		return "trap: divide by zero"; 
1991/1113    
	case 128: 
		return "syscall"; 
	case 129: 
		return "breakpoint"; 
	} 
1992/0721    
	t = 0; 
1991/1218    
	if(tbr < sizeof trapname/sizeof(char*)) 
		t = trapname[tbr]; 
	else{ 
1992/0721    
	if(t == 0){ 
1991/1218    
		if(tbr >= 130) 
			sprint(xx, "trap instruction %d", tbr-128); 
		else if(17<=tbr && tbr<=31) 
1992/0720/sys/src/9/ss/trap.c:68,741992/0721/sys/src/9/ss/trap.c:76,82
1990/1223    
{ 
1991/01151    
	int user, x; 
1990/1223    
	char buf[64]; 
1990/1227    
	ulong tbr; 
1992/0721    
	ulong tbr, iw; 
1990/1223    
 
1991/1113    
	if(u) { 
1990/1223    
		u->p->pc = ur->pc;		/* BUG */ 
1992/0720/sys/src/9/ss/trap.c:118,1231992/0721/sys/src/9/ss/trap.c:126,139
1991/01151    
			}else 
				faultsparc(ur); 
			goto Return; 
1992/0721    
		case 2:				/* illegal instr, maybe mul */ 
			iw = *(ulong*)ur->pc; 
			if((iw&0xC1500000) == 0x80500000){ 
				if(domuldiv(iw, ur)) 
					goto Return; 
				tbr = ur->tbr; 
			} 
			break; 
1991/01151    
		case 4:				/* floating point disabled */ 
			if(u && u->p){ 
				if(u->p->fpstate == FPinit) 
1992/0720/sys/src/9/ss/trap.c:186,1911992/0721/sys/src/9/ss/trap.c:202,319
1990/1226    
	*(ulong*)(t+4) = 0xa7480000;	/* MOVW PSR, R19 */ 
1991/1113    
 
1990/1226    
	puttbr(TRAPS); 
1992/0721    
} 
 
void 
mulu(ulong u1, ulong u2, ulong *lop, ulong *hip) 
{ 
	ulong lo1, lo2, hi1, hi2, lo, hi, t1, t2, t; 
 
	lo1 = u1 & 0xffff; 
	lo2 = u2 & 0xffff; 
	hi1 = u1 >> 16; 
	hi2 = u2 >> 16; 
 
	lo = lo1 * lo2; 
	t1 = lo1 * hi2; 
	t2 = lo2 * hi1; 
	hi = hi1 * hi2; 
	t = lo; 
	lo += t1 << 16; 
	if(lo < t) 
		hi++; 
	t = lo; 
	lo += t2 << 16; 
	if(lo < t) 
		hi++; 
	hi += (t1 >> 16) + (t2 >> 16); 
	*lop = lo; 
	*hip = hi; 
} 
 
void 
muls(long l1, long l2, long *lop, long *hip) 
{ 
	ulong t, lo, hi; 
	ulong mlo, mhi; 
	int sign; 
 
	sign = 0; 
	if(l1 < 0){ 
		sign ^= 1; 
		l1 = -l1; 
	} 
	if(l2 < 0){ 
		sign ^= 1; 
		l2 = -l2; 
	} 
	mulu(l1, l2, &mlo, &mhi); 
	lo = mlo; 
	hi = mhi; 
	if(sign){ 
		t = lo = ~lo; 
		hi = ~hi; 
		lo++; 
		if(lo < t) 
			hi++; 
	} 
	*lop = lo; 
	*hip = hi; 
} 
 
int 
domuldiv(ulong iw, Ureg *ur) 
{ 
	long op1, op2; 
	long *regp; 
	long *regs; 
 
	regs = (long*)ur; 
	if(iw & (1<<13)){	/* signed immediate */ 
		op2 = iw & 0x1FFF; 
		if(op2 & 0x1000) 
			op2 |= ~0x1FFF; 
	}else 
		op2 = regs[iw&0x1F]; 
	op1 = regs[(iw>>14)&0x1F]; 
	regp = ®s[(iw>>25)&0x1F]; 
 
	if(iw & (4<<19)){	/* divide */ 
		if(ur->y!=0 && ur->y!=~0){ 
	unimp: 
			ur->tbr = 37;	/* "unimplemented instruction" */ 
			return 0;	/* complex Y is too hard */ 
		} 
		if(op2 == 0){ 
			ur->tbr = 42;	/* "zero divide" */ 
			return 0; 
		} 
		if(iw & (1<<19)){ 
			if(ur->y && (op1&(1<<31))==0) 
				goto unimp;	/* Y not sign extension */ 
			*regp = op1 / op2; 
		}else{ 
			if(ur->y) 
				goto unimp; 
			*regp = (ulong)op1 / (ulong)op2; 
		} 
	}else{ 
		if(iw & (1<<19)) 
			muls(op1, op2, regp, (long*)&ur->y); 
		else 
			mulu(op1, op2, (ulong*)regp, &ur->y); 
	} 
	if(iw & (16<<19)){	/* set CC */ 
		ur->psr &= ~(0xF << 20); 
		if(*regp & (1<<31)) 
			ur->psr |= 8 << 20;	/* N */ 
		if(*regp == 0) 
			ur->psr |= 4 << 20;	/* Z */ 
		/* BUG: don't get overflow right on divide */ 
	} 
	ur->pc += 4; 
	ur->npc = ur->pc+4; 
	return 1; 
1990/1226    
} 
 
void 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)