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;
}