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

📄 fpu_trig.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
			reg_sub(&CONST_PI, &sum, &sum, FULL_PRECISION);		}		if (quadrant & 1)			sum.sign ^= SIGN_POS ^ SIGN_NEG;		/* All of the basic arithmetic is done now */		control_word = saved_control;		status_word = saved_status;		reg_move(&sum, st1_ptr);	} else		if ((FPU_st0_tag == TW_Empty) || (st1_tag == TW_Empty)) {			stack_underflow_pop(1);			return;		} else			if ((FPU_st0_tag == TW_NaN) || (st1_tag == TW_NaN)) {				real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr);				pop();				return;			} else				if ((FPU_st0_tag == TW_Infinity) || (st1_tag == TW_Infinity)) {					char    sign = st1_ptr->sign;					if (FPU_st0_tag == TW_Infinity) {						if (st1_tag == TW_Infinity) {							if (FPU_st0_ptr->sign == SIGN_POS) {								reg_move(&CONST_PI4, st1_ptr);							} else								reg_add(&CONST_PI4, &CONST_PI2, st1_ptr, FULL_PRECISION);						} else {#ifdef DENORM_OPERAND							if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand()))								return;#endif				/* DENORM_OPERAND */							if (FPU_st0_ptr->sign == SIGN_POS) {								reg_move(&CONST_Z, st1_ptr);								pop();								return;							} else								reg_move(&CONST_PI, st1_ptr);						}					} else {						/* st(1) is infinity, st(0)						 * not infinity */#ifdef DENORM_OPERAND						if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))							return;#endif				/* DENORM_OPERAND */						reg_move(&CONST_PI2, st1_ptr);					}					st1_ptr->sign = sign;				} else					if (st1_tag == TW_Zero) {						/* st(0) must be valid or zero */						char    sign = st1_ptr->sign;#ifdef DENORM_OPERAND						if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))							return;#endif				/* DENORM_OPERAND */						if (FPU_st0_ptr->sign == SIGN_POS) {							reg_move(&CONST_Z, st1_ptr);							pop();							return;						} else							reg_move(&CONST_PI, st1_ptr);						st1_ptr->sign = sign;					} else						if (FPU_st0_tag == TW_Zero) {							/* st(1) must be							 * TW_Valid here */							char    sign = st1_ptr->sign;#ifdef DENORM_OPERAND							if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand()))								return;#endif				/* DENORM_OPERAND */							reg_move(&CONST_PI2, st1_ptr);							st1_ptr->sign = sign;						}#ifdef PARANOID						else							EXCEPTION(EX_INTERNAL | 0x220);#endif				/* PARANOID */	pop();	set_precision_flag_up();/* We do not really know if up or down */}static voidfprem(void){	fprem_kernel(RC_CHOP);}static voidfprem1(void){	fprem_kernel(RC_RND);}static voidfyl2xp1(void){	FPU_REG *st1_ptr = &st(1);	char    st1_tag = st1_ptr->tag;	if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) {		int     saved_control, saved_status;#ifdef DENORM_OPERAND		if (((FPU_st0_ptr->exp <= EXP_UNDER) ||			(st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()))			return;#endif				/* DENORM_OPERAND */		/* We use the general purpose arithmetic so we need to save		 * these. */		saved_status = status_word;		saved_control = control_word;		control_word = FULL_PRECISION;		if (poly_l2p1(FPU_st0_ptr, FPU_st0_ptr)) {			arith_invalid(st1_ptr);	/* poly_l2p1() returned						 * invalid */			pop();			return;		}		/* Enough of the basic arithmetic is done now */		control_word = saved_control;		status_word = saved_status;		/* Let the multiply set the flags */		reg_mul(FPU_st0_ptr, st1_ptr, st1_ptr, FULL_PRECISION);		pop();	} else		if ((FPU_st0_tag == TW_Empty) | (st1_tag == TW_Empty)) {			stack_underflow_pop(1);			return;		} else			if (FPU_st0_tag == TW_Zero) {				if (st1_tag <= TW_Zero) {#ifdef DENORM_OPERAND					if ((st1_tag == TW_Valid) && (st1_ptr->exp <= EXP_UNDER) &&					    (denormal_operand()))						return;#endif				/* DENORM_OPERAND */					st1_ptr->sign ^= FPU_st0_ptr->sign;					reg_move(FPU_st0_ptr, st1_ptr);				} else					if (st1_tag == TW_Infinity) {						arith_invalid(st1_ptr);	/* Infinity*log(1) */						pop();						return;					} else						if (st1_tag == TW_NaN) {							real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr);							pop();							return;						}#ifdef PARANOID						else {							EXCEPTION(EX_INTERNAL | 0x116);							return;						}#endif				/* PARANOID */				pop();				return;			} else				if (FPU_st0_tag == TW_Valid) {					if (st1_tag == TW_Zero) {						if (FPU_st0_ptr->sign == SIGN_NEG) {							if (FPU_st0_ptr->exp >= EXP_BIAS) {								/* st(0) holds								 * <= -1.0 */								arith_invalid(st1_ptr);	/* infinity*log(1) */								pop();								return;							}#ifdef DENORM_OPERAND							if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))								return;#endif				/* DENORM_OPERAND */							st1_ptr->sign ^= SIGN_POS ^ SIGN_NEG;							pop();							return;						}#ifdef DENORM_OPERAND						if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))							return;#endif				/* DENORM_OPERAND */						pop();						return;					}					if (st1_tag == TW_Infinity) {						if (FPU_st0_ptr->sign == SIGN_NEG) {							if ((FPU_st0_ptr->exp >= EXP_BIAS) &&							    !((FPU_st0_ptr->sigh == 0x80000000) &&								(FPU_st0_ptr->sigl == 0))) {								/* st(0) holds								 * < -1.0 */								arith_invalid(st1_ptr);								pop();								return;							}#ifdef DENORM_OPERAND							if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))								return;#endif				/* DENORM_OPERAND */							st1_ptr->sign ^= SIGN_POS ^ SIGN_NEG;							pop();							return;						}#ifdef DENORM_OPERAND						if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))							return;#endif				/* DENORM_OPERAND */						pop();						return;					}					if (st1_tag == TW_NaN) {						real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr);						pop();						return;					}				} else					if (FPU_st0_tag == TW_NaN) {						real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr);						pop();						return;					} else						if (FPU_st0_tag == TW_Infinity) {							if (st1_tag == TW_NaN) {								real_2op_NaN(FPU_st0_ptr, st1_ptr, st1_ptr);								pop();								return;							} else								if ((FPU_st0_ptr->sign == SIGN_NEG) ||								    (st1_tag == TW_Zero)) {									arith_invalid(st1_ptr);	/* log(infinity) */									pop();									return;								}							/* st(1) must be valid							 * here. */#ifdef DENORM_OPERAND							if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand()))								return;#endif				/* DENORM_OPERAND */							/* The Manual says							 * that log(Infinity)							 * is invalid, but a							 * real 80486 sensibly							 * says that it is							 * o.k. */							{								char    sign = st1_ptr->sign;								reg_move(&CONST_INF, st1_ptr);								st1_ptr->sign = sign;							}							pop();							return;						}#ifdef PARANOID						else {							EXCEPTION(EX_INTERNAL | 0x117);						}#endif				/* PARANOID */}static voidemu_fscale(void){	FPU_REG *st1_ptr = &st(1);	char    st1_tag = st1_ptr->tag;	int     old_cw = control_word;	if (!((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid))) {		long    scale;		FPU_REG tmp;#ifdef DENORM_OPERAND		if (((FPU_st0_ptr->exp <= EXP_UNDER) ||			(st1_ptr->exp <= EXP_UNDER)) && (denormal_operand()))			return;#endif				/* DENORM_OPERAND */		if (st1_ptr->exp > EXP_BIAS + 30) {			/* 2^31 is far too large, would require 2^(2^30) or			 * 2^(-2^30) */			char    sign;			if (st1_ptr->sign == SIGN_POS) {				EXCEPTION(EX_Overflow);				sign = FPU_st0_ptr->sign;				reg_move(&CONST_INF, FPU_st0_ptr);				FPU_st0_ptr->sign = sign;			} else {				EXCEPTION(EX_Underflow);				sign = FPU_st0_ptr->sign;				reg_move(&CONST_Z, FPU_st0_ptr);				FPU_st0_ptr->sign = sign;			}			return;		}		control_word &= ~CW_RC;		control_word |= RC_CHOP;		reg_move(st1_ptr, &tmp);		round_to_int(&tmp);	/* This can never overflow here */		control_word = old_cw;		scale = st1_ptr->sign ? -tmp.sigl : tmp.sigl;		scale += FPU_st0_ptr->exp;		FPU_st0_ptr->exp = scale;		/* Use round_reg() to properly detect under/overflow etc */		round_reg(FPU_st0_ptr, 0, control_word);		return;	} else		if (FPU_st0_tag == TW_Valid) {			if (st1_tag == TW_Zero) {#ifdef DENORM_OPERAND				if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))					return;#endif				/* DENORM_OPERAND */				return;			}			if (st1_tag == TW_Infinity) {				char    sign = st1_ptr->sign;#ifdef DENORM_OPERAND				if ((FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()))					return;#endif				/* DENORM_OPERAND */				if (sign == SIGN_POS) {					reg_move(&CONST_INF, FPU_st0_ptr);				} else					reg_move(&CONST_Z, FPU_st0_ptr);				FPU_st0_ptr->sign = sign;				return;			}			if (st1_tag == TW_NaN) {				real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr);				return;			}		} else			if (FPU_st0_tag == TW_Zero) {				if (st1_tag == TW_Valid) {#ifdef DENORM_OPERAND					if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand()))						return;#endif				/* DENORM_OPERAND */					return;				} else					if (st1_tag == TW_Zero) {						return;					} else						if (st1_tag == TW_Infinity) {							if (st1_ptr->sign == SIGN_NEG)								return;							else {								arith_invalid(FPU_st0_ptr);	/* Zero scaled by												 * +Infinity */								return;							}						} else							if (st1_tag == TW_NaN) {								real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr);								return;							}			} else				if (FPU_st0_tag == TW_Infinity) {					if (st1_tag == TW_Valid) {#ifdef DENORM_OPERAND						if ((st1_ptr->exp <= EXP_UNDER) && (denormal_operand()))							return;#endif				/* DENORM_OPERAND */						return;					}					if (((st1_tag == TW_Infinity) && (st1_ptr->sign == SIGN_POS))					    || (st1_tag == TW_Zero))						return;					else						if (st1_tag == TW_Infinity) {							arith_invalid(FPU_st0_ptr);	/* Infinity scaled by											 * -Infinity */							return;						} else							if (st1_tag == TW_NaN) {								real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr);								return;							}				} else					if (FPU_st0_tag == TW_NaN) {						if (st1_tag != TW_Empty) {							real_2op_NaN(FPU_st0_ptr, st1_ptr, FPU_st0_ptr);							return;						}					}#ifdef PARANOID	if (!((FPU_st0_tag == TW_Empty) || (st1_tag == TW_Empty))) {		EXCEPTION(EX_INTERNAL | 0x115);		return;	}#endif	/* At least one of st(0), st(1) must be empty */	stack_underflow();}/*---------------------------------------------------------------------------*/static FUNC trig_table_a[] = {	f2xm1, fyl2x, fptan, fpatan, fxtract, fprem1, fdecstp, fincstp};voidtrig_a(void){	(trig_table_a[FPU_rm]) ();}static FUNC trig_table_b[] ={	fprem, fyl2xp1, fsqrt_, fsincos, frndint_, emu_fscale, fsin, fcos};voidtrig_b(void){	(trig_table_b[FPU_rm]) ();}

⌨️ 快捷键说明

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