static void fyl2xp1()

in math-emu/fpu_trig.c [1317:1484]


static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag)
{
	u_char sign, sign1;
	FPU_REG *st1_ptr = &st(1), a, b;
	u_char st1_tag = FPU_gettagi(1);

	clear_C1();
	if (!((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid))) {
	      valid_yl2xp1:

		sign = getsign(st0_ptr);
		sign1 = getsign(st1_ptr);

		FPU_to_exp16(st0_ptr, &a);
		FPU_to_exp16(st1_ptr, &b);

		if (poly_l2p1(sign, sign1, &a, &b, st1_ptr))
			return;

		FPU_pop();
		return;
	}

	if (st0_tag == TAG_Special)
		st0_tag = FPU_Special(st0_ptr);
	if (st1_tag == TAG_Special)
		st1_tag = FPU_Special(st1_ptr);

	if (((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
	    || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
	    || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal))) {
		if (denormal_operand() < 0)
			return;

		goto valid_yl2xp1;
	} else if ((st0_tag == TAG_Empty) | (st1_tag == TAG_Empty)) {
		FPU_stack_underflow_pop(1);
		return;
	} else if (st0_tag == TAG_Zero) {
		switch (st1_tag) {
		case TW_Denormal:
			if (denormal_operand() < 0)
				return;
			fallthrough;
		case TAG_Zero:
		case TAG_Valid:
			setsign(st0_ptr, getsign(st0_ptr) ^ getsign(st1_ptr));
			FPU_copy_to_reg1(st0_ptr, st0_tag);
			break;

		case TW_Infinity:
			/* Infinity*log(1) */
			if (arith_invalid(1) < 0)
				return;
			break;

		case TW_NaN:
			if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0)
				return;
			break;

		default:
#ifdef PARANOID
			EXCEPTION(EX_INTERNAL | 0x116);
			return;
#endif /* PARANOID */
			break;
		}
	} else if ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal)) {
		switch (st1_tag) {
		case TAG_Zero:
			if (signnegative(st0_ptr)) {
				if (exponent(st0_ptr) >= 0) {
					/* st(0) holds <= -1.0 */
#ifdef PECULIAR_486		/* Stupid 80486 doesn't worry about log(negative). */
					changesign(st1_ptr);
#else
					if (arith_invalid(1) < 0)
						return;
#endif /* PECULIAR_486 */
				} else if ((st0_tag == TW_Denormal)
					   && (denormal_operand() < 0))
					return;
				else
					changesign(st1_ptr);
			} else if ((st0_tag == TW_Denormal)
				   && (denormal_operand() < 0))
				return;
			break;

		case TW_Infinity:
			if (signnegative(st0_ptr)) {
				if ((exponent(st0_ptr) >= 0) &&
				    !((st0_ptr->sigh == 0x80000000) &&
				      (st0_ptr->sigl == 0))) {
					/* st(0) holds < -1.0 */
#ifdef PECULIAR_486		/* Stupid 80486 doesn't worry about log(negative). */
					changesign(st1_ptr);
#else
					if (arith_invalid(1) < 0)
						return;
#endif /* PECULIAR_486 */
				} else if ((st0_tag == TW_Denormal)
					   && (denormal_operand() < 0))
					return;
				else
					changesign(st1_ptr);
			} else if ((st0_tag == TW_Denormal)
				   && (denormal_operand() < 0))
				return;
			break;

		case TW_NaN:
			if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0)
				return;
		}

	} else if (st0_tag == TW_NaN) {
		if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0)
			return;
	} else if (st0_tag == TW_Infinity) {
		if (st1_tag == TW_NaN) {
			if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0)
				return;
		} else if (signnegative(st0_ptr)) {
#ifndef PECULIAR_486
			/* This should have higher priority than denormals, but... */
			if (arith_invalid(1) < 0)	/* log(-infinity) */
				return;
#endif /* PECULIAR_486 */
			if ((st1_tag == TW_Denormal)
			    && (denormal_operand() < 0))
				return;
#ifdef PECULIAR_486
			/* Denormal operands actually get higher priority */
			if (arith_invalid(1) < 0)	/* log(-infinity) */
				return;
#endif /* PECULIAR_486 */
		} else if (st1_tag == TAG_Zero) {
			/* log(infinity) */
			if (arith_invalid(1) < 0)
				return;
		}

		/* st(1) must be valid here. */

		else if ((st1_tag == TW_Denormal) && (denormal_operand() < 0))
			return;

		/* The Manual says that log(Infinity) is invalid, but a real
		   80486 sensibly says that it is o.k. */
		else {
			u_char sign = getsign(st1_ptr);
			FPU_copy_to_reg1(&CONST_INF, TAG_Special);
			setsign(st1_ptr, sign);
		}
	}
#ifdef PARANOID
	else {
		EXCEPTION(EX_INTERNAL | 0x117);
		return;
	}
#endif /* PARANOID */

	FPU_pop();
	return;

}