0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include "fpu_system.h"
0015 #include "exception.h"
0016 #include "fpu_emu.h"
0017 #include "status_w.h"
0018 #include "control_w.h"
0019 #include "reg_constant.h"
0020
0021 static void rem_kernel(unsigned long long st0, unsigned long long *y,
0022 unsigned long long st1, unsigned long long q, int n);
0023
0024 #define BETTER_THAN_486
0025
0026 #define FCOS 4
0027
0028
0029
0030
0031
0032
0033
0034 static int trig_arg(FPU_REG *st0_ptr, int even)
0035 {
0036 FPU_REG tmp;
0037 u_char tmptag;
0038 unsigned long long q;
0039 int old_cw = control_word, saved_status = partial_status;
0040 int tag, st0_tag = TAG_Valid;
0041
0042 if (exponent(st0_ptr) >= 63) {
0043 partial_status |= SW_C2;
0044 return -1;
0045 }
0046
0047 control_word &= ~CW_RC;
0048 control_word |= RC_CHOP;
0049
0050 setpositive(st0_ptr);
0051 tag = FPU_u_div(st0_ptr, &CONST_PI2, &tmp, PR_64_BITS | RC_CHOP | 0x3f,
0052 SIGN_POS);
0053
0054 FPU_round_to_int(&tmp, tag);
0055
0056 q = significand(&tmp);
0057 if (q) {
0058 rem_kernel(significand(st0_ptr),
0059 &significand(&tmp),
0060 significand(&CONST_PI2),
0061 q, exponent(st0_ptr) - exponent(&CONST_PI2));
0062 setexponent16(&tmp, exponent(&CONST_PI2));
0063 st0_tag = FPU_normalize(&tmp);
0064 FPU_copy_to_reg0(&tmp, st0_tag);
0065 }
0066
0067 if ((even && !(q & 1)) || (!even && (q & 1))) {
0068 st0_tag =
0069 FPU_sub(REV | LOADED | TAG_Valid, (int)&CONST_PI2,
0070 FULL_PRECISION);
0071
0072 #ifdef BETTER_THAN_486
0073
0074
0075
0076
0077 if ((exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64)
0078 || (q > 1)) {
0079
0080
0081
0082 significand(&tmp) = q + 1;
0083 setexponent16(&tmp, 63);
0084 FPU_normalize(&tmp);
0085 tmptag =
0086 FPU_u_mul(&CONST_PI2extra, &tmp, &tmp,
0087 FULL_PRECISION, SIGN_POS,
0088 exponent(&CONST_PI2extra) +
0089 exponent(&tmp));
0090 setsign(&tmp, getsign(&CONST_PI2extra));
0091 st0_tag = FPU_add(&tmp, tmptag, 0, FULL_PRECISION);
0092 if (signnegative(st0_ptr)) {
0093
0094
0095
0096
0097 setpositive(st0_ptr);
0098 q++;
0099 }
0100 }
0101 #endif
0102 }
0103 #ifdef BETTER_THAN_486
0104 else {
0105
0106
0107
0108
0109 if (((q > 0)
0110 && (exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64))
0111 || (q > 1)) {
0112
0113
0114
0115 significand(&tmp) = q;
0116 setexponent16(&tmp, 63);
0117 FPU_normalize(&tmp);
0118 tmptag =
0119 FPU_u_mul(&CONST_PI2extra, &tmp, &tmp,
0120 FULL_PRECISION, SIGN_POS,
0121 exponent(&CONST_PI2extra) +
0122 exponent(&tmp));
0123 setsign(&tmp, getsign(&CONST_PI2extra));
0124 st0_tag = FPU_sub(LOADED | (tmptag & 0x0f), (int)&tmp,
0125 FULL_PRECISION);
0126 if ((exponent(st0_ptr) == exponent(&CONST_PI2)) &&
0127 ((st0_ptr->sigh > CONST_PI2.sigh)
0128 || ((st0_ptr->sigh == CONST_PI2.sigh)
0129 && (st0_ptr->sigl > CONST_PI2.sigl)))) {
0130
0131
0132
0133
0134
0135 st0_tag =
0136 FPU_sub(REV | LOADED | TAG_Valid,
0137 (int)&CONST_PI2, FULL_PRECISION);
0138 q++;
0139 }
0140 }
0141 }
0142 #endif
0143
0144 FPU_settag0(st0_tag);
0145 control_word = old_cw;
0146 partial_status = saved_status & ~SW_C2;
0147
0148 return (q & 3) | even;
0149 }
0150
0151
0152 static void convert_l2reg(long const *arg, int deststnr)
0153 {
0154 int tag;
0155 long num = *arg;
0156 u_char sign;
0157 FPU_REG *dest = &st(deststnr);
0158
0159 if (num == 0) {
0160 FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
0161 return;
0162 }
0163
0164 if (num > 0) {
0165 sign = SIGN_POS;
0166 } else {
0167 num = -num;
0168 sign = SIGN_NEG;
0169 }
0170
0171 dest->sigh = num;
0172 dest->sigl = 0;
0173 setexponent16(dest, 31);
0174 tag = FPU_normalize(dest);
0175 FPU_settagi(deststnr, tag);
0176 setsign(dest, sign);
0177 return;
0178 }
0179
0180 static void single_arg_error(FPU_REG *st0_ptr, u_char st0_tag)
0181 {
0182 if (st0_tag == TAG_Empty)
0183 FPU_stack_underflow();
0184 else if (st0_tag == TW_NaN)
0185 real_1op_NaN(st0_ptr);
0186 #ifdef PARANOID
0187 else
0188 EXCEPTION(EX_INTERNAL | 0x0112);
0189 #endif
0190 }
0191
0192 static void single_arg_2_error(FPU_REG *st0_ptr, u_char st0_tag)
0193 {
0194 int isNaN;
0195
0196 switch (st0_tag) {
0197 case TW_NaN:
0198 isNaN = (exponent(st0_ptr) == EXP_OVER)
0199 && (st0_ptr->sigh & 0x80000000);
0200 if (isNaN && !(st0_ptr->sigh & 0x40000000)) {
0201 EXCEPTION(EX_Invalid);
0202 if (control_word & CW_Invalid) {
0203
0204
0205 st0_ptr->sigh |= 0x40000000;
0206 push();
0207 FPU_copy_to_reg0(st0_ptr, TAG_Special);
0208 }
0209 } else if (isNaN) {
0210
0211 push();
0212 FPU_copy_to_reg0(st0_ptr, TAG_Special);
0213 } else {
0214
0215 EXCEPTION(EX_Invalid);
0216 if (control_word & CW_Invalid) {
0217
0218 FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
0219 push();
0220 FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
0221 }
0222 }
0223 break;
0224 #ifdef PARANOID
0225 default:
0226 EXCEPTION(EX_INTERNAL | 0x0112);
0227 #endif
0228 }
0229 }
0230
0231
0232
0233 static void f2xm1(FPU_REG *st0_ptr, u_char tag)
0234 {
0235 FPU_REG a;
0236
0237 clear_C1();
0238
0239 if (tag == TAG_Valid) {
0240
0241 if (exponent(st0_ptr) < 0) {
0242 denormal_arg:
0243
0244 FPU_to_exp16(st0_ptr, &a);
0245
0246
0247 poly_2xm1(getsign(st0_ptr), &a, st0_ptr);
0248 }
0249 set_precision_flag_up();
0250 return;
0251 }
0252
0253 if (tag == TAG_Zero)
0254 return;
0255
0256 if (tag == TAG_Special)
0257 tag = FPU_Special(st0_ptr);
0258
0259 switch (tag) {
0260 case TW_Denormal:
0261 if (denormal_operand() < 0)
0262 return;
0263 goto denormal_arg;
0264 case TW_Infinity:
0265 if (signnegative(st0_ptr)) {
0266
0267 FPU_copy_to_reg0(&CONST_1, TAG_Valid);
0268 setnegative(st0_ptr);
0269 }
0270 return;
0271 default:
0272 single_arg_error(st0_ptr, tag);
0273 }
0274 }
0275
0276 static void fptan(FPU_REG *st0_ptr, u_char st0_tag)
0277 {
0278 FPU_REG *st_new_ptr;
0279 int q;
0280 u_char arg_sign = getsign(st0_ptr);
0281
0282
0283 if (st0_tag == TAG_Empty) {
0284 FPU_stack_underflow();
0285 if (control_word & CW_Invalid) {
0286 st_new_ptr = &st(-1);
0287 push();
0288 FPU_stack_underflow();
0289 }
0290 return;
0291 }
0292
0293 if (STACK_OVERFLOW) {
0294 FPU_stack_overflow();
0295 return;
0296 }
0297
0298 if (st0_tag == TAG_Valid) {
0299 if (exponent(st0_ptr) > -40) {
0300 if ((q = trig_arg(st0_ptr, 0)) == -1) {
0301
0302 return;
0303 }
0304
0305 poly_tan(st0_ptr);
0306 setsign(st0_ptr, (q & 1) ^ (arg_sign != 0));
0307 set_precision_flag_up();
0308 } else {
0309
0310
0311
0312 denormal_arg:
0313
0314 FPU_to_exp16(st0_ptr, st0_ptr);
0315
0316 st0_tag =
0317 FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign);
0318 FPU_settag0(st0_tag);
0319 }
0320 push();
0321 FPU_copy_to_reg0(&CONST_1, TAG_Valid);
0322 return;
0323 }
0324
0325 if (st0_tag == TAG_Zero) {
0326 push();
0327 FPU_copy_to_reg0(&CONST_1, TAG_Valid);
0328 setcc(0);
0329 return;
0330 }
0331
0332 if (st0_tag == TAG_Special)
0333 st0_tag = FPU_Special(st0_ptr);
0334
0335 if (st0_tag == TW_Denormal) {
0336 if (denormal_operand() < 0)
0337 return;
0338
0339 goto denormal_arg;
0340 }
0341
0342 if (st0_tag == TW_Infinity) {
0343
0344 if (arith_invalid(0) >= 0) {
0345 st_new_ptr = &st(-1);
0346 push();
0347 arith_invalid(0);
0348 }
0349 return;
0350 }
0351
0352 single_arg_2_error(st0_ptr, st0_tag);
0353 }
0354
0355 static void fxtract(FPU_REG *st0_ptr, u_char st0_tag)
0356 {
0357 FPU_REG *st_new_ptr;
0358 u_char sign;
0359 register FPU_REG *st1_ptr = st0_ptr;
0360
0361 if (STACK_OVERFLOW) {
0362 FPU_stack_overflow();
0363 return;
0364 }
0365
0366 clear_C1();
0367
0368 if (st0_tag == TAG_Valid) {
0369 long e;
0370
0371 push();
0372 sign = getsign(st1_ptr);
0373 reg_copy(st1_ptr, st_new_ptr);
0374 setexponent16(st_new_ptr, exponent(st_new_ptr));
0375
0376 denormal_arg:
0377
0378 e = exponent16(st_new_ptr);
0379 convert_l2reg(&e, 1);
0380 setexponentpos(st_new_ptr, 0);
0381 setsign(st_new_ptr, sign);
0382 FPU_settag0(TAG_Valid);
0383 return;
0384 } else if (st0_tag == TAG_Zero) {
0385 sign = getsign(st0_ptr);
0386
0387 if (FPU_divide_by_zero(0, SIGN_NEG) < 0)
0388 return;
0389
0390 push();
0391 FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
0392 setsign(st_new_ptr, sign);
0393 return;
0394 }
0395
0396 if (st0_tag == TAG_Special)
0397 st0_tag = FPU_Special(st0_ptr);
0398
0399 if (st0_tag == TW_Denormal) {
0400 if (denormal_operand() < 0)
0401 return;
0402
0403 push();
0404 sign = getsign(st1_ptr);
0405 FPU_to_exp16(st1_ptr, st_new_ptr);
0406 goto denormal_arg;
0407 } else if (st0_tag == TW_Infinity) {
0408 sign = getsign(st0_ptr);
0409 setpositive(st0_ptr);
0410 push();
0411 FPU_copy_to_reg0(&CONST_INF, TAG_Special);
0412 setsign(st_new_ptr, sign);
0413 return;
0414 } else if (st0_tag == TW_NaN) {
0415 if (real_1op_NaN(st0_ptr) < 0)
0416 return;
0417
0418 push();
0419 FPU_copy_to_reg0(st0_ptr, TAG_Special);
0420 return;
0421 } else if (st0_tag == TAG_Empty) {
0422
0423 if (control_word & EX_Invalid) {
0424 FPU_stack_underflow();
0425 push();
0426 FPU_stack_underflow();
0427 } else
0428 EXCEPTION(EX_StackUnder);
0429 }
0430 #ifdef PARANOID
0431 else
0432 EXCEPTION(EX_INTERNAL | 0x119);
0433 #endif
0434 }
0435
0436 static void fdecstp(void)
0437 {
0438 clear_C1();
0439 top--;
0440 }
0441
0442 static void fincstp(void)
0443 {
0444 clear_C1();
0445 top++;
0446 }
0447
0448 static void fsqrt_(FPU_REG *st0_ptr, u_char st0_tag)
0449 {
0450 int expon;
0451
0452 clear_C1();
0453
0454 if (st0_tag == TAG_Valid) {
0455 u_char tag;
0456
0457 if (signnegative(st0_ptr)) {
0458 arith_invalid(0);
0459 return;
0460 }
0461
0462
0463 expon = exponent(st0_ptr);
0464
0465 denormal_arg:
0466
0467 setexponent16(st0_ptr, (expon & 1));
0468
0469
0470 tag = wm_sqrt(st0_ptr, 0, 0, control_word, SIGN_POS);
0471 addexponent(st0_ptr, expon >> 1);
0472 FPU_settag0(tag);
0473 return;
0474 }
0475
0476 if (st0_tag == TAG_Zero)
0477 return;
0478
0479 if (st0_tag == TAG_Special)
0480 st0_tag = FPU_Special(st0_ptr);
0481
0482 if (st0_tag == TW_Infinity) {
0483 if (signnegative(st0_ptr))
0484 arith_invalid(0);
0485 return;
0486 } else if (st0_tag == TW_Denormal) {
0487 if (signnegative(st0_ptr)) {
0488 arith_invalid(0);
0489 return;
0490 }
0491
0492 if (denormal_operand() < 0)
0493 return;
0494
0495 FPU_to_exp16(st0_ptr, st0_ptr);
0496
0497 expon = exponent16(st0_ptr);
0498
0499 goto denormal_arg;
0500 }
0501
0502 single_arg_error(st0_ptr, st0_tag);
0503
0504 }
0505
0506 static void frndint_(FPU_REG *st0_ptr, u_char st0_tag)
0507 {
0508 int flags, tag;
0509
0510 if (st0_tag == TAG_Valid) {
0511 u_char sign;
0512
0513 denormal_arg:
0514
0515 sign = getsign(st0_ptr);
0516
0517 if (exponent(st0_ptr) > 63)
0518 return;
0519
0520 if (st0_tag == TW_Denormal) {
0521 if (denormal_operand() < 0)
0522 return;
0523 }
0524
0525
0526 if ((flags = FPU_round_to_int(st0_ptr, st0_tag)))
0527 set_precision_flag(flags);
0528
0529 setexponent16(st0_ptr, 63);
0530 tag = FPU_normalize(st0_ptr);
0531 setsign(st0_ptr, sign);
0532 FPU_settag0(tag);
0533 return;
0534 }
0535
0536 if (st0_tag == TAG_Zero)
0537 return;
0538
0539 if (st0_tag == TAG_Special)
0540 st0_tag = FPU_Special(st0_ptr);
0541
0542 if (st0_tag == TW_Denormal)
0543 goto denormal_arg;
0544 else if (st0_tag == TW_Infinity)
0545 return;
0546 else
0547 single_arg_error(st0_ptr, st0_tag);
0548 }
0549
0550 static int f_sin(FPU_REG *st0_ptr, u_char tag)
0551 {
0552 u_char arg_sign = getsign(st0_ptr);
0553
0554 if (tag == TAG_Valid) {
0555 int q;
0556
0557 if (exponent(st0_ptr) > -40) {
0558 if ((q = trig_arg(st0_ptr, 0)) == -1) {
0559
0560 return 1;
0561 }
0562
0563 poly_sine(st0_ptr);
0564
0565 if (q & 2)
0566 changesign(st0_ptr);
0567
0568 setsign(st0_ptr, getsign(st0_ptr) ^ arg_sign);
0569
0570
0571 set_precision_flag_up();
0572 return 0;
0573 } else {
0574
0575 set_precision_flag_up();
0576 return 0;
0577 }
0578 }
0579
0580 if (tag == TAG_Zero) {
0581 setcc(0);
0582 return 0;
0583 }
0584
0585 if (tag == TAG_Special)
0586 tag = FPU_Special(st0_ptr);
0587
0588 if (tag == TW_Denormal) {
0589 if (denormal_operand() < 0)
0590 return 1;
0591
0592
0593
0594 FPU_to_exp16(st0_ptr, st0_ptr);
0595
0596 tag = FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign);
0597
0598 FPU_settag0(tag);
0599
0600 return 0;
0601 } else if (tag == TW_Infinity) {
0602
0603 arith_invalid(0);
0604 return 1;
0605 } else {
0606 single_arg_error(st0_ptr, tag);
0607 return 1;
0608 }
0609 }
0610
0611 static void fsin(FPU_REG *st0_ptr, u_char tag)
0612 {
0613 f_sin(st0_ptr, tag);
0614 }
0615
0616 static int f_cos(FPU_REG *st0_ptr, u_char tag)
0617 {
0618 u_char st0_sign;
0619
0620 st0_sign = getsign(st0_ptr);
0621
0622 if (tag == TAG_Valid) {
0623 int q;
0624
0625 if (exponent(st0_ptr) > -40) {
0626 if ((exponent(st0_ptr) < 0)
0627 || ((exponent(st0_ptr) == 0)
0628 && (significand(st0_ptr) <=
0629 0xc90fdaa22168c234LL))) {
0630 poly_cos(st0_ptr);
0631
0632
0633 set_precision_flag_down();
0634
0635 return 0;
0636 } else if ((q = trig_arg(st0_ptr, FCOS)) != -1) {
0637 poly_sine(st0_ptr);
0638
0639 if ((q + 1) & 2)
0640 changesign(st0_ptr);
0641
0642
0643 set_precision_flag_down();
0644
0645 return 0;
0646 } else {
0647
0648 return 1;
0649 }
0650 } else {
0651 denormal_arg:
0652
0653 setcc(0);
0654 FPU_copy_to_reg0(&CONST_1, TAG_Valid);
0655 #ifdef PECULIAR_486
0656 set_precision_flag_down();
0657 #else
0658 set_precision_flag_up();
0659 #endif
0660 return 0;
0661 }
0662 } else if (tag == TAG_Zero) {
0663 FPU_copy_to_reg0(&CONST_1, TAG_Valid);
0664 setcc(0);
0665 return 0;
0666 }
0667
0668 if (tag == TAG_Special)
0669 tag = FPU_Special(st0_ptr);
0670
0671 if (tag == TW_Denormal) {
0672 if (denormal_operand() < 0)
0673 return 1;
0674
0675 goto denormal_arg;
0676 } else if (tag == TW_Infinity) {
0677
0678 arith_invalid(0);
0679 return 1;
0680 } else {
0681 single_arg_error(st0_ptr, tag);
0682 return 1;
0683 }
0684 }
0685
0686 static void fcos(FPU_REG *st0_ptr, u_char st0_tag)
0687 {
0688 f_cos(st0_ptr, st0_tag);
0689 }
0690
0691 static void fsincos(FPU_REG *st0_ptr, u_char st0_tag)
0692 {
0693 FPU_REG *st_new_ptr;
0694 FPU_REG arg;
0695 u_char tag;
0696
0697
0698 if (st0_tag == TAG_Empty) {
0699 FPU_stack_underflow();
0700 if (control_word & CW_Invalid) {
0701 st_new_ptr = &st(-1);
0702 push();
0703 FPU_stack_underflow();
0704 }
0705 return;
0706 }
0707
0708 if (STACK_OVERFLOW) {
0709 FPU_stack_overflow();
0710 return;
0711 }
0712
0713 if (st0_tag == TAG_Special)
0714 tag = FPU_Special(st0_ptr);
0715 else
0716 tag = st0_tag;
0717
0718 if (tag == TW_NaN) {
0719 single_arg_2_error(st0_ptr, TW_NaN);
0720 return;
0721 } else if (tag == TW_Infinity) {
0722
0723 if (arith_invalid(0) >= 0) {
0724
0725 push();
0726 arith_invalid(0);
0727 }
0728 return;
0729 }
0730
0731 reg_copy(st0_ptr, &arg);
0732 if (!f_sin(st0_ptr, st0_tag)) {
0733 push();
0734 FPU_copy_to_reg0(&arg, st0_tag);
0735 f_cos(&st(0), st0_tag);
0736 } else {
0737
0738 FPU_copy_to_reg0(&arg, st0_tag);
0739 }
0740 }
0741
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751 static void rem_kernel(unsigned long long st0, unsigned long long *y,
0752 unsigned long long st1, unsigned long long q, int n)
0753 {
0754 int dummy;
0755 unsigned long long x;
0756
0757 x = st0 << n;
0758
0759
0760
0761
0762 asm volatile ("mull %4; subl %%eax,%0; sbbl %%edx,%1":"=m"
0763 (((unsigned *)&x)[0]), "=m"(((unsigned *)&x)[1]),
0764 "=a"(dummy)
0765 :"2"(((unsigned *)&st1)[0]), "m"(((unsigned *)&q)[0])
0766 :"%dx");
0767
0768 asm volatile ("mull %3; subl %%eax,%0":"=m" (((unsigned *)&x)[1]),
0769 "=a"(dummy)
0770 :"1"(((unsigned *)&st1)[1]), "m"(((unsigned *)&q)[0])
0771 :"%dx");
0772
0773 asm volatile ("mull %3; subl %%eax,%0":"=m" (((unsigned *)&x)[1]),
0774 "=a"(dummy)
0775 :"1"(((unsigned *)&st1)[0]), "m"(((unsigned *)&q)[1])
0776 :"%dx");
0777
0778 *y = x;
0779 }
0780
0781
0782
0783
0784 static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round)
0785 {
0786 FPU_REG *st1_ptr = &st(1);
0787 u_char st1_tag = FPU_gettagi(1);
0788
0789 if (!((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid))) {
0790 FPU_REG tmp, st0, st1;
0791 u_char st0_sign, st1_sign;
0792 u_char tmptag;
0793 int tag;
0794 int old_cw;
0795 int expdif;
0796 long long q;
0797 unsigned short saved_status;
0798 int cc;
0799
0800 fprem_valid:
0801
0802 st0_sign = FPU_to_exp16(st0_ptr, &st0);
0803 st1_sign = FPU_to_exp16(st1_ptr, &st1);
0804 expdif = exponent16(&st0) - exponent16(&st1);
0805
0806 old_cw = control_word;
0807 cc = 0;
0808
0809
0810
0811 saved_status = partial_status;
0812 control_word &= ~CW_RC;
0813 control_word |= RC_CHOP;
0814
0815 if (expdif < 64) {
0816
0817
0818 if (expdif > -2) {
0819 u_char sign = st0_sign ^ st1_sign;
0820 tag = FPU_u_div(&st0, &st1, &tmp,
0821 PR_64_BITS | RC_CHOP | 0x3f,
0822 sign);
0823 setsign(&tmp, sign);
0824
0825 if (exponent(&tmp) >= 0) {
0826 FPU_round_to_int(&tmp, tag);
0827
0828 q = significand(&tmp);
0829
0830 rem_kernel(significand(&st0),
0831 &significand(&tmp),
0832 significand(&st1),
0833 q, expdif);
0834
0835 setexponent16(&tmp, exponent16(&st1));
0836 } else {
0837 reg_copy(&st0, &tmp);
0838 q = 0;
0839 }
0840
0841 if ((round == RC_RND)
0842 && (tmp.sigh & 0xc0000000)) {
0843
0844
0845 unsigned long long x;
0846 expdif =
0847 exponent16(&st1) - exponent16(&tmp);
0848 if (expdif <= 1) {
0849 if (expdif == 0)
0850 x = significand(&st1) -
0851 significand(&tmp);
0852 else
0853 x = (significand(&st1)
0854 << 1) -
0855 significand(&tmp);
0856 if ((x < significand(&tmp)) ||
0857
0858 ((x == significand(&tmp))
0859 && (q & 1))) {
0860 st0_sign = !st0_sign;
0861 significand(&tmp) = x;
0862 q++;
0863 }
0864 }
0865 }
0866
0867 if (q & 4)
0868 cc |= SW_C0;
0869 if (q & 2)
0870 cc |= SW_C3;
0871 if (q & 1)
0872 cc |= SW_C1;
0873 } else {
0874 control_word = old_cw;
0875 setcc(0);
0876 return;
0877 }
0878 } else {
0879
0880
0881
0882 int exp_1, N;
0883 u_char sign;
0884
0885
0886
0887 reg_copy(&st0, &tmp);
0888 tmptag = st0_tag;
0889 N = (expdif & 0x0000001f) + 32;
0890
0891 setexponent16(&tmp, N);
0892 exp_1 = exponent16(&st1);
0893 setexponent16(&st1, 0);
0894 expdif -= N;
0895
0896 sign = getsign(&tmp) ^ st1_sign;
0897 tag =
0898 FPU_u_div(&tmp, &st1, &tmp,
0899 PR_64_BITS | RC_CHOP | 0x3f, sign);
0900 setsign(&tmp, sign);
0901
0902 FPU_round_to_int(&tmp, tag);
0903
0904
0905 rem_kernel(significand(&st0),
0906 &significand(&tmp),
0907 significand(&st1),
0908 significand(&tmp), exponent(&tmp)
0909 );
0910 setexponent16(&tmp, exp_1 + expdif);
0911
0912
0913
0914
0915
0916
0917 if (!(tmp.sigh | tmp.sigl)) {
0918
0919 control_word = old_cw;
0920 partial_status = saved_status;
0921 FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
0922 setsign(&st0, st0_sign);
0923 #ifdef PECULIAR_486
0924 setcc(SW_C2);
0925 #else
0926 setcc(0);
0927 #endif
0928 return;
0929 }
0930 cc = SW_C2;
0931 }
0932
0933 control_word = old_cw;
0934 partial_status = saved_status;
0935 tag = FPU_normalize_nuo(&tmp);
0936 reg_copy(&tmp, st0_ptr);
0937
0938
0939
0940 if ((exponent16(&tmp) <= EXP_UNDER) && (tag != TAG_Zero)
0941 && !(control_word & CW_Underflow)) {
0942 setcc(cc);
0943 tag = arith_underflow(st0_ptr);
0944 setsign(st0_ptr, st0_sign);
0945 FPU_settag0(tag);
0946 return;
0947 } else if ((exponent16(&tmp) > EXP_UNDER) || (tag == TAG_Zero)) {
0948 stdexp(st0_ptr);
0949 setsign(st0_ptr, st0_sign);
0950 } else {
0951 tag =
0952 FPU_round(st0_ptr, 0, 0, FULL_PRECISION, st0_sign);
0953 }
0954 FPU_settag0(tag);
0955 setcc(cc);
0956
0957 return;
0958 }
0959
0960 if (st0_tag == TAG_Special)
0961 st0_tag = FPU_Special(st0_ptr);
0962 if (st1_tag == TAG_Special)
0963 st1_tag = FPU_Special(st1_ptr);
0964
0965 if (((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
0966 || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
0967 || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal))) {
0968 if (denormal_operand() < 0)
0969 return;
0970 goto fprem_valid;
0971 } else if ((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) {
0972 FPU_stack_underflow();
0973 return;
0974 } else if (st0_tag == TAG_Zero) {
0975 if (st1_tag == TAG_Valid) {
0976 setcc(0);
0977 return;
0978 } else if (st1_tag == TW_Denormal) {
0979 if (denormal_operand() < 0)
0980 return;
0981 setcc(0);
0982 return;
0983 } else if (st1_tag == TAG_Zero) {
0984 arith_invalid(0);
0985 return;
0986 }
0987 else if (st1_tag == TW_Infinity) {
0988 setcc(0);
0989 return;
0990 }
0991 } else if ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal)) {
0992 if (st1_tag == TAG_Zero) {
0993 arith_invalid(0);
0994 return;
0995 } else if (st1_tag != TW_NaN) {
0996 if (((st0_tag == TW_Denormal)
0997 || (st1_tag == TW_Denormal))
0998 && (denormal_operand() < 0))
0999 return;
1000
1001 if (st1_tag == TW_Infinity) {
1002
1003 setcc(0);
1004 return;
1005 }
1006 }
1007 } else if (st0_tag == TW_Infinity) {
1008 if (st1_tag != TW_NaN) {
1009 arith_invalid(0);
1010 return;
1011 }
1012 }
1013
1014
1015
1016 #ifdef PARANOID
1017 if ((st0_tag != TW_NaN) && (st1_tag != TW_NaN))
1018 EXCEPTION(EX_INTERNAL | 0x118);
1019 #endif
1020
1021 real_2op_NaN(st1_ptr, st1_tag, 0, st1_ptr);
1022
1023 }
1024
1025
1026 static void fyl2x(FPU_REG *st0_ptr, u_char st0_tag)
1027 {
1028 FPU_REG *st1_ptr = &st(1), exponent;
1029 u_char st1_tag = FPU_gettagi(1);
1030 u_char sign;
1031 int e, tag;
1032
1033 clear_C1();
1034
1035 if ((st0_tag == TAG_Valid) && (st1_tag == TAG_Valid)) {
1036 both_valid:
1037
1038 if (signpositive(st0_ptr)) {
1039 if (st0_tag == TW_Denormal)
1040 FPU_to_exp16(st0_ptr, st0_ptr);
1041 else
1042
1043 setexponent16(st0_ptr, exponent(st0_ptr));
1044
1045 if ((st0_ptr->sigh == 0x80000000)
1046 && (st0_ptr->sigl == 0)) {
1047
1048 u_char esign;
1049 e = exponent16(st0_ptr);
1050 if (e >= 0) {
1051 exponent.sigh = e;
1052 esign = SIGN_POS;
1053 } else {
1054 exponent.sigh = -e;
1055 esign = SIGN_NEG;
1056 }
1057 exponent.sigl = 0;
1058 setexponent16(&exponent, 31);
1059 tag = FPU_normalize_nuo(&exponent);
1060 stdexp(&exponent);
1061 setsign(&exponent, esign);
1062 tag =
1063 FPU_mul(&exponent, tag, 1, FULL_PRECISION);
1064 if (tag >= 0)
1065 FPU_settagi(1, tag);
1066 } else {
1067
1068 sign = getsign(st1_ptr);
1069 if (st1_tag == TW_Denormal)
1070 FPU_to_exp16(st1_ptr, st1_ptr);
1071 else
1072
1073 setexponent16(st1_ptr,
1074 exponent(st1_ptr));
1075 poly_l2(st0_ptr, st1_ptr, sign);
1076 }
1077 } else {
1078
1079 if (arith_invalid(1) < 0)
1080 return;
1081 }
1082
1083 FPU_pop();
1084
1085 return;
1086 }
1087
1088 if (st0_tag == TAG_Special)
1089 st0_tag = FPU_Special(st0_ptr);
1090 if (st1_tag == TAG_Special)
1091 st1_tag = FPU_Special(st1_ptr);
1092
1093 if ((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) {
1094 FPU_stack_underflow_pop(1);
1095 return;
1096 } else if ((st0_tag <= TW_Denormal) && (st1_tag <= TW_Denormal)) {
1097 if (st0_tag == TAG_Zero) {
1098 if (st1_tag == TAG_Zero) {
1099
1100 if (arith_invalid(1) < 0)
1101 return;
1102 } else {
1103 u_char sign;
1104 sign = getsign(st1_ptr) ^ SIGN_NEG;
1105 if (FPU_divide_by_zero(1, sign) < 0)
1106 return;
1107
1108 setsign(st1_ptr, sign);
1109 }
1110 } else if (st1_tag == TAG_Zero) {
1111
1112
1113 sign = getsign(st1_ptr);
1114
1115 if (signnegative(st0_ptr)) {
1116
1117 if (arith_invalid(1) < 0)
1118 return;
1119 } else if ((st0_tag == TW_Denormal)
1120 && (denormal_operand() < 0))
1121 return;
1122 else {
1123 if (exponent(st0_ptr) < 0)
1124 sign ^= SIGN_NEG;
1125
1126 FPU_copy_to_reg1(&CONST_Z, TAG_Zero);
1127 setsign(st1_ptr, sign);
1128 }
1129 } else {
1130
1131 if (denormal_operand() < 0)
1132 return;
1133 goto both_valid;
1134 }
1135 } else if ((st0_tag == TW_NaN) || (st1_tag == TW_NaN)) {
1136 if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0)
1137 return;
1138 }
1139
1140 else if (st0_tag == TW_Infinity) {
1141 if ((signnegative(st0_ptr)) || (st1_tag == TAG_Zero)) {
1142
1143 if (arith_invalid(1) < 0)
1144 return;
1145 } else {
1146 u_char sign = getsign(st1_ptr);
1147
1148 if ((st1_tag == TW_Denormal)
1149 && (denormal_operand() < 0))
1150 return;
1151
1152 FPU_copy_to_reg1(&CONST_INF, TAG_Special);
1153 setsign(st1_ptr, sign);
1154 }
1155 }
1156
1157 else if (((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal))
1158 && (signpositive(st0_ptr))) {
1159 if (exponent(st0_ptr) >= 0) {
1160 if ((exponent(st0_ptr) == 0) &&
1161 (st0_ptr->sigh == 0x80000000) &&
1162 (st0_ptr->sigl == 0)) {
1163
1164
1165 if (arith_invalid(1) < 0)
1166 return;
1167 }
1168
1169 } else {
1170
1171
1172 if ((st0_tag == TW_Denormal)
1173 && (denormal_operand() < 0))
1174 return;
1175
1176 changesign(st1_ptr);
1177 }
1178 } else {
1179
1180 if (st0_tag == TAG_Zero) {
1181
1182
1183 #ifndef PECULIAR_486
1184 sign = getsign(st1_ptr);
1185 if (FPU_divide_by_zero(1, sign) < 0)
1186 return;
1187 #endif
1188
1189 changesign(st1_ptr);
1190 } else if (arith_invalid(1) < 0)
1191 return;
1192 }
1193
1194 FPU_pop();
1195 }
1196
1197 static void fpatan(FPU_REG *st0_ptr, u_char st0_tag)
1198 {
1199 FPU_REG *st1_ptr = &st(1);
1200 u_char st1_tag = FPU_gettagi(1);
1201 int tag;
1202
1203 clear_C1();
1204 if (!((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid))) {
1205 valid_atan:
1206
1207 poly_atan(st0_ptr, st0_tag, st1_ptr, st1_tag);
1208
1209 FPU_pop();
1210
1211 return;
1212 }
1213
1214 if (st0_tag == TAG_Special)
1215 st0_tag = FPU_Special(st0_ptr);
1216 if (st1_tag == TAG_Special)
1217 st1_tag = FPU_Special(st1_ptr);
1218
1219 if (((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
1220 || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
1221 || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal))) {
1222 if (denormal_operand() < 0)
1223 return;
1224
1225 goto valid_atan;
1226 } else if ((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) {
1227 FPU_stack_underflow_pop(1);
1228 return;
1229 } else if ((st0_tag == TW_NaN) || (st1_tag == TW_NaN)) {
1230 if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) >= 0)
1231 FPU_pop();
1232 return;
1233 } else if ((st0_tag == TW_Infinity) || (st1_tag == TW_Infinity)) {
1234 u_char sign = getsign(st1_ptr);
1235 if (st0_tag == TW_Infinity) {
1236 if (st1_tag == TW_Infinity) {
1237 if (signpositive(st0_ptr)) {
1238 FPU_copy_to_reg1(&CONST_PI4, TAG_Valid);
1239 } else {
1240 setpositive(st1_ptr);
1241 tag =
1242 FPU_u_add(&CONST_PI4, &CONST_PI2,
1243 st1_ptr, FULL_PRECISION,
1244 SIGN_POS,
1245 exponent(&CONST_PI4),
1246 exponent(&CONST_PI2));
1247 if (tag >= 0)
1248 FPU_settagi(1, tag);
1249 }
1250 } else {
1251 if ((st1_tag == TW_Denormal)
1252 && (denormal_operand() < 0))
1253 return;
1254
1255 if (signpositive(st0_ptr)) {
1256 FPU_copy_to_reg1(&CONST_Z, TAG_Zero);
1257 setsign(st1_ptr, sign);
1258 FPU_pop();
1259 return;
1260 } else {
1261 FPU_copy_to_reg1(&CONST_PI, TAG_Valid);
1262 }
1263 }
1264 } else {
1265
1266 if ((st0_tag == TW_Denormal)
1267 && (denormal_operand() < 0))
1268 return;
1269
1270 FPU_copy_to_reg1(&CONST_PI2, TAG_Valid);
1271 }
1272 setsign(st1_ptr, sign);
1273 } else if (st1_tag == TAG_Zero) {
1274
1275 u_char sign = getsign(st1_ptr);
1276
1277 if ((st0_tag == TW_Denormal) && (denormal_operand() < 0))
1278 return;
1279
1280 if (signpositive(st0_ptr)) {
1281
1282 FPU_pop();
1283 return;
1284 }
1285
1286 FPU_copy_to_reg1(&CONST_PI, TAG_Valid);
1287 setsign(st1_ptr, sign);
1288 } else if (st0_tag == TAG_Zero) {
1289
1290 u_char sign = getsign(st1_ptr);
1291
1292 if ((st1_tag == TW_Denormal) && (denormal_operand() < 0))
1293 return;
1294
1295 FPU_copy_to_reg1(&CONST_PI2, TAG_Valid);
1296 setsign(st1_ptr, sign);
1297 }
1298 #ifdef PARANOID
1299 else
1300 EXCEPTION(EX_INTERNAL | 0x125);
1301 #endif
1302
1303 FPU_pop();
1304 set_precision_flag_up();
1305 }
1306
1307 static void fprem(FPU_REG *st0_ptr, u_char st0_tag)
1308 {
1309 do_fprem(st0_ptr, st0_tag, RC_CHOP);
1310 }
1311
1312 static void fprem1(FPU_REG *st0_ptr, u_char st0_tag)
1313 {
1314 do_fprem(st0_ptr, st0_tag, RC_RND);
1315 }
1316
1317 static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag)
1318 {
1319 u_char sign, sign1;
1320 FPU_REG *st1_ptr = &st(1), a, b;
1321 u_char st1_tag = FPU_gettagi(1);
1322
1323 clear_C1();
1324 if (!((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid))) {
1325 valid_yl2xp1:
1326
1327 sign = getsign(st0_ptr);
1328 sign1 = getsign(st1_ptr);
1329
1330 FPU_to_exp16(st0_ptr, &a);
1331 FPU_to_exp16(st1_ptr, &b);
1332
1333 if (poly_l2p1(sign, sign1, &a, &b, st1_ptr))
1334 return;
1335
1336 FPU_pop();
1337 return;
1338 }
1339
1340 if (st0_tag == TAG_Special)
1341 st0_tag = FPU_Special(st0_ptr);
1342 if (st1_tag == TAG_Special)
1343 st1_tag = FPU_Special(st1_ptr);
1344
1345 if (((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
1346 || ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
1347 || ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal))) {
1348 if (denormal_operand() < 0)
1349 return;
1350
1351 goto valid_yl2xp1;
1352 } else if ((st0_tag == TAG_Empty) | (st1_tag == TAG_Empty)) {
1353 FPU_stack_underflow_pop(1);
1354 return;
1355 } else if (st0_tag == TAG_Zero) {
1356 switch (st1_tag) {
1357 case TW_Denormal:
1358 if (denormal_operand() < 0)
1359 return;
1360 fallthrough;
1361 case TAG_Zero:
1362 case TAG_Valid:
1363 setsign(st0_ptr, getsign(st0_ptr) ^ getsign(st1_ptr));
1364 FPU_copy_to_reg1(st0_ptr, st0_tag);
1365 break;
1366
1367 case TW_Infinity:
1368
1369 if (arith_invalid(1) < 0)
1370 return;
1371 break;
1372
1373 case TW_NaN:
1374 if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0)
1375 return;
1376 break;
1377
1378 default:
1379 #ifdef PARANOID
1380 EXCEPTION(EX_INTERNAL | 0x116);
1381 return;
1382 #endif
1383 break;
1384 }
1385 } else if ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal)) {
1386 switch (st1_tag) {
1387 case TAG_Zero:
1388 if (signnegative(st0_ptr)) {
1389 if (exponent(st0_ptr) >= 0) {
1390
1391 #ifdef PECULIAR_486
1392 changesign(st1_ptr);
1393 #else
1394 if (arith_invalid(1) < 0)
1395 return;
1396 #endif
1397 } else if ((st0_tag == TW_Denormal)
1398 && (denormal_operand() < 0))
1399 return;
1400 else
1401 changesign(st1_ptr);
1402 } else if ((st0_tag == TW_Denormal)
1403 && (denormal_operand() < 0))
1404 return;
1405 break;
1406
1407 case TW_Infinity:
1408 if (signnegative(st0_ptr)) {
1409 if ((exponent(st0_ptr) >= 0) &&
1410 !((st0_ptr->sigh == 0x80000000) &&
1411 (st0_ptr->sigl == 0))) {
1412
1413 #ifdef PECULIAR_486
1414 changesign(st1_ptr);
1415 #else
1416 if (arith_invalid(1) < 0)
1417 return;
1418 #endif
1419 } else if ((st0_tag == TW_Denormal)
1420 && (denormal_operand() < 0))
1421 return;
1422 else
1423 changesign(st1_ptr);
1424 } else if ((st0_tag == TW_Denormal)
1425 && (denormal_operand() < 0))
1426 return;
1427 break;
1428
1429 case TW_NaN:
1430 if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0)
1431 return;
1432 }
1433
1434 } else if (st0_tag == TW_NaN) {
1435 if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0)
1436 return;
1437 } else if (st0_tag == TW_Infinity) {
1438 if (st1_tag == TW_NaN) {
1439 if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0)
1440 return;
1441 } else if (signnegative(st0_ptr)) {
1442 #ifndef PECULIAR_486
1443
1444 if (arith_invalid(1) < 0)
1445 return;
1446 #endif
1447 if ((st1_tag == TW_Denormal)
1448 && (denormal_operand() < 0))
1449 return;
1450 #ifdef PECULIAR_486
1451
1452 if (arith_invalid(1) < 0)
1453 return;
1454 #endif
1455 } else if (st1_tag == TAG_Zero) {
1456
1457 if (arith_invalid(1) < 0)
1458 return;
1459 }
1460
1461
1462
1463 else if ((st1_tag == TW_Denormal) && (denormal_operand() < 0))
1464 return;
1465
1466
1467
1468 else {
1469 u_char sign = getsign(st1_ptr);
1470 FPU_copy_to_reg1(&CONST_INF, TAG_Special);
1471 setsign(st1_ptr, sign);
1472 }
1473 }
1474 #ifdef PARANOID
1475 else {
1476 EXCEPTION(EX_INTERNAL | 0x117);
1477 return;
1478 }
1479 #endif
1480
1481 FPU_pop();
1482 return;
1483
1484 }
1485
1486 static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
1487 {
1488 FPU_REG *st1_ptr = &st(1);
1489 u_char st1_tag = FPU_gettagi(1);
1490 int old_cw = control_word;
1491 u_char sign = getsign(st0_ptr);
1492
1493 clear_C1();
1494 if (!((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid))) {
1495 long scale;
1496 FPU_REG tmp;
1497
1498
1499 setexponent16(st0_ptr, exponent(st0_ptr));
1500
1501 valid_scale:
1502
1503 if (exponent(st1_ptr) > 30) {
1504
1505
1506 if (signpositive(st1_ptr)) {
1507 EXCEPTION(EX_Overflow);
1508 FPU_copy_to_reg0(&CONST_INF, TAG_Special);
1509 } else {
1510 EXCEPTION(EX_Underflow);
1511 FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
1512 }
1513 setsign(st0_ptr, sign);
1514 return;
1515 }
1516
1517 control_word &= ~CW_RC;
1518 control_word |= RC_CHOP;
1519 reg_copy(st1_ptr, &tmp);
1520 FPU_round_to_int(&tmp, st1_tag);
1521 control_word = old_cw;
1522 scale = signnegative(st1_ptr) ? -tmp.sigl : tmp.sigl;
1523 scale += exponent16(st0_ptr);
1524
1525 setexponent16(st0_ptr, scale);
1526
1527
1528 FPU_round(st0_ptr, 0, 0, control_word, sign);
1529
1530 return;
1531 }
1532
1533 if (st0_tag == TAG_Special)
1534 st0_tag = FPU_Special(st0_ptr);
1535 if (st1_tag == TAG_Special)
1536 st1_tag = FPU_Special(st1_ptr);
1537
1538 if ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal)) {
1539 switch (st1_tag) {
1540 case TAG_Valid:
1541
1542 if ((st0_tag == TW_Denormal)
1543 && (denormal_operand() < 0))
1544 return;
1545
1546 FPU_to_exp16(st0_ptr, st0_ptr);
1547 goto valid_scale;
1548
1549 case TAG_Zero:
1550 if (st0_tag == TW_Denormal)
1551 denormal_operand();
1552 return;
1553
1554 case TW_Denormal:
1555 denormal_operand();
1556 return;
1557
1558 case TW_Infinity:
1559 if ((st0_tag == TW_Denormal)
1560 && (denormal_operand() < 0))
1561 return;
1562
1563 if (signpositive(st1_ptr))
1564 FPU_copy_to_reg0(&CONST_INF, TAG_Special);
1565 else
1566 FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
1567 setsign(st0_ptr, sign);
1568 return;
1569
1570 case TW_NaN:
1571 real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
1572 return;
1573 }
1574 } else if (st0_tag == TAG_Zero) {
1575 switch (st1_tag) {
1576 case TAG_Valid:
1577 case TAG_Zero:
1578 return;
1579
1580 case TW_Denormal:
1581 denormal_operand();
1582 return;
1583
1584 case TW_Infinity:
1585 if (signpositive(st1_ptr))
1586 arith_invalid(0);
1587 return;
1588
1589 case TW_NaN:
1590 real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
1591 return;
1592 }
1593 } else if (st0_tag == TW_Infinity) {
1594 switch (st1_tag) {
1595 case TAG_Valid:
1596 case TAG_Zero:
1597 return;
1598
1599 case TW_Denormal:
1600 denormal_operand();
1601 return;
1602
1603 case TW_Infinity:
1604 if (signnegative(st1_ptr))
1605 arith_invalid(0);
1606 return;
1607
1608 case TW_NaN:
1609 real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
1610 return;
1611 }
1612 } else if (st0_tag == TW_NaN) {
1613 if (st1_tag != TAG_Empty) {
1614 real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
1615 return;
1616 }
1617 }
1618 #ifdef PARANOID
1619 if (!((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty))) {
1620 EXCEPTION(EX_INTERNAL | 0x115);
1621 return;
1622 }
1623 #endif
1624
1625
1626 FPU_stack_underflow();
1627
1628 }
1629
1630
1631
1632 static FUNC_ST0 const trig_table_a[] = {
1633 f2xm1, fyl2x, fptan, fpatan,
1634 fxtract, fprem1, (FUNC_ST0) fdecstp, (FUNC_ST0) fincstp
1635 };
1636
1637 void FPU_triga(void)
1638 {
1639 (trig_table_a[FPU_rm]) (&st(0), FPU_gettag0());
1640 }
1641
1642 static FUNC_ST0 const trig_table_b[] = {
1643 fprem, fyl2xp1, fsqrt_, fsincos, frndint_, fscale, fsin, fcos
1644 };
1645
1646 void FPU_trigb(void)
1647 {
1648 (trig_table_b[FPU_rm]) (&st(0), FPU_gettag0());
1649 }