⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reg_ld_str.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
			((long *) &tll)[0] = 0;		} else			return 0;	} else		if (t.sign)			tll = -tll;	REENTRANT_CHECK(OFF);/*	    verify_area(VERIFY_WRITE, (void *) d, 8); */	suword((unsigned long *) d, ((long *) &tll)[0]);	suword(1 + (unsigned long *) d, ((long *) &tll)[1]);	REENTRANT_CHECK(ON);	return 1;}/* Put a long into user memory */intreg_store_int32(void){	long   *d = (long *) FPU_data_address;	FPU_REG t;	if (FPU_st0_tag == TW_Empty) {		/* Empty register (stack underflow) */		EXCEPTION(EX_StackUnder);		if (control_word & EX_Invalid) {			/* The masked response */			/* Put out the QNaN indefinite */			REENTRANT_CHECK(OFF);/*			    verify_area(VERIFY_WRITE, d, 4);*/			suword((unsigned long *) d, 0x80000000);			REENTRANT_CHECK(ON);			return 1;		} else			return 0;	}	reg_move(FPU_st0_ptr, &t);	round_to_int(&t);	if (t.sigh ||	    ((t.sigl & 0x80000000) &&		!((t.sigl == 0x80000000) && (t.sign == SIGN_NEG)))) {		EXCEPTION(EX_Invalid);		/* This is a special case: see sec 16.2.5.1 of the 80486 book */		if (control_word & EX_Invalid) {			/* Produce "indefinite" */			t.sigl = 0x80000000;		} else			return 0;	} else		if (t.sign)			t.sigl = -(long) t.sigl;	REENTRANT_CHECK(OFF);/*	    verify_area(VERIFY_WRITE, d, 4); */	suword((unsigned long *) d, t.sigl);	REENTRANT_CHECK(ON);	return 1;}/* Put a short into user memory */intreg_store_int16(void){	short  *d = (short *) FPU_data_address;	FPU_REG t;	short   ts;	if (FPU_st0_tag == TW_Empty) {		/* Empty register (stack underflow) */		EXCEPTION(EX_StackUnder);		if (control_word & EX_Invalid) {			/* The masked response */			/* Put out the QNaN indefinite */			REENTRANT_CHECK(OFF);/*			    verify_area(VERIFY_WRITE, d, 2);*/			susword((unsigned short *) d, 0x8000);			REENTRANT_CHECK(ON);			return 1;		} else			return 0;	}	reg_move(FPU_st0_ptr, &t);	round_to_int(&t);	if (t.sigh ||	    ((t.sigl & 0xffff8000) &&		!((t.sigl == 0x8000) && (t.sign == SIGN_NEG)))) {		EXCEPTION(EX_Invalid);		/* This is a special case: see sec 16.2.5.1 of the 80486 book */		if (control_word & EX_Invalid) {			/* Produce "indefinite" */			ts = 0x8000;		} else			return 0;	} else		if (t.sign)			t.sigl = -t.sigl;	REENTRANT_CHECK(OFF);/*	    verify_area(VERIFY_WRITE, d, 2); */	susword((short *) d, (short) t.sigl);	REENTRANT_CHECK(ON);	return 1;}/* Put a packed bcd array into user memory */intreg_store_bcd(void){	char   *d = (char *) FPU_data_address;	FPU_REG t;	long long ll;	unsigned char b;	int     i;	unsigned char sign = (FPU_st0_ptr->sign == SIGN_NEG) ? 0x80 : 0;	if (FPU_st0_tag == TW_Empty) {		/* Empty register (stack underflow) */		EXCEPTION(EX_StackUnder);		if (control_word & EX_Invalid) {			/* The masked response */			/* Put out the QNaN indefinite */			goto put_indefinite;		} else			return 0;	}	reg_move(FPU_st0_ptr, &t);	round_to_int(&t);	ll = *(long long *) (&t.sigl);	/* Check for overflow, by comparing with 999999999999999999 decimal. */	if ((t.sigh > 0x0de0b6b3) ||	    ((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff))) {		EXCEPTION(EX_Invalid);		/* This is a special case: see sec 16.2.5.1 of the 80486 book */		if (control_word & EX_Invalid) {	put_indefinite:			/* Produce "indefinite" */			REENTRANT_CHECK(OFF);/*			    verify_area(VERIFY_WRITE, d, 10);*/			subyte((unsigned char *) d + 7, 0xff);			subyte((unsigned char *) d + 8, 0xff);			subyte((unsigned char *) d + 9, 0xff);			REENTRANT_CHECK(ON);			return 1;		} else			return 0;	}/*	verify_area(VERIFY_WRITE, d, 10);*/	for (i = 0; i < 9; i++) {		b = div_small(&ll, 10);		b |= (div_small(&ll, 10)) << 4;		REENTRANT_CHECK(OFF);		subyte((unsigned char *) d + i, b);		REENTRANT_CHECK(ON);	}	REENTRANT_CHECK(OFF);	subyte((unsigned char *) d + 9, sign);	REENTRANT_CHECK(ON);	return 1;}/*===========================================================================*//* r gets mangled such that sig is int, sign:   it is NOT normalized *//* The return value (in eax) is zero if the result is exact,   if bits are changed due to rounding, truncation, etc, then   a non-zero value is returned *//* Overflow is signalled by a non-zero return value (in eax).   In the case of overflow, the returned significand always has the   the largest possible value *//* The value returned in eax is never actually needed :-) */intround_to_int(FPU_REG * r){	char    very_big;	unsigned eax;	if (r->tag == TW_Zero) {		/* Make sure that zero is returned */		*(long long *) &r->sigl = 0;		return 0;	/* o.k. */	}	if (r->exp > EXP_BIAS + 63) {		r->sigl = r->sigh = ~0;	/* The largest representable number */		return 1;	/* overflow */	}	eax = shrxs(&r->sigl, EXP_BIAS + 63 - r->exp);	very_big = !(~(r->sigh) | ~(r->sigl));	/* test for 0xfff...fff */#define	half_or_more	(eax & 0x80000000)#define	frac_part	(eax)#define more_than_half  ((eax & 0x80000001) == 0x80000001)	switch (control_word & CW_RC) {	case RC_RND:		if (more_than_half	/* nearest */		    || (half_or_more && (r->sigl & 1))) {	/* odd -> even */			if (very_big)				return 1;	/* overflow */			(*(long long *) (&r->sigl))++;			return LOST_UP;		}		break;	case RC_DOWN:		if (frac_part && r->sign) {			if (very_big)				return 1;	/* overflow */			(*(long long *) (&r->sigl))++;			return LOST_UP;		}		break;	case RC_UP:		if (frac_part && !r->sign) {			if (very_big)				return 1;	/* overflow */			(*(long long *) (&r->sigl))++;			return LOST_UP;		}		break;	case RC_CHOP:		break;	}	return eax ? LOST_DOWN : 0;}/*===========================================================================*/char   *fldenv(void){	char   *s = (char *) FPU_data_address;	unsigned short tag_word = 0;	unsigned char tag;	int     i;	REENTRANT_CHECK(OFF);	control_word = fusword((unsigned short *) s);	status_word = fusword((unsigned short *) (s + 4));	tag_word = fusword((unsigned short *) (s + 8));	ip_offset = fuword((unsigned long *) (s + 0x0c));	cs_selector = fuword((unsigned long *) (s + 0x10));	data_operand_offset = fuword((unsigned long *) (s + 0x14));	operand_selector = fuword((unsigned long *) (s + 0x18));	REENTRANT_CHECK(ON);	top = (status_word >> SW_Top_Shift) & 7;	for (i = 0; i < 8; i++) {		tag = tag_word & 3;		tag_word >>= 2;		switch (tag) {		case 0:			regs[i].tag = TW_Valid;			break;		case 1:			regs[i].tag = TW_Zero;			break;		case 2:			regs[i].tag = TW_NaN;			break;		case 3:			regs[i].tag = TW_Empty;			break;		}	}	FPU_data_address = (void *) data_operand_offset;	/* We want no net effect */	FPU_entry_eip = ip_offset;	/* We want no net effect */	return s + 0x1c;}voidfrstor(void){	int     i, stnr;	unsigned char tag;	unsigned short saved_status, saved_control;	char   *s = (char *) fldenv();	saved_status = status_word;	saved_control = control_word;	control_word = 0x037f;	/* Mask all interrupts while we load. */	for (i = 0; i < 8; i++) {		/* load each register */		FPU_data_address = (void *) (s + i * 10);		reg_load_extended();		stnr = (i + top) & 7;		tag = regs[stnr].tag;	/* derived from the loaded tag word */		reg_move(&FPU_loaded_data, &regs[stnr]);		if (tag == TW_NaN) {			/* The current data is a special, i.e. NaN,			 * unsupported, infinity, or denormal */			unsigned char t = regs[stnr].tag;	/* derived from the new								 * data */			if ( /* (t == TW_Valid) || *** */ (t == TW_Zero))				regs[stnr].tag = TW_NaN;		} else			regs[stnr].tag = tag;	}	control_word = saved_control;	status_word = saved_status;	FPU_data_address = (void *) data_operand_offset;	/* We want no net effect */}unsigned shorttag_word(void){	unsigned short word = 0;	unsigned char tag;	int     i;	for (i = 7; i >= 0; i--) {		switch (tag = regs[i].tag) {#if 0				/* TW_Denormal is not used yet, and probably				 * won't be */		case TW_Denormal:#endif		case TW_Valid:			if (regs[i].exp <= (EXP_BIAS - EXTENDED_Ebias))				tag = 2;			break;		case TW_Infinity:		case TW_NaN:			tag = 2;			break;		case TW_Empty:			tag = 3;			break;			/* TW_Valid and TW_Zero already have the correct value */		}		word <<= 2;		word |= tag;	}	return word;}char   *fstenv(void){	char   *d = (char *) FPU_data_address;/*	verify_area(VERIFY_WRITE, d, 28);*/#if 0				/****/	*(unsigned short *) &cs_selector = fpu_cs;	*(unsigned short *) &operand_selector = fpu_os;#endif				/****/	REENTRANT_CHECK(OFF);	susword((unsigned short *) d, control_word);	susword((unsigned short *) (d + 4), (status_word & ~SW_Top) | ((top & 7) << SW_Top_Shift));	susword((unsigned short *) (d + 8), tag_word());	suword((unsigned long *) (d + 0x0c), ip_offset);	suword((unsigned long *) (d + 0x10), cs_selector);	suword((unsigned long *) (d + 0x14), data_operand_offset);	suword((unsigned long *) (d + 0x18), operand_selector);	REENTRANT_CHECK(ON);	return d + 0x1c;}voidfsave(void){	char   *d;	FPU_REG tmp, *rp;	int     i;	short   e;	d = fstenv();/*	verify_area(VERIFY_WRITE, d, 80);*/	for (i = 0; i < 8; i++) {		/* Store each register in the order: st(0), st(1), ... */		rp = &regs[(top + i) & 7];		e = rp->exp - EXP_BIAS + EXTENDED_Ebias;		if (rp->tag == TW_Valid) {			if (e >= 0x7fff) {				/* Overflow to infinity */				REENTRANT_CHECK(OFF);				suword((unsigned long *) (d + i * 10), 0);				suword((unsigned long *) (d + i * 10 + 4), 0);				REENTRANT_CHECK(ON);				e = 0x7fff;			} else				if (e <= 0) {					if (e > -63) {						/* Make a de-normal */						reg_move(rp, &tmp);						tmp.exp += -EXTENDED_Emin + 63;	/* largest exp to be 62 */						round_to_int(&tmp);						REENTRANT_CHECK(OFF);						suword((unsigned long *) (d + i * 10), tmp.sigl);						suword((unsigned long *) (d + i * 10 + 4), tmp.sigh);						REENTRANT_CHECK(ON);					} else {						/* Underflow to zero */						REENTRANT_CHECK(OFF);						suword((unsigned long *) (d + i * 10), 0);						suword((unsigned long *) (d + i * 10 + 4), 0);						REENTRANT_CHECK(ON);					}					e = 0;				} else {					REENTRANT_CHECK(OFF);					suword((unsigned long *) (d + i * 10), rp->sigl);					suword((unsigned long *) (d + i * 10 + 4), rp->sigh);					REENTRANT_CHECK(ON);				}		} else			if (rp->tag == TW_Zero) {				REENTRANT_CHECK(OFF);				suword((unsigned long *) (d + i * 10), 0);				suword((unsigned long *) (d + i * 10 + 4), 0);				REENTRANT_CHECK(ON);				e = 0;			} else				if (rp->tag == TW_Infinity) {					REENTRANT_CHECK(OFF);					suword((unsigned long *) (d + i * 10), 0);					suword((unsigned long *) (d + i * 10 + 4), 0x80000000);					REENTRANT_CHECK(ON);					e = 0x7fff;				} else					if (rp->tag == TW_NaN) {						REENTRANT_CHECK(OFF);						suword((unsigned long *) (d + i * 10), rp->sigl);						suword((unsigned long *) (d + i * 10 + 4), rp->sigh);						REENTRANT_CHECK(ON);						e = 0x7fff;					} else						if (rp->tag == TW_Empty) {							/* just copy the reg */							REENTRANT_CHECK(OFF);							suword((unsigned long *) (d + i * 10), rp->sigl);							suword((unsigned long *) (d + i * 10 + 4), rp->sigh);							REENTRANT_CHECK(ON);						}		e |= rp->sign == SIGN_POS ? 0 : 0x8000;		REENTRANT_CHECK(OFF);		susword((unsigned short *) (d + i * 10 + 8), e);		REENTRANT_CHECK(ON);	}	finit();}/*===========================================================================*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -