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

📄 reg_ld_str.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
						/* This is a special case: see						 * sec 16.2.5.1 of the 80486						 * book */						if (!(control_word & EX_Underflow))							return 0;					}					e = 0;					ls = tmp.sigl;					ms = tmp.sigh;				} else {					/* ****** ??? This should not be					 * possible */					EXCEPTION(EX_Underflow);	/* Underflow */					/* This is a special case: see sec					 * 16.2.5.1 of the 80486 book */					if (control_word & EX_Underflow) {						/* Underflow to zero */						ls = 0;						ms = 0;						e = FPU_st0_ptr->sign == SIGN_POS ? 0x7fff : 0xffff;					} else						return 0;				}			} else {				ls = FPU_st0_ptr->sigl;				ms = FPU_st0_ptr->sigh;			}	} else		if (FPU_st0_tag == TW_Zero) {			ls = ms = 0;			e = 0;		} else			if (FPU_st0_tag == TW_Infinity) {				ls = 0;				ms = 0x80000000;				e = 0x7fff;			} else				if (FPU_st0_tag == TW_NaN) {					ls = FPU_st0_ptr->sigl;					ms = FPU_st0_ptr->sigh;					e = 0x7fff;				} else					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 */							ls = 0;							ms = 0xc0000000;							e = 0xffff;						} else							return 0;					} else {						/* We don't use TW_Denormal						 * yet ... perhaps never! */						EXCEPTION(EX_Invalid);						/* Store a NaN */						e = 0x7fff;						ls = 1;						ms = 0x80000000;					}	REENTRANT_CHECK(OFF);/*	    verify_area(VERIFY_WRITE, d, 10); */	suword((unsigned long *) d, ls);	suword(1 + (unsigned long *) d, ms);	susword(4 + (short *) d, (unsigned short) e | sign);	REENTRANT_CHECK(ON);	return 1;}/* Put a double into user memory */intreg_store_double(void){	double *dfloat = (double *) FPU_data_address;	unsigned long l[2];	if (FPU_st0_tag == TW_Valid) {		int     exp;		FPU_REG tmp;		reg_move(FPU_st0_ptr, &tmp);		exp = tmp.exp - EXP_BIAS;		if (exp < DOUBLE_Emin) {	/* It may be a denormal */			/* Make a de-normal */			int     precision_loss;			if (exp <= -EXTENDED_Ebias)				EXCEPTION(EX_Denormal);			tmp.exp += -DOUBLE_Emin + 52;	/* largest exp to be 51 */			if ((precision_loss = round_to_int(&tmp))) {#ifdef PECULIAR_486				/* Did it round to a non-denormal ? */				/* This behaviour might be regarded as				 * peculiar, it appears that the 80486 rounds				 * to the dest precision, then converts to				 * decide underflow. */				if ((tmp.sigh == 0x00100000) && (tmp.sigl == 0) &&				    (FPU_st0_ptr->sigl & 0x000007ff))					EXCEPTION(precision_loss);				else#endif				/* PECULIAR_486 */				{					EXCEPTION(EX_Underflow | precision_loss);					/* This is a special case: see sec					 * 16.2.5.1 of the 80486 book */					if (!(control_word & EX_Underflow))						return 0;				}			}			l[0] = tmp.sigl;			l[1] = tmp.sigh;		} else {			if (tmp.sigl & 0x000007ff) {				unsigned long increment = 0;	/* avoid gcc warnings */				switch (control_word & CW_RC) {				case RC_RND:					/* Rounding can get a little messy.. */					increment = ((tmp.sigl & 0x7ff) > 0x400) |	/* nearest */					    ((tmp.sigl & 0xc00) == 0xc00);	/* odd -> even */					break;				case RC_DOWN:	/* towards -infinity */					increment = (tmp.sign == SIGN_POS) ? 0 : tmp.sigl & 0x7ff;					break;				case RC_UP:	/* towards +infinity */					increment = (tmp.sign == SIGN_POS) ? tmp.sigl & 0x7ff : 0;					break;				case RC_CHOP:					increment = 0;					break;				}				/* Truncate the mantissa */				tmp.sigl &= 0xfffff800;				if (increment) {					set_precision_flag_up();					if (tmp.sigl >= 0xfffff800) {						/* the sigl part overflows */						if (tmp.sigh == 0xffffffff) {							/* The sigh part							 * overflows */							tmp.sigh = 0x80000000;							exp++;							if (exp >= EXP_OVER)								goto overflow;						} else {							tmp.sigh++;						}						tmp.sigl = 0x00000000;					} else {						/* We only need to increment						 * sigl */						tmp.sigl += 0x00000800;					}				} else					set_precision_flag_down();			}			l[0] = (tmp.sigl >> 11) | (tmp.sigh << 21);			l[1] = ((tmp.sigh >> 11) & 0xfffff);			if (exp > DOUBLE_Emax) {		overflow:				EXCEPTION(EX_Overflow);				/* This is a special case: see sec 16.2.5.1 of				 * the 80486 book */				if (control_word & EX_Overflow) {					/* Overflow to infinity */					l[0] = 0x00000000;	/* Set to */					l[1] = 0x7ff00000;	/* + INF */				} else					return 0;			} else {				/* Add the exponent */				l[1] |= (((exp + DOUBLE_Ebias) & 0x7ff) << 20);			}		}	} else		if (FPU_st0_tag == TW_Zero) {			/* Number is zero */			l[0] = 0;			l[1] = 0;		} else			if (FPU_st0_tag == TW_Infinity) {				l[0] = 0;				l[1] = 0x7ff00000;			} else				if (FPU_st0_tag == TW_NaN) {					/* See if we can get a valid NaN from					 * the FPU_REG */					l[0] = (FPU_st0_ptr->sigl >> 11) | (FPU_st0_ptr->sigh << 21);					l[1] = ((FPU_st0_ptr->sigh >> 11) & 0xfffff);					if (!(l[0] | l[1])) {						/* This case does not seem to						 * be handled by the 80486						 * specs */						EXCEPTION(EX_Invalid);						/* Make the quiet NaN "real						 * indefinite" */						goto put_indefinite;					}					l[1] |= 0x7ff00000;				} else					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 */					put_indefinite:							REENTRANT_CHECK(OFF);							/* verify_area(VERIFY_W							 * RITE, (void *)							 * dfloat, 8); */							suword((unsigned long *) dfloat, 0);							suword(1 + (unsigned long *) dfloat, 0xfff80000);							REENTRANT_CHECK(ON);							return 1;						} else							return 0;					}#if 0				/* TW_Denormal is not used yet, and probably				 * won't be */					else						if (FPU_st0_tag == TW_Denormal) {							/* Extended real ->							 * double real will							 * always underflow */							l[0] = l[1] = 0;							EXCEPTION(EX_Underflow);						}#endif	if (FPU_st0_ptr->sign)		l[1] |= 0x80000000;	REENTRANT_CHECK(OFF);/*	    verify_area(VERIFY_WRITE, (void *) dfloat, 8);*/	suword((u_long *) dfloat, l[0]);	suword((u_long *) dfloat + 1, l[1]);/*	suword(l[0], (unsigned long *) dfloat);	suword(l[1], 1 + (unsigned long *) dfloat);*/	REENTRANT_CHECK(ON);	return 1;}/* Put a float into user memory */intreg_store_single(void){	float  *single = (float *) FPU_data_address;	long    templ = 0;	if (FPU_st0_tag == TW_Valid) {		int     exp;		FPU_REG tmp;		reg_move(FPU_st0_ptr, &tmp);		exp = tmp.exp - EXP_BIAS;		if (exp < SINGLE_Emin) {			/* Make a de-normal */			int     precision_loss;			if (exp <= -EXTENDED_Ebias)				EXCEPTION(EX_Denormal);			tmp.exp += -SINGLE_Emin + 23;	/* largest exp to be 22 */			if ((precision_loss = round_to_int(&tmp))) {#ifdef PECULIAR_486				/* Did it round to a non-denormal ? */				/* This behaviour might be regarded as				 * peculiar, it appears that the 80486 rounds				 * to the dest precision, then converts to				 * decide underflow. */				if ((tmp.sigl == 0x00800000) &&				    ((FPU_st0_ptr->sigh & 0x000000ff) || FPU_st0_ptr->sigl))					EXCEPTION(precision_loss);				else#endif				/* PECULIAR_486 */				{					EXCEPTION(EX_Underflow | precision_loss);					/* This is a special case: see sec					 * 16.2.5.1 of the 80486 book */					if (!(control_word & EX_Underflow))						return 0;				}			}			templ = tmp.sigl;		} else {			if (tmp.sigl | (tmp.sigh & 0x000000ff)) {				unsigned long increment = 0;	/* avoid gcc warnings */				unsigned long sigh = tmp.sigh;				unsigned long sigl = tmp.sigl;				switch (control_word & CW_RC) {				case RC_RND:					increment = ((sigh & 0xff) > 0x80)	/* more than half */					    ||(((sigh & 0xff) == 0x80) && sigl)	/* more than half */					    ||((sigh & 0x180) == 0x180);	/* round to even */					break;				case RC_DOWN:	/* towards -infinity */					increment = (tmp.sign == SIGN_POS)					    ? 0 : (sigl | (sigh & 0xff));					break;				case RC_UP:	/* towards +infinity */					increment = (tmp.sign == SIGN_POS)					    ? (sigl | (sigh & 0xff)) : 0;					break;				case RC_CHOP:					increment = 0;					break;				}				/* Truncate part of the mantissa */				tmp.sigl = 0;				if (increment) {					set_precision_flag_up();					if (sigh >= 0xffffff00) {						/* The sigh part overflows */						tmp.sigh = 0x80000000;						exp++;						if (exp >= EXP_OVER)							goto overflow;					} else {						tmp.sigh &= 0xffffff00;						tmp.sigh += 0x100;					}				} else {					set_precision_flag_down();					tmp.sigh &= 0xffffff00;	/* Finish the truncation */				}			}			templ = (tmp.sigh >> 8) & 0x007fffff;			if (exp > SINGLE_Emax) {		overflow:				EXCEPTION(EX_Overflow);				/* This is a special case: see sec 16.2.5.1 of				 * the 80486 book */				if (control_word & EX_Overflow) {					/* Overflow to infinity */					templ = 0x7f800000;				} else					return 0;			} else				templ |= ((exp + SINGLE_Ebias) & 0xff) << 23;		}	} else		if (FPU_st0_tag == TW_Zero) {			templ = 0;		} else			if (FPU_st0_tag == TW_Infinity) {				templ = 0x7f800000;			} else				if (FPU_st0_tag == TW_NaN) {					/* See if we can get a valid NaN from					 * the FPU_REG */					templ = FPU_st0_ptr->sigh >> 8;					if (!(templ & 0x3fffff)) {						/* This case does not seem to						 * be handled by the 80486						 * specs */						EXCEPTION(EX_Invalid);						/* Make the quiet NaN "real						 * indefinite" */						goto put_indefinite;					}					templ |= 0x7f800000;				} else					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 */					put_indefinite:							REENTRANT_CHECK(OFF);/*							    verify_area(VERIFY_WRITE, (void *) single, 4); */							suword((unsigned long *) single, 0xffc00000);							REENTRANT_CHECK(ON);							return 1;						} else							return 0;					}#if 0				/* TW_Denormal is not used yet, and probably				 * won't be */					else						if (FPU_st0_tag == TW_Denormal) {							/* Extended real ->							 * real will always							 * underflow */							templ = 0;							EXCEPTION(EX_Underflow);						}#endif#ifdef PARANOID						else {							EXCEPTION(EX_INTERNAL | 0x106);							return 0;						}#endif	if (FPU_st0_ptr->sign)		templ |= 0x80000000;	REENTRANT_CHECK(OFF);/*	    verify_area(VERIFY_WRITE, (void *) single, 4); */	suword((unsigned long *) single, templ);	REENTRANT_CHECK(ON);	return 1;}/* Put a long long into user memory */intreg_store_int64(void){	long long *d = (long long *) FPU_data_address;	FPU_REG t;	long long tll;	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);	((long *) &tll)[0] = t.sigl;	((long *) &tll)[1] = t.sigh;	if ((t.sigh & 0x80000000) &&	    !((t.sigh == 0x80000000) && (t.sigl == 0) && (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" */	put_indefinite:			((long *) &tll)[1] = 0x80000000;

⌨️ 快捷键说明

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