0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include "exception.h"
0015 #include "reg_constant.h"
0016 #include "fpu_emu.h"
0017 #include "fpu_system.h"
0018 #include "control_w.h"
0019 #include "poly.h"
0020
0021 #define HiPOWERop 3
0022 static const unsigned long long oddplterm[HiPOWERop] = {
0023 0x0000000000000000LL,
0024 0x0051a1cf08fca228LL,
0025 0x0000000071284ff7LL
0026 };
0027
0028 #define HiPOWERon 2
0029 static const unsigned long long oddnegterm[HiPOWERon] = {
0030 0x1291a9a184244e80LL,
0031 0x0000583245819c21LL
0032 };
0033
0034 #define HiPOWERep 2
0035 static const unsigned long long evenplterm[HiPOWERep] = {
0036 0x0e848884b539e888LL,
0037 0x00003c7f18b887daLL
0038 };
0039
0040 #define HiPOWERen 2
0041 static const unsigned long long evennegterm[HiPOWERen] = {
0042 0xf1f0200fd51569ccLL,
0043 0x003afb46105c4432LL
0044 };
0045
0046 static const unsigned long long twothirds = 0xaaaaaaaaaaaaaaabLL;
0047
0048
0049
0050
0051 void poly_tan(FPU_REG *st0_ptr)
0052 {
0053 long int exponent;
0054 int invert;
0055 Xsig argSq, argSqSq, accumulatoro, accumulatore, accum,
0056 argSignif, fix_up;
0057 unsigned long adj;
0058
0059 exponent = exponent(st0_ptr);
0060
0061 #ifdef PARANOID
0062 if (signnegative(st0_ptr)) {
0063 arith_invalid(0);
0064 return;
0065 }
0066 #endif
0067
0068
0069 if ((exponent == 0)
0070 || ((exponent == -1) && (st0_ptr->sigh > 0xc90fdaa2))) {
0071
0072 invert = 1;
0073 accum.lsw = 0;
0074 XSIG_LL(accum) = significand(st0_ptr);
0075
0076 if (exponent == 0) {
0077
0078
0079 XSIG_LL(accum) <<= 1;
0080 }
0081
0082 XSIG_LL(accum) = 0x921fb54442d18469LL - XSIG_LL(accum);
0083
0084 if (XSIG_LL(accum) == 0xffffffffffffffffLL) {
0085 FPU_settag0(TAG_Valid);
0086 significand(st0_ptr) = 0x8a51e04daabda360LL;
0087 setexponent16(st0_ptr,
0088 (0x41 + EXTENDED_Ebias) | SIGN_Negative);
0089 return;
0090 }
0091
0092 argSignif.lsw = accum.lsw;
0093 XSIG_LL(argSignif) = XSIG_LL(accum);
0094 exponent = -1 + norm_Xsig(&argSignif);
0095 } else {
0096 invert = 0;
0097 argSignif.lsw = 0;
0098 XSIG_LL(accum) = XSIG_LL(argSignif) = significand(st0_ptr);
0099
0100 if (exponent < -1) {
0101
0102 if (FPU_shrx(&XSIG_LL(accum), -1 - exponent) >=
0103 0x80000000U)
0104 XSIG_LL(accum)++;
0105 }
0106 }
0107
0108 XSIG_LL(argSq) = XSIG_LL(accum);
0109 argSq.lsw = accum.lsw;
0110 mul_Xsig_Xsig(&argSq, &argSq);
0111 XSIG_LL(argSqSq) = XSIG_LL(argSq);
0112 argSqSq.lsw = argSq.lsw;
0113 mul_Xsig_Xsig(&argSqSq, &argSqSq);
0114
0115
0116 accumulatoro.msw = accumulatoro.midw = accumulatoro.lsw = 0;
0117 polynomial_Xsig(&accumulatoro, &XSIG_LL(argSqSq), oddnegterm,
0118 HiPOWERon - 1);
0119 mul_Xsig_Xsig(&accumulatoro, &argSq);
0120 negate_Xsig(&accumulatoro);
0121
0122 polynomial_Xsig(&accumulatoro, &XSIG_LL(argSqSq), oddplterm,
0123 HiPOWERop - 1);
0124
0125
0126 accumulatore.msw = accumulatore.midw = accumulatore.lsw = 0;
0127 polynomial_Xsig(&accumulatore, &XSIG_LL(argSqSq), evenplterm,
0128 HiPOWERep - 1);
0129 mul_Xsig_Xsig(&accumulatore, &argSq);
0130 negate_Xsig(&accumulatore);
0131
0132 polynomial_Xsig(&accumulatore, &XSIG_LL(argSqSq), evennegterm,
0133 HiPOWERen - 1);
0134
0135 mul64_Xsig(&accumulatore, &XSIG_LL(argSignif));
0136 mul64_Xsig(&accumulatore, &XSIG_LL(argSignif));
0137
0138 shr_Xsig(&accumulatore, -2 * (1 + exponent) + 1);
0139 negate_Xsig(&accumulatore);
0140
0141
0142 if (accumulatore.msw == 0) {
0143
0144
0145
0146
0147 XSIG_LL(accum) = 0x8000000000000000LL;
0148 accum.lsw = 0;
0149 } else {
0150 div_Xsig(&accumulatoro, &accumulatore, &accum);
0151 }
0152
0153
0154 mul64_Xsig(&accum, &XSIG_LL(argSignif));
0155 mul64_Xsig(&accum, &XSIG_LL(argSignif));
0156 mul64_Xsig(&accum, &XSIG_LL(argSignif));
0157 mul64_Xsig(&accum, &twothirds);
0158 shr_Xsig(&accum, -2 * (exponent + 1));
0159
0160
0161 add_two_Xsig(&accum, &argSignif, &exponent);
0162
0163 if (invert) {
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174 XSIG_LL(fix_up) = 0x898cc51701b839a2LL;
0175 fix_up.lsw = 0;
0176
0177 if (exponent == 0)
0178 adj = 0xffffffff;
0179
0180 else if (exponent > -30) {
0181 adj = accum.msw >> -(exponent + 1);
0182 adj = mul_32_32(adj, adj);
0183 } else
0184 adj = 0;
0185 adj = mul_32_32(0x898cc517, adj);
0186
0187 fix_up.msw += adj;
0188 if (!(fix_up.msw & 0x80000000)) {
0189
0190 shr_Xsig(&fix_up, 1);
0191 fix_up.msw |= 0x80000000;
0192 shr_Xsig(&fix_up, 64 + exponent);
0193 } else
0194 shr_Xsig(&fix_up, 65 + exponent);
0195
0196 add_two_Xsig(&accum, &fix_up, &exponent);
0197
0198
0199
0200
0201 accumulatoro.lsw = accumulatoro.midw = 0;
0202 accumulatoro.msw = 0x80000000;
0203 div_Xsig(&accumulatoro, &accum, &accum);
0204 exponent = -exponent - 1;
0205 }
0206
0207
0208 round_Xsig(&accum);
0209 FPU_settag0(TAG_Valid);
0210 significand(st0_ptr) = XSIG_LL(accum);
0211 setexponent16(st0_ptr, exponent + EXTENDED_Ebias);
0212
0213 }