diff options
| author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
| commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
| tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/parisc/math-emu | |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/parisc/math-emu')
37 files changed, 15182 insertions, 0 deletions
diff --git a/arch/parisc/math-emu/Makefile b/arch/parisc/math-emu/Makefile new file mode 100644 index 000000000000..affd4c80e3b7 --- /dev/null +++ b/arch/parisc/math-emu/Makefile | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | # | ||
| 2 | # Makefile for the linux/parisc floating point code | ||
| 3 | # | ||
| 4 | |||
| 5 | # See arch/parisc/math-emu/README | ||
| 6 | CFLAGS += -Wno-parentheses -Wno-implicit-function-declaration \ | ||
| 7 | -Wno-uninitialized -Wno-strict-prototypes -Wno-return-type \ | ||
| 8 | -Wno-implicit-int | ||
| 9 | |||
| 10 | obj-y := frnd.o driver.o decode_exc.o fpudispatch.o denormal.o \ | ||
| 11 | dfmpy.o sfmpy.o sfsqrt.o dfsqrt.o dfadd.o fmpyfadd.o \ | ||
| 12 | sfadd.o dfsub.o sfsub.o fcnvfxt.o fcnvff.o fcnvxf.o \ | ||
| 13 | fcnvfx.o fcnvuf.o fcnvfu.o fcnvfut.o dfdiv.o sfdiv.o \ | ||
| 14 | dfrem.o sfrem.o dfcmp.o sfcmp.o | ||
| 15 | |||
| 16 | # Math emulation code beyond the FRND is required for 712/80i and | ||
| 17 | # other very old or stripped-down PA-RISC CPUs -- not currently supported | ||
| 18 | |||
| 19 | obj-$(CONFIG_MATH_EMULATION) += unimplemented-math-emulation.o | ||
diff --git a/arch/parisc/math-emu/README b/arch/parisc/math-emu/README new file mode 100644 index 000000000000..1a0124ef02f2 --- /dev/null +++ b/arch/parisc/math-emu/README | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | All files except driver.c are snapshots from the HP-UX kernel. They've | ||
| 2 | been modified as little as possible. Even though they don't fit the | ||
| 3 | Linux coding style, please leave them in their funny format just in case | ||
| 4 | someone in the future, with access to HP-UX source code, is generous | ||
| 5 | enough to update our copies with later changes from HP-UX -- it'll | ||
| 6 | make their 'diff' job easier if our code is relatively unmodified. | ||
| 7 | |||
| 8 | Required Disclaimer: Hewlett-Packard makes no implied or expressed | ||
| 9 | warranties about this code nor any promises to maintain or test it | ||
| 10 | in any way. This copy of this snapshot is no longer the property | ||
| 11 | of Hewlett-Packard. | ||
diff --git a/arch/parisc/math-emu/cnv_float.h b/arch/parisc/math-emu/cnv_float.h new file mode 100644 index 000000000000..9071e093164a --- /dev/null +++ b/arch/parisc/math-emu/cnv_float.h | |||
| @@ -0,0 +1,377 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifdef __NO_PA_HDRS | ||
| 23 | PA header file -- do not include this header file for non-PA builds. | ||
| 24 | #endif | ||
| 25 | |||
| 26 | /* | ||
| 27 | * Some more constants | ||
| 28 | */ | ||
| 29 | #define SGL_FX_MAX_EXP 30 | ||
| 30 | #define DBL_FX_MAX_EXP 62 | ||
| 31 | #define QUAD_FX_MAX_EXP 126 | ||
| 32 | |||
| 33 | #define Dintp1(object) (object) | ||
| 34 | #define Dintp2(object) (object) | ||
| 35 | |||
| 36 | #define Duintp1(object) (object) | ||
| 37 | #define Duintp2(object) (object) | ||
| 38 | |||
| 39 | #define Qintp0(object) (object) | ||
| 40 | #define Qintp1(object) (object) | ||
| 41 | #define Qintp2(object) (object) | ||
| 42 | #define Qintp3(object) (object) | ||
| 43 | |||
| 44 | |||
| 45 | /* | ||
| 46 | * These macros will be used specifically by the convert instructions. | ||
| 47 | * | ||
| 48 | * | ||
| 49 | * Single format macros | ||
| 50 | */ | ||
| 51 | |||
| 52 | #define Sgl_to_dbl_exponent(src_exponent,dest) \ | ||
| 53 | Deposit_dexponent(dest,src_exponent+(DBL_BIAS-SGL_BIAS)) | ||
| 54 | |||
| 55 | #define Sgl_to_dbl_mantissa(src_mantissa,destA,destB) \ | ||
| 56 | Deposit_dmantissap1(destA,src_mantissa>>3); \ | ||
| 57 | Dmantissap2(destB) = src_mantissa << 29 | ||
| 58 | |||
| 59 | #define Sgl_isinexact_to_fix(sgl_value,exponent) \ | ||
| 60 | ((exponent < (SGL_P - 1)) ? \ | ||
| 61 | (Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) : FALSE) | ||
| 62 | |||
| 63 | #define Int_isinexact_to_sgl(int_value) (int_value << 33 - SGL_EXP_LENGTH) | ||
| 64 | |||
| 65 | #define Sgl_roundnearest_from_int(int_value,sgl_value) \ | ||
| 66 | if (int_value & 1<<(SGL_EXP_LENGTH - 2)) /* round bit */ \ | ||
| 67 | if ((int_value << 34 - SGL_EXP_LENGTH) || Slow(sgl_value)) \ | ||
| 68 | Sall(sgl_value)++ | ||
| 69 | |||
| 70 | #define Dint_isinexact_to_sgl(dint_valueA,dint_valueB) \ | ||
| 71 | ((Dintp1(dint_valueA) << 33 - SGL_EXP_LENGTH) || Dintp2(dint_valueB)) | ||
| 72 | |||
| 73 | #define Sgl_roundnearest_from_dint(dint_valueA,dint_valueB,sgl_value) \ | ||
| 74 | if (Dintp1(dint_valueA) & 1<<(SGL_EXP_LENGTH - 2)) \ | ||
| 75 | if ((Dintp1(dint_valueA) << 34 - SGL_EXP_LENGTH) || \ | ||
| 76 | Dintp2(dint_valueB) || Slow(sgl_value)) Sall(sgl_value)++ | ||
| 77 | |||
| 78 | #define Dint_isinexact_to_dbl(dint_value) \ | ||
| 79 | (Dintp2(dint_value) << 33 - DBL_EXP_LENGTH) | ||
| 80 | |||
| 81 | #define Dbl_roundnearest_from_dint(dint_opndB,dbl_opndA,dbl_opndB) \ | ||
| 82 | if (Dintp2(dint_opndB) & 1<<(DBL_EXP_LENGTH - 2)) \ | ||
| 83 | if ((Dintp2(dint_opndB) << 34 - DBL_EXP_LENGTH) || Dlowp2(dbl_opndB)) \ | ||
| 84 | if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++ | ||
| 85 | |||
| 86 | #define Sgl_isone_roundbit(sgl_value,exponent) \ | ||
| 87 | ((Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) >> 31) | ||
| 88 | |||
| 89 | #define Sgl_isone_stickybit(sgl_value,exponent) \ | ||
| 90 | (exponent < (SGL_P - 2) ? \ | ||
| 91 | Sall(sgl_value) << (SGL_EXP_LENGTH + 2 + exponent) : FALSE) | ||
| 92 | |||
| 93 | |||
| 94 | /* | ||
| 95 | * Double format macros | ||
| 96 | */ | ||
| 97 | |||
| 98 | #define Dbl_to_sgl_exponent(src_exponent,dest) \ | ||
| 99 | dest = src_exponent + (SGL_BIAS - DBL_BIAS) | ||
| 100 | |||
| 101 | #define Dbl_to_sgl_mantissa(srcA,srcB,dest,inexact,guard,sticky,odd) \ | ||
| 102 | Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest); \ | ||
| 103 | guard = Dbit3p2(srcB); \ | ||
| 104 | sticky = Dallp2(srcB)<<4; \ | ||
| 105 | inexact = guard | sticky; \ | ||
| 106 | odd = Dbit2p2(srcB) | ||
| 107 | |||
| 108 | #define Dbl_to_sgl_denormalized(srcA,srcB,exp,dest,inexact,guard,sticky,odd,tiny) \ | ||
| 109 | Deposit_dexponent(srcA,1); \ | ||
| 110 | tiny = TRUE; \ | ||
| 111 | if (exp >= -2) { \ | ||
| 112 | if (exp == 0) { \ | ||
| 113 | inexact = Dallp2(srcB) << 3; \ | ||
| 114 | guard = inexact >> 31; \ | ||
| 115 | sticky = inexact << 1; \ | ||
| 116 | Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest); \ | ||
| 117 | odd = dest << 31; \ | ||
| 118 | if (inexact) { \ | ||
| 119 | switch(Rounding_mode()) { \ | ||
| 120 | case ROUNDPLUS: \ | ||
| 121 | if (Dbl_iszero_sign(srcA)) { \ | ||
| 122 | dest++; \ | ||
| 123 | if (Sgl_isone_hidden(dest)) \ | ||
| 124 | tiny = FALSE; \ | ||
| 125 | dest--; \ | ||
| 126 | } \ | ||
| 127 | break; \ | ||
| 128 | case ROUNDMINUS: \ | ||
| 129 | if (Dbl_isone_sign(srcA)) { \ | ||
| 130 | dest++; \ | ||
| 131 | if (Sgl_isone_hidden(dest)) \ | ||
| 132 | tiny = FALSE; \ | ||
| 133 | dest--; \ | ||
| 134 | } \ | ||
| 135 | break; \ | ||
| 136 | case ROUNDNEAREST: \ | ||
| 137 | if (guard && (sticky || odd)) { \ | ||
| 138 | dest++; \ | ||
| 139 | if (Sgl_isone_hidden(dest)) \ | ||
| 140 | tiny = FALSE; \ | ||
| 141 | dest--; \ | ||
| 142 | } \ | ||
| 143 | break; \ | ||
| 144 | } \ | ||
| 145 | } \ | ||
| 146 | /* shift right by one to get correct result */ \ | ||
| 147 | guard = odd; \ | ||
| 148 | sticky = inexact; \ | ||
| 149 | inexact |= guard; \ | ||
| 150 | dest >>= 1; \ | ||
| 151 | Deposit_dsign(srcA,0); \ | ||
| 152 | Shiftdouble(Dallp1(srcA),Dallp2(srcB),30,dest); \ | ||
| 153 | odd = dest << 31; \ | ||
| 154 | } \ | ||
| 155 | else { \ | ||
| 156 | inexact = Dallp2(srcB) << (2 + exp); \ | ||
| 157 | guard = inexact >> 31; \ | ||
| 158 | sticky = inexact << 1; \ | ||
| 159 | Deposit_dsign(srcA,0); \ | ||
| 160 | if (exp == -2) dest = Dallp1(srcA); \ | ||
| 161 | else Variable_shift_double(Dallp1(srcA),Dallp2(srcB),30-exp,dest); \ | ||
| 162 | odd = dest << 31; \ | ||
| 163 | } \ | ||
| 164 | } \ | ||
| 165 | else { \ | ||
| 166 | Deposit_dsign(srcA,0); \ | ||
| 167 | if (exp > (1 - SGL_P)) { \ | ||
| 168 | dest = Dallp1(srcA) >> (- 2 - exp); \ | ||
| 169 | inexact = Dallp1(srcA) << (34 + exp); \ | ||
| 170 | guard = inexact >> 31; \ | ||
| 171 | sticky = (inexact << 1) | Dallp2(srcB); \ | ||
| 172 | inexact |= Dallp2(srcB); \ | ||
| 173 | odd = dest << 31; \ | ||
| 174 | } \ | ||
| 175 | else { \ | ||
| 176 | dest = 0; \ | ||
| 177 | inexact = Dallp1(srcA) | Dallp2(srcB); \ | ||
| 178 | if (exp == (1 - SGL_P)) { \ | ||
| 179 | guard = Dhidden(srcA); \ | ||
| 180 | sticky = Dmantissap1(srcA) | Dallp2(srcB); \ | ||
| 181 | } \ | ||
| 182 | else { \ | ||
| 183 | guard = 0; \ | ||
| 184 | sticky = inexact; \ | ||
| 185 | } \ | ||
| 186 | odd = 0; \ | ||
| 187 | } \ | ||
| 188 | } \ | ||
| 189 | exp = 0 | ||
| 190 | |||
| 191 | #define Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent) \ | ||
| 192 | (exponent < (DBL_P-33) ? \ | ||
| 193 | Dallp2(dbl_valueB) || Dallp1(dbl_valueA) << (DBL_EXP_LENGTH+1+exponent) : \ | ||
| 194 | (exponent < (DBL_P-1) ? Dallp2(dbl_valueB) << (exponent + (33-DBL_P)) : \ | ||
| 195 | FALSE)) | ||
| 196 | |||
| 197 | #define Dbl_isoverflow_to_int(exponent,dbl_valueA,dbl_valueB) \ | ||
| 198 | ((exponent > SGL_FX_MAX_EXP + 1) || Dsign(dbl_valueA)==0 || \ | ||
| 199 | Dmantissap1(dbl_valueA)!=0 || (Dallp2(dbl_valueB)>>21)!=0 ) | ||
| 200 | |||
| 201 | #define Dbl_isone_roundbit(dbl_valueA,dbl_valueB,exponent) \ | ||
| 202 | ((exponent < (DBL_P - 33) ? \ | ||
| 203 | Dallp1(dbl_valueA) >> ((30 - DBL_EXP_LENGTH) - exponent) : \ | ||
| 204 | Dallp2(dbl_valueB) >> ((DBL_P - 2) - exponent)) & 1) | ||
| 205 | |||
| 206 | #define Dbl_isone_stickybit(dbl_valueA,dbl_valueB,exponent) \ | ||
| 207 | (exponent < (DBL_P-34) ? \ | ||
| 208 | (Dallp2(dbl_valueB) || Dallp1(dbl_valueA)<<(DBL_EXP_LENGTH+2+exponent)) : \ | ||
| 209 | (exponent<(DBL_P-2) ? (Dallp2(dbl_valueB) << (exponent + (34-DBL_P))) : \ | ||
| 210 | FALSE)) | ||
| 211 | |||
| 212 | |||
| 213 | /* Int macros */ | ||
| 214 | |||
| 215 | #define Int_from_sgl_mantissa(sgl_value,exponent) \ | ||
| 216 | Sall(sgl_value) = \ | ||
| 217 | (unsigned)(Sall(sgl_value) << SGL_EXP_LENGTH)>>(31 - exponent) | ||
| 218 | |||
| 219 | #define Int_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent) \ | ||
| 220 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),22,Dallp1(dbl_valueA)); \ | ||
| 221 | if (exponent < 31) Dallp1(dbl_valueA) >>= 30 - exponent; \ | ||
| 222 | else Dallp1(dbl_valueA) <<= 1 | ||
| 223 | |||
| 224 | #define Int_negate(int_value) int_value = -int_value | ||
| 225 | |||
| 226 | |||
| 227 | /* Dint macros */ | ||
| 228 | |||
| 229 | #define Dint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \ | ||
| 230 | {Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \ | ||
| 231 | if (exponent <= 31) { \ | ||
| 232 | Dintp1(dresultA) = 0; \ | ||
| 233 | Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \ | ||
| 234 | } \ | ||
| 235 | else { \ | ||
| 236 | Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \ | ||
| 237 | Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \ | ||
| 238 | }} | ||
| 239 | |||
| 240 | |||
| 241 | #define Dint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \ | ||
| 242 | {if (exponent < 32) { \ | ||
| 243 | Dintp1(destA) = 0; \ | ||
| 244 | if (exponent <= 20) \ | ||
| 245 | Dintp2(destB) = Dallp1(dbl_valueA) >> 20-exponent; \ | ||
| 246 | else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \ | ||
| 247 | 52-exponent,Dintp2(destB)); \ | ||
| 248 | } \ | ||
| 249 | else { \ | ||
| 250 | if (exponent <= 52) { \ | ||
| 251 | Dintp1(destA) = Dallp1(dbl_valueA) >> 52-exponent; \ | ||
| 252 | if (exponent == 52) Dintp2(destB) = Dallp2(dbl_valueB); \ | ||
| 253 | else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \ | ||
| 254 | 52-exponent,Dintp2(destB)); \ | ||
| 255 | } \ | ||
| 256 | else { \ | ||
| 257 | Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \ | ||
| 258 | 84-exponent,Dintp1(destA)); \ | ||
| 259 | Dintp2(destB) = Dallp2(dbl_valueB) << exponent-52; \ | ||
| 260 | } \ | ||
| 261 | }} | ||
| 262 | |||
| 263 | #define Dint_setzero(dresultA,dresultB) \ | ||
| 264 | Dintp1(dresultA) = 0; \ | ||
| 265 | Dintp2(dresultB) = 0 | ||
| 266 | |||
| 267 | #define Dint_setone_sign(dresultA,dresultB) \ | ||
| 268 | Dintp1(dresultA) = ~Dintp1(dresultA); \ | ||
| 269 | if ((Dintp2(dresultB) = -Dintp2(dresultB)) == 0) Dintp1(dresultA)++ | ||
| 270 | |||
| 271 | #define Dint_set_minint(dresultA,dresultB) \ | ||
| 272 | Dintp1(dresultA) = (unsigned int)1<<31; \ | ||
| 273 | Dintp2(dresultB) = 0 | ||
| 274 | |||
| 275 | #define Dint_isone_lowp2(dresultB) (Dintp2(dresultB) & 01) | ||
| 276 | |||
| 277 | #define Dint_increment(dresultA,dresultB) \ | ||
| 278 | if ((++Dintp2(dresultB))==0) Dintp1(dresultA)++ | ||
| 279 | |||
| 280 | #define Dint_decrement(dresultA,dresultB) \ | ||
| 281 | if ((Dintp2(dresultB)--)==0) Dintp1(dresultA)-- | ||
| 282 | |||
| 283 | #define Dint_negate(dresultA,dresultB) \ | ||
| 284 | Dintp1(dresultA) = ~Dintp1(dresultA); \ | ||
| 285 | if ((Dintp2(dresultB) = -Dintp2(dresultB))==0) Dintp1(dresultA)++ | ||
| 286 | |||
| 287 | #define Dint_copyfromptr(src,destA,destB) \ | ||
| 288 | Dintp1(destA) = src->wd0; \ | ||
| 289 | Dintp2(destB) = src->wd1 | ||
| 290 | #define Dint_copytoptr(srcA,srcB,dest) \ | ||
| 291 | dest->wd0 = Dintp1(srcA); \ | ||
| 292 | dest->wd1 = Dintp2(srcB) | ||
| 293 | |||
| 294 | |||
| 295 | /* other macros */ | ||
| 296 | |||
| 297 | #define Find_ms_one_bit(value, position) \ | ||
| 298 | { \ | ||
| 299 | int var; \ | ||
| 300 | for (var=8; var >=1; var >>= 1) { \ | ||
| 301 | if (value >> 32 - position) \ | ||
| 302 | position -= var; \ | ||
| 303 | else position += var; \ | ||
| 304 | } \ | ||
| 305 | if ((value >> 32 - position) == 0) \ | ||
| 306 | position--; \ | ||
| 307 | else position -= 2; \ | ||
| 308 | } | ||
| 309 | |||
| 310 | |||
| 311 | /* | ||
| 312 | * Unsigned int macros | ||
| 313 | */ | ||
| 314 | #define Duint_copyfromptr(src,destA,destB) \ | ||
| 315 | Dint_copyfromptr(src,destA,destB) | ||
| 316 | #define Duint_copytoptr(srcA,srcB,dest) \ | ||
| 317 | Dint_copytoptr(srcA,srcB,dest) | ||
| 318 | |||
| 319 | #define Suint_isinexact_to_sgl(int_value) \ | ||
| 320 | (int_value << 32 - SGL_EXP_LENGTH) | ||
| 321 | |||
| 322 | #define Sgl_roundnearest_from_suint(suint_value,sgl_value) \ | ||
| 323 | if (suint_value & 1<<(SGL_EXP_LENGTH - 1)) /* round bit */ \ | ||
| 324 | if ((suint_value << 33 - SGL_EXP_LENGTH) || Slow(sgl_value)) \ | ||
| 325 | Sall(sgl_value)++ | ||
| 326 | |||
| 327 | #define Duint_isinexact_to_sgl(duint_valueA,duint_valueB) \ | ||
| 328 | ((Duintp1(duint_valueA) << 32 - SGL_EXP_LENGTH) || Duintp2(duint_valueB)) | ||
| 329 | |||
| 330 | #define Sgl_roundnearest_from_duint(duint_valueA,duint_valueB,sgl_value) \ | ||
| 331 | if (Duintp1(duint_valueA) & 1<<(SGL_EXP_LENGTH - 1)) \ | ||
| 332 | if ((Duintp1(duint_valueA) << 33 - SGL_EXP_LENGTH) || \ | ||
| 333 | Duintp2(duint_valueB) || Slow(sgl_value)) Sall(sgl_value)++ | ||
| 334 | |||
| 335 | #define Duint_isinexact_to_dbl(duint_value) \ | ||
| 336 | (Duintp2(duint_value) << 32 - DBL_EXP_LENGTH) | ||
| 337 | |||
| 338 | #define Dbl_roundnearest_from_duint(duint_opndB,dbl_opndA,dbl_opndB) \ | ||
| 339 | if (Duintp2(duint_opndB) & 1<<(DBL_EXP_LENGTH - 1)) \ | ||
| 340 | if ((Duintp2(duint_opndB) << 33 - DBL_EXP_LENGTH) || Dlowp2(dbl_opndB)) \ | ||
| 341 | if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++ | ||
| 342 | |||
| 343 | #define Suint_from_sgl_mantissa(src,exponent,result) \ | ||
| 344 | Sall(result) = (unsigned)(Sall(src) << SGL_EXP_LENGTH)>>(31 - exponent) | ||
| 345 | |||
| 346 | #define Sgl_isinexact_to_unsigned(sgl_value,exponent) \ | ||
| 347 | Sgl_isinexact_to_fix(sgl_value,exponent) | ||
| 348 | |||
| 349 | #define Duint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \ | ||
| 350 | {Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \ | ||
| 351 | if (exponent <= 31) { \ | ||
| 352 | Dintp1(dresultA) = 0; \ | ||
| 353 | Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \ | ||
| 354 | } \ | ||
| 355 | else { \ | ||
| 356 | Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \ | ||
| 357 | Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \ | ||
| 358 | } \ | ||
| 359 | Sall(sgl_value) >>= SGL_EXP_LENGTH; /* return to original */ \ | ||
| 360 | } | ||
| 361 | |||
| 362 | #define Duint_setzero(dresultA,dresultB) \ | ||
| 363 | Dint_setzero(dresultA,dresultB) | ||
| 364 | |||
| 365 | #define Duint_increment(dresultA,dresultB) Dint_increment(dresultA,dresultB) | ||
| 366 | |||
| 367 | #define Duint_isone_lowp2(dresultB) Dint_isone_lowp2(dresultB) | ||
| 368 | |||
| 369 | #define Suint_from_dbl_mantissa(srcA,srcB,exponent,dest) \ | ||
| 370 | Shiftdouble(Dallp1(srcA),Dallp2(srcB),21,dest); \ | ||
| 371 | dest = (unsigned)dest >> 31 - exponent | ||
| 372 | |||
| 373 | #define Dbl_isinexact_to_unsigned(dbl_valueA,dbl_valueB,exponent) \ | ||
| 374 | Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent) | ||
| 375 | |||
| 376 | #define Duint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \ | ||
| 377 | Dint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) | ||
diff --git a/arch/parisc/math-emu/dbl_float.h b/arch/parisc/math-emu/dbl_float.h new file mode 100644 index 000000000000..1570e2e0a327 --- /dev/null +++ b/arch/parisc/math-emu/dbl_float.h | |||
| @@ -0,0 +1,847 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | #ifdef __NO_PA_HDRS | ||
| 22 | PA header file -- do not include this header file for non-PA builds. | ||
| 23 | #endif | ||
| 24 | |||
| 25 | /* 32-bit word grabing functions */ | ||
| 26 | #define Dbl_firstword(value) Dallp1(value) | ||
| 27 | #define Dbl_secondword(value) Dallp2(value) | ||
| 28 | #define Dbl_thirdword(value) dummy_location | ||
| 29 | #define Dbl_fourthword(value) dummy_location | ||
| 30 | |||
| 31 | #define Dbl_sign(object) Dsign(object) | ||
| 32 | #define Dbl_exponent(object) Dexponent(object) | ||
| 33 | #define Dbl_signexponent(object) Dsignexponent(object) | ||
| 34 | #define Dbl_mantissap1(object) Dmantissap1(object) | ||
| 35 | #define Dbl_mantissap2(object) Dmantissap2(object) | ||
| 36 | #define Dbl_exponentmantissap1(object) Dexponentmantissap1(object) | ||
| 37 | #define Dbl_allp1(object) Dallp1(object) | ||
| 38 | #define Dbl_allp2(object) Dallp2(object) | ||
| 39 | |||
| 40 | /* dbl_and_signs ands the sign bits of each argument and puts the result | ||
| 41 | * into the first argument. dbl_or_signs ors those same sign bits */ | ||
| 42 | #define Dbl_and_signs( src1dst, src2) \ | ||
| 43 | Dallp1(src1dst) = (Dallp1(src2)|~((unsigned int)1<<31)) & Dallp1(src1dst) | ||
| 44 | #define Dbl_or_signs( src1dst, src2) \ | ||
| 45 | Dallp1(src1dst) = (Dallp1(src2)&((unsigned int)1<<31)) | Dallp1(src1dst) | ||
| 46 | |||
| 47 | /* The hidden bit is always the low bit of the exponent */ | ||
| 48 | #define Dbl_clear_exponent_set_hidden(srcdst) Deposit_dexponent(srcdst,1) | ||
| 49 | #define Dbl_clear_signexponent_set_hidden(srcdst) \ | ||
| 50 | Deposit_dsignexponent(srcdst,1) | ||
| 51 | #define Dbl_clear_sign(srcdst) Dallp1(srcdst) &= ~((unsigned int)1<<31) | ||
| 52 | #define Dbl_clear_signexponent(srcdst) \ | ||
| 53 | Dallp1(srcdst) &= Dmantissap1((unsigned int)-1) | ||
| 54 | |||
| 55 | /* Exponent field for doubles has already been cleared and may be | ||
| 56 | * included in the shift. Here we need to generate two double width | ||
| 57 | * variable shifts. The insignificant bits can be ignored. | ||
| 58 | * MTSAR f(varamount) | ||
| 59 | * VSHD srcdst.high,srcdst.low => srcdst.low | ||
| 60 | * VSHD 0,srcdst.high => srcdst.high | ||
| 61 | * This is very difficult to model with C expressions since the shift amount | ||
| 62 | * could exceed 32. */ | ||
| 63 | /* varamount must be less than 64 */ | ||
| 64 | #define Dbl_rightshift(srcdstA, srcdstB, varamount) \ | ||
| 65 | {if((varamount) >= 32) { \ | ||
| 66 | Dallp2(srcdstB) = Dallp1(srcdstA) >> (varamount-32); \ | ||
| 67 | Dallp1(srcdstA)=0; \ | ||
| 68 | } \ | ||
| 69 | else if(varamount > 0) { \ | ||
| 70 | Variable_shift_double(Dallp1(srcdstA), Dallp2(srcdstB), \ | ||
| 71 | (varamount), Dallp2(srcdstB)); \ | ||
| 72 | Dallp1(srcdstA) >>= varamount; \ | ||
| 73 | } } | ||
| 74 | /* varamount must be less than 64 */ | ||
| 75 | #define Dbl_rightshift_exponentmantissa(srcdstA, srcdstB, varamount) \ | ||
| 76 | {if((varamount) >= 32) { \ | ||
| 77 | Dallp2(srcdstB) = Dexponentmantissap1(srcdstA) >> (varamount-32); \ | ||
| 78 | Dallp1(srcdstA) &= ((unsigned int)1<<31); /* clear expmant field */ \ | ||
| 79 | } \ | ||
| 80 | else if(varamount > 0) { \ | ||
| 81 | Variable_shift_double(Dexponentmantissap1(srcdstA), Dallp2(srcdstB), \ | ||
| 82 | (varamount), Dallp2(srcdstB)); \ | ||
| 83 | Deposit_dexponentmantissap1(srcdstA, \ | ||
| 84 | (Dexponentmantissap1(srcdstA)>>varamount)); \ | ||
| 85 | } } | ||
| 86 | /* varamount must be less than 64 */ | ||
| 87 | #define Dbl_leftshift(srcdstA, srcdstB, varamount) \ | ||
| 88 | {if((varamount) >= 32) { \ | ||
| 89 | Dallp1(srcdstA) = Dallp2(srcdstB) << (varamount-32); \ | ||
| 90 | Dallp2(srcdstB)=0; \ | ||
| 91 | } \ | ||
| 92 | else { \ | ||
| 93 | if ((varamount) > 0) { \ | ||
| 94 | Dallp1(srcdstA) = (Dallp1(srcdstA) << (varamount)) | \ | ||
| 95 | (Dallp2(srcdstB) >> (32-(varamount))); \ | ||
| 96 | Dallp2(srcdstB) <<= varamount; \ | ||
| 97 | } \ | ||
| 98 | } } | ||
| 99 | #define Dbl_leftshiftby1_withextent(lefta,leftb,right,resulta,resultb) \ | ||
| 100 | Shiftdouble(Dallp1(lefta), Dallp2(leftb), 31, Dallp1(resulta)); \ | ||
| 101 | Shiftdouble(Dallp2(leftb), Extall(right), 31, Dallp2(resultb)) | ||
| 102 | |||
| 103 | #define Dbl_rightshiftby1_withextent(leftb,right,dst) \ | ||
| 104 | Extall(dst) = (Dallp2(leftb) << 31) | ((unsigned int)Extall(right) >> 1) | \ | ||
| 105 | Extlow(right) | ||
| 106 | |||
| 107 | #define Dbl_arithrightshiftby1(srcdstA,srcdstB) \ | ||
| 108 | Shiftdouble(Dallp1(srcdstA),Dallp2(srcdstB),1,Dallp2(srcdstB));\ | ||
| 109 | Dallp1(srcdstA) = (int)Dallp1(srcdstA) >> 1 | ||
| 110 | |||
| 111 | /* Sign extend the sign bit with an integer destination */ | ||
| 112 | #define Dbl_signextendedsign(value) Dsignedsign(value) | ||
| 113 | |||
| 114 | #define Dbl_isone_hidden(dbl_value) (Is_dhidden(dbl_value)!=0) | ||
| 115 | /* Singles and doubles may include the sign and exponent fields. The | ||
| 116 | * hidden bit and the hidden overflow must be included. */ | ||
| 117 | #define Dbl_increment(dbl_valueA,dbl_valueB) \ | ||
| 118 | if( (Dallp2(dbl_valueB) += 1) == 0 ) Dallp1(dbl_valueA) += 1 | ||
| 119 | #define Dbl_increment_mantissa(dbl_valueA,dbl_valueB) \ | ||
| 120 | if( (Dmantissap2(dbl_valueB) += 1) == 0 ) \ | ||
| 121 | Deposit_dmantissap1(dbl_valueA,dbl_valueA+1) | ||
| 122 | #define Dbl_decrement(dbl_valueA,dbl_valueB) \ | ||
| 123 | if( Dallp2(dbl_valueB) == 0 ) Dallp1(dbl_valueA) -= 1; \ | ||
| 124 | Dallp2(dbl_valueB) -= 1 | ||
| 125 | |||
| 126 | #define Dbl_isone_sign(dbl_value) (Is_dsign(dbl_value)!=0) | ||
| 127 | #define Dbl_isone_hiddenoverflow(dbl_value) (Is_dhiddenoverflow(dbl_value)!=0) | ||
| 128 | #define Dbl_isone_lowmantissap1(dbl_valueA) (Is_dlowp1(dbl_valueA)!=0) | ||
| 129 | #define Dbl_isone_lowmantissap2(dbl_valueB) (Is_dlowp2(dbl_valueB)!=0) | ||
| 130 | #define Dbl_isone_signaling(dbl_value) (Is_dsignaling(dbl_value)!=0) | ||
| 131 | #define Dbl_is_signalingnan(dbl_value) (Dsignalingnan(dbl_value)==0xfff) | ||
| 132 | #define Dbl_isnotzero(dbl_valueA,dbl_valueB) \ | ||
| 133 | (Dallp1(dbl_valueA) || Dallp2(dbl_valueB)) | ||
| 134 | #define Dbl_isnotzero_hiddenhigh7mantissa(dbl_value) \ | ||
| 135 | (Dhiddenhigh7mantissa(dbl_value)!=0) | ||
| 136 | #define Dbl_isnotzero_exponent(dbl_value) (Dexponent(dbl_value)!=0) | ||
| 137 | #define Dbl_isnotzero_mantissa(dbl_valueA,dbl_valueB) \ | ||
| 138 | (Dmantissap1(dbl_valueA) || Dmantissap2(dbl_valueB)) | ||
| 139 | #define Dbl_isnotzero_mantissap1(dbl_valueA) (Dmantissap1(dbl_valueA)!=0) | ||
| 140 | #define Dbl_isnotzero_mantissap2(dbl_valueB) (Dmantissap2(dbl_valueB)!=0) | ||
| 141 | #define Dbl_isnotzero_exponentmantissa(dbl_valueA,dbl_valueB) \ | ||
| 142 | (Dexponentmantissap1(dbl_valueA) || Dmantissap2(dbl_valueB)) | ||
| 143 | #define Dbl_isnotzero_low4p2(dbl_value) (Dlow4p2(dbl_value)!=0) | ||
| 144 | #define Dbl_iszero(dbl_valueA,dbl_valueB) (Dallp1(dbl_valueA)==0 && \ | ||
| 145 | Dallp2(dbl_valueB)==0) | ||
| 146 | #define Dbl_iszero_allp1(dbl_value) (Dallp1(dbl_value)==0) | ||
| 147 | #define Dbl_iszero_allp2(dbl_value) (Dallp2(dbl_value)==0) | ||
| 148 | #define Dbl_iszero_hidden(dbl_value) (Is_dhidden(dbl_value)==0) | ||
| 149 | #define Dbl_iszero_hiddenoverflow(dbl_value) (Is_dhiddenoverflow(dbl_value)==0) | ||
| 150 | #define Dbl_iszero_hiddenhigh3mantissa(dbl_value) \ | ||
| 151 | (Dhiddenhigh3mantissa(dbl_value)==0) | ||
| 152 | #define Dbl_iszero_hiddenhigh7mantissa(dbl_value) \ | ||
| 153 | (Dhiddenhigh7mantissa(dbl_value)==0) | ||
| 154 | #define Dbl_iszero_sign(dbl_value) (Is_dsign(dbl_value)==0) | ||
| 155 | #define Dbl_iszero_exponent(dbl_value) (Dexponent(dbl_value)==0) | ||
| 156 | #define Dbl_iszero_mantissa(dbl_valueA,dbl_valueB) \ | ||
| 157 | (Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0) | ||
| 158 | #define Dbl_iszero_exponentmantissa(dbl_valueA,dbl_valueB) \ | ||
| 159 | (Dexponentmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0) | ||
| 160 | #define Dbl_isinfinity_exponent(dbl_value) \ | ||
| 161 | (Dexponent(dbl_value)==DBL_INFINITY_EXPONENT) | ||
| 162 | #define Dbl_isnotinfinity_exponent(dbl_value) \ | ||
| 163 | (Dexponent(dbl_value)!=DBL_INFINITY_EXPONENT) | ||
| 164 | #define Dbl_isinfinity(dbl_valueA,dbl_valueB) \ | ||
| 165 | (Dexponent(dbl_valueA)==DBL_INFINITY_EXPONENT && \ | ||
| 166 | Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0) | ||
| 167 | #define Dbl_isnan(dbl_valueA,dbl_valueB) \ | ||
| 168 | (Dexponent(dbl_valueA)==DBL_INFINITY_EXPONENT && \ | ||
| 169 | (Dmantissap1(dbl_valueA)!=0 || Dmantissap2(dbl_valueB)!=0)) | ||
| 170 | #define Dbl_isnotnan(dbl_valueA,dbl_valueB) \ | ||
| 171 | (Dexponent(dbl_valueA)!=DBL_INFINITY_EXPONENT || \ | ||
| 172 | (Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)) | ||
| 173 | |||
| 174 | #define Dbl_islessthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ | ||
| 175 | (Dallp1(dbl_op1a) < Dallp1(dbl_op2a) || \ | ||
| 176 | (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \ | ||
| 177 | Dallp2(dbl_op1b) < Dallp2(dbl_op2b))) | ||
| 178 | #define Dbl_isgreaterthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ | ||
| 179 | (Dallp1(dbl_op1a) > Dallp1(dbl_op2a) || \ | ||
| 180 | (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \ | ||
| 181 | Dallp2(dbl_op1b) > Dallp2(dbl_op2b))) | ||
| 182 | #define Dbl_isnotlessthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ | ||
| 183 | (Dallp1(dbl_op1a) > Dallp1(dbl_op2a) || \ | ||
| 184 | (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \ | ||
| 185 | Dallp2(dbl_op1b) >= Dallp2(dbl_op2b))) | ||
| 186 | #define Dbl_isnotgreaterthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ | ||
| 187 | (Dallp1(dbl_op1a) < Dallp1(dbl_op2a) || \ | ||
| 188 | (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) && \ | ||
| 189 | Dallp2(dbl_op1b) <= Dallp2(dbl_op2b))) | ||
| 190 | #define Dbl_isequal(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \ | ||
| 191 | ((Dallp1(dbl_op1a) == Dallp1(dbl_op2a)) && \ | ||
| 192 | (Dallp2(dbl_op1b) == Dallp2(dbl_op2b))) | ||
| 193 | |||
| 194 | #define Dbl_leftshiftby8(dbl_valueA,dbl_valueB) \ | ||
| 195 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),24,Dallp1(dbl_valueA)); \ | ||
| 196 | Dallp2(dbl_valueB) <<= 8 | ||
| 197 | #define Dbl_leftshiftby7(dbl_valueA,dbl_valueB) \ | ||
| 198 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),25,Dallp1(dbl_valueA)); \ | ||
| 199 | Dallp2(dbl_valueB) <<= 7 | ||
| 200 | #define Dbl_leftshiftby4(dbl_valueA,dbl_valueB) \ | ||
| 201 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),28,Dallp1(dbl_valueA)); \ | ||
| 202 | Dallp2(dbl_valueB) <<= 4 | ||
| 203 | #define Dbl_leftshiftby3(dbl_valueA,dbl_valueB) \ | ||
| 204 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),29,Dallp1(dbl_valueA)); \ | ||
| 205 | Dallp2(dbl_valueB) <<= 3 | ||
| 206 | #define Dbl_leftshiftby2(dbl_valueA,dbl_valueB) \ | ||
| 207 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),30,Dallp1(dbl_valueA)); \ | ||
| 208 | Dallp2(dbl_valueB) <<= 2 | ||
| 209 | #define Dbl_leftshiftby1(dbl_valueA,dbl_valueB) \ | ||
| 210 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),31,Dallp1(dbl_valueA)); \ | ||
| 211 | Dallp2(dbl_valueB) <<= 1 | ||
| 212 | |||
| 213 | #define Dbl_rightshiftby8(dbl_valueA,dbl_valueB) \ | ||
| 214 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),8,Dallp2(dbl_valueB)); \ | ||
| 215 | Dallp1(dbl_valueA) >>= 8 | ||
| 216 | #define Dbl_rightshiftby4(dbl_valueA,dbl_valueB) \ | ||
| 217 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),4,Dallp2(dbl_valueB)); \ | ||
| 218 | Dallp1(dbl_valueA) >>= 4 | ||
| 219 | #define Dbl_rightshiftby2(dbl_valueA,dbl_valueB) \ | ||
| 220 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),2,Dallp2(dbl_valueB)); \ | ||
| 221 | Dallp1(dbl_valueA) >>= 2 | ||
| 222 | #define Dbl_rightshiftby1(dbl_valueA,dbl_valueB) \ | ||
| 223 | Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),1,Dallp2(dbl_valueB)); \ | ||
| 224 | Dallp1(dbl_valueA) >>= 1 | ||
| 225 | |||
| 226 | /* This magnitude comparison uses the signless first words and | ||
| 227 | * the regular part2 words. The comparison is graphically: | ||
| 228 | * | ||
| 229 | * 1st greater? ------------- | ||
| 230 | * | | ||
| 231 | * 1st less?-----------------+--------- | ||
| 232 | * | | | ||
| 233 | * 2nd greater or equal----->| | | ||
| 234 | * False True | ||
| 235 | */ | ||
| 236 | #define Dbl_ismagnitudeless(leftB,rightB,signlessleft,signlessright) \ | ||
| 237 | ((signlessleft <= signlessright) && \ | ||
| 238 | ( (signlessleft < signlessright) || (Dallp2(leftB)<Dallp2(rightB)) )) | ||
| 239 | |||
| 240 | #define Dbl_copytoint_exponentmantissap1(src,dest) \ | ||
| 241 | dest = Dexponentmantissap1(src) | ||
| 242 | |||
| 243 | /* A quiet NaN has the high mantissa bit clear and at least on other (in this | ||
| 244 | * case the adjacent bit) bit set. */ | ||
| 245 | #define Dbl_set_quiet(dbl_value) Deposit_dhigh2mantissa(dbl_value,1) | ||
| 246 | #define Dbl_set_exponent(dbl_value, exp) Deposit_dexponent(dbl_value,exp) | ||
| 247 | |||
| 248 | #define Dbl_set_mantissa(desta,destb,valuea,valueb) \ | ||
| 249 | Deposit_dmantissap1(desta,valuea); \ | ||
| 250 | Dmantissap2(destb) = Dmantissap2(valueb) | ||
| 251 | #define Dbl_set_mantissap1(desta,valuea) \ | ||
| 252 | Deposit_dmantissap1(desta,valuea) | ||
| 253 | #define Dbl_set_mantissap2(destb,valueb) \ | ||
| 254 | Dmantissap2(destb) = Dmantissap2(valueb) | ||
| 255 | |||
| 256 | #define Dbl_set_exponentmantissa(desta,destb,valuea,valueb) \ | ||
| 257 | Deposit_dexponentmantissap1(desta,valuea); \ | ||
| 258 | Dmantissap2(destb) = Dmantissap2(valueb) | ||
| 259 | #define Dbl_set_exponentmantissap1(dest,value) \ | ||
| 260 | Deposit_dexponentmantissap1(dest,value) | ||
| 261 | |||
| 262 | #define Dbl_copyfromptr(src,desta,destb) \ | ||
| 263 | Dallp1(desta) = src->wd0; \ | ||
| 264 | Dallp2(destb) = src->wd1 | ||
| 265 | #define Dbl_copytoptr(srca,srcb,dest) \ | ||
| 266 | dest->wd0 = Dallp1(srca); \ | ||
| 267 | dest->wd1 = Dallp2(srcb) | ||
| 268 | |||
| 269 | /* An infinity is represented with the max exponent and a zero mantissa */ | ||
| 270 | #define Dbl_setinfinity_exponent(dbl_value) \ | ||
| 271 | Deposit_dexponent(dbl_value,DBL_INFINITY_EXPONENT) | ||
| 272 | #define Dbl_setinfinity_exponentmantissa(dbl_valueA,dbl_valueB) \ | ||
| 273 | Deposit_dexponentmantissap1(dbl_valueA, \ | ||
| 274 | (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH)))); \ | ||
| 275 | Dmantissap2(dbl_valueB) = 0 | ||
| 276 | #define Dbl_setinfinitypositive(dbl_valueA,dbl_valueB) \ | ||
| 277 | Dallp1(dbl_valueA) \ | ||
| 278 | = (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \ | ||
| 279 | Dmantissap2(dbl_valueB) = 0 | ||
| 280 | #define Dbl_setinfinitynegative(dbl_valueA,dbl_valueB) \ | ||
| 281 | Dallp1(dbl_valueA) = ((unsigned int)1<<31) | \ | ||
| 282 | (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \ | ||
| 283 | Dmantissap2(dbl_valueB) = 0 | ||
| 284 | #define Dbl_setinfinity(dbl_valueA,dbl_valueB,sign) \ | ||
| 285 | Dallp1(dbl_valueA) = ((unsigned int)sign << 31) | \ | ||
| 286 | (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))); \ | ||
| 287 | Dmantissap2(dbl_valueB) = 0 | ||
| 288 | |||
| 289 | #define Dbl_sethigh4bits(dbl_value, extsign) Deposit_dhigh4p1(dbl_value,extsign) | ||
| 290 | #define Dbl_set_sign(dbl_value,sign) Deposit_dsign(dbl_value,sign) | ||
| 291 | #define Dbl_invert_sign(dbl_value) Deposit_dsign(dbl_value,~Dsign(dbl_value)) | ||
| 292 | #define Dbl_setone_sign(dbl_value) Deposit_dsign(dbl_value,1) | ||
| 293 | #define Dbl_setone_lowmantissap2(dbl_value) Deposit_dlowp2(dbl_value,1) | ||
| 294 | #define Dbl_setzero_sign(dbl_value) Dallp1(dbl_value) &= 0x7fffffff | ||
| 295 | #define Dbl_setzero_exponent(dbl_value) \ | ||
| 296 | Dallp1(dbl_value) &= 0x800fffff | ||
| 297 | #define Dbl_setzero_mantissa(dbl_valueA,dbl_valueB) \ | ||
| 298 | Dallp1(dbl_valueA) &= 0xfff00000; \ | ||
| 299 | Dallp2(dbl_valueB) = 0 | ||
| 300 | #define Dbl_setzero_mantissap1(dbl_value) Dallp1(dbl_value) &= 0xfff00000 | ||
| 301 | #define Dbl_setzero_mantissap2(dbl_value) Dallp2(dbl_value) = 0 | ||
| 302 | #define Dbl_setzero_exponentmantissa(dbl_valueA,dbl_valueB) \ | ||
| 303 | Dallp1(dbl_valueA) &= 0x80000000; \ | ||
| 304 | Dallp2(dbl_valueB) = 0 | ||
| 305 | #define Dbl_setzero_exponentmantissap1(dbl_valueA) \ | ||
| 306 | Dallp1(dbl_valueA) &= 0x80000000 | ||
| 307 | #define Dbl_setzero(dbl_valueA,dbl_valueB) \ | ||
| 308 | Dallp1(dbl_valueA) = 0; Dallp2(dbl_valueB) = 0 | ||
| 309 | #define Dbl_setzerop1(dbl_value) Dallp1(dbl_value) = 0 | ||
| 310 | #define Dbl_setzerop2(dbl_value) Dallp2(dbl_value) = 0 | ||
| 311 | #define Dbl_setnegativezero(dbl_value) \ | ||
| 312 | Dallp1(dbl_value) = (unsigned int)1 << 31; Dallp2(dbl_value) = 0 | ||
| 313 | #define Dbl_setnegativezerop1(dbl_value) Dallp1(dbl_value) = (unsigned int)1<<31 | ||
| 314 | |||
| 315 | /* Use the following macro for both overflow & underflow conditions */ | ||
| 316 | #define ovfl - | ||
| 317 | #define unfl + | ||
| 318 | #define Dbl_setwrapped_exponent(dbl_value,exponent,op) \ | ||
| 319 | Deposit_dexponent(dbl_value,(exponent op DBL_WRAP)) | ||
| 320 | |||
| 321 | #define Dbl_setlargestpositive(dbl_valueA,dbl_valueB) \ | ||
| 322 | Dallp1(dbl_valueA) = ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \ | ||
| 323 | | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ); \ | ||
| 324 | Dallp2(dbl_valueB) = 0xFFFFFFFF | ||
| 325 | #define Dbl_setlargestnegative(dbl_valueA,dbl_valueB) \ | ||
| 326 | Dallp1(dbl_valueA) = ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \ | ||
| 327 | | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ) \ | ||
| 328 | | ((unsigned int)1<<31); \ | ||
| 329 | Dallp2(dbl_valueB) = 0xFFFFFFFF | ||
| 330 | #define Dbl_setlargest_exponentmantissa(dbl_valueA,dbl_valueB) \ | ||
| 331 | Deposit_dexponentmantissap1(dbl_valueA, \ | ||
| 332 | (((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \ | ||
| 333 | | ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 ))); \ | ||
| 334 | Dallp2(dbl_valueB) = 0xFFFFFFFF | ||
| 335 | |||
| 336 | #define Dbl_setnegativeinfinity(dbl_valueA,dbl_valueB) \ | ||
| 337 | Dallp1(dbl_valueA) = ((1<<DBL_EXP_LENGTH) | DBL_INFINITY_EXPONENT) \ | ||
| 338 | << (32-(1+DBL_EXP_LENGTH)) ; \ | ||
| 339 | Dallp2(dbl_valueB) = 0 | ||
| 340 | #define Dbl_setlargest(dbl_valueA,dbl_valueB,sign) \ | ||
| 341 | Dallp1(dbl_valueA) = ((unsigned int)sign << 31) | \ | ||
| 342 | ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) | \ | ||
| 343 | ((1 << (32-(1+DBL_EXP_LENGTH))) - 1 ); \ | ||
| 344 | Dallp2(dbl_valueB) = 0xFFFFFFFF | ||
| 345 | |||
| 346 | |||
| 347 | /* The high bit is always zero so arithmetic or logical shifts will work. */ | ||
| 348 | #define Dbl_right_align(srcdstA,srcdstB,shift,extent) \ | ||
| 349 | if( shift >= 32 ) \ | ||
| 350 | { \ | ||
| 351 | /* Big shift requires examining the portion shift off \ | ||
| 352 | the end to properly set inexact. */ \ | ||
| 353 | if(shift < 64) \ | ||
| 354 | { \ | ||
| 355 | if(shift > 32) \ | ||
| 356 | { \ | ||
| 357 | Variable_shift_double(Dallp1(srcdstA),Dallp2(srcdstB), \ | ||
| 358 | shift-32, Extall(extent)); \ | ||
| 359 | if(Dallp2(srcdstB) << 64 - (shift)) Ext_setone_low(extent); \ | ||
| 360 | } \ | ||
| 361 | else Extall(extent) = Dallp2(srcdstB); \ | ||
| 362 | Dallp2(srcdstB) = Dallp1(srcdstA) >> (shift - 32); \ | ||
| 363 | } \ | ||
| 364 | else \ | ||
| 365 | { \ | ||
| 366 | Extall(extent) = Dallp1(srcdstA); \ | ||
| 367 | if(Dallp2(srcdstB)) Ext_setone_low(extent); \ | ||
| 368 | Dallp2(srcdstB) = 0; \ | ||
| 369 | } \ | ||
| 370 | Dallp1(srcdstA) = 0; \ | ||
| 371 | } \ | ||
| 372 | else \ | ||
| 373 | { \ | ||
| 374 | /* Small alignment is simpler. Extension is easily set. */ \ | ||
| 375 | if (shift > 0) \ | ||
| 376 | { \ | ||
| 377 | Extall(extent) = Dallp2(srcdstB) << 32 - (shift); \ | ||
| 378 | Variable_shift_double(Dallp1(srcdstA),Dallp2(srcdstB),shift, \ | ||
| 379 | Dallp2(srcdstB)); \ | ||
| 380 | Dallp1(srcdstA) >>= shift; \ | ||
| 381 | } \ | ||
| 382 | else Extall(extent) = 0; \ | ||
| 383 | } | ||
| 384 | |||
| 385 | /* | ||
| 386 | * Here we need to shift the result right to correct for an overshift | ||
| 387 | * (due to the exponent becoming negative) during normalization. | ||
| 388 | */ | ||
| 389 | #define Dbl_fix_overshift(srcdstA,srcdstB,shift,extent) \ | ||
| 390 | Extall(extent) = Dallp2(srcdstB) << 32 - (shift); \ | ||
| 391 | Dallp2(srcdstB) = (Dallp1(srcdstA) << 32 - (shift)) | \ | ||
| 392 | (Dallp2(srcdstB) >> (shift)); \ | ||
| 393 | Dallp1(srcdstA) = Dallp1(srcdstA) >> shift | ||
| 394 | |||
| 395 | #define Dbl_hiddenhigh3mantissa(dbl_value) Dhiddenhigh3mantissa(dbl_value) | ||
| 396 | #define Dbl_hidden(dbl_value) Dhidden(dbl_value) | ||
| 397 | #define Dbl_lowmantissap2(dbl_value) Dlowp2(dbl_value) | ||
| 398 | |||
| 399 | /* The left argument is never smaller than the right argument */ | ||
| 400 | #define Dbl_subtract(lefta,leftb,righta,rightb,resulta,resultb) \ | ||
| 401 | if( Dallp2(rightb) > Dallp2(leftb) ) Dallp1(lefta)--; \ | ||
| 402 | Dallp2(resultb) = Dallp2(leftb) - Dallp2(rightb); \ | ||
| 403 | Dallp1(resulta) = Dallp1(lefta) - Dallp1(righta) | ||
| 404 | |||
| 405 | /* Subtract right augmented with extension from left augmented with zeros and | ||
| 406 | * store into result and extension. */ | ||
| 407 | #define Dbl_subtract_withextension(lefta,leftb,righta,rightb,extent,resulta,resultb) \ | ||
| 408 | Dbl_subtract(lefta,leftb,righta,rightb,resulta,resultb); \ | ||
| 409 | if( (Extall(extent) = 0-Extall(extent)) ) \ | ||
| 410 | { \ | ||
| 411 | if((Dallp2(resultb)--) == 0) Dallp1(resulta)--; \ | ||
| 412 | } | ||
| 413 | |||
| 414 | #define Dbl_addition(lefta,leftb,righta,rightb,resulta,resultb) \ | ||
| 415 | /* If the sum of the low words is less than either source, then \ | ||
| 416 | * an overflow into the next word occurred. */ \ | ||
| 417 | Dallp1(resulta) = Dallp1(lefta) + Dallp1(righta); \ | ||
| 418 | if((Dallp2(resultb) = Dallp2(leftb) + Dallp2(rightb)) < Dallp2(rightb)) \ | ||
| 419 | Dallp1(resulta)++ | ||
| 420 | |||
| 421 | #define Dbl_xortointp1(left,right,result) \ | ||
| 422 | result = Dallp1(left) XOR Dallp1(right) | ||
| 423 | |||
| 424 | #define Dbl_xorfromintp1(left,right,result) \ | ||
| 425 | Dallp1(result) = left XOR Dallp1(right) | ||
| 426 | |||
| 427 | #define Dbl_swap_lower(left,right) \ | ||
| 428 | Dallp2(left) = Dallp2(left) XOR Dallp2(right); \ | ||
| 429 | Dallp2(right) = Dallp2(left) XOR Dallp2(right); \ | ||
| 430 | Dallp2(left) = Dallp2(left) XOR Dallp2(right) | ||
| 431 | |||
| 432 | /* Need to Initialize */ | ||
| 433 | #define Dbl_makequietnan(desta,destb) \ | ||
| 434 | Dallp1(desta) = ((DBL_EMAX+DBL_BIAS)+1)<< (32-(1+DBL_EXP_LENGTH)) \ | ||
| 435 | | (1<<(32-(1+DBL_EXP_LENGTH+2))); \ | ||
| 436 | Dallp2(destb) = 0 | ||
| 437 | #define Dbl_makesignalingnan(desta,destb) \ | ||
| 438 | Dallp1(desta) = ((DBL_EMAX+DBL_BIAS)+1)<< (32-(1+DBL_EXP_LENGTH)) \ | ||
| 439 | | (1<<(32-(1+DBL_EXP_LENGTH+1))); \ | ||
| 440 | Dallp2(destb) = 0 | ||
| 441 | |||
| 442 | #define Dbl_normalize(dbl_opndA,dbl_opndB,exponent) \ | ||
| 443 | while(Dbl_iszero_hiddenhigh7mantissa(dbl_opndA)) { \ | ||
| 444 | Dbl_leftshiftby8(dbl_opndA,dbl_opndB); \ | ||
| 445 | exponent -= 8; \ | ||
| 446 | } \ | ||
| 447 | if(Dbl_iszero_hiddenhigh3mantissa(dbl_opndA)) { \ | ||
| 448 | Dbl_leftshiftby4(dbl_opndA,dbl_opndB); \ | ||
| 449 | exponent -= 4; \ | ||
| 450 | } \ | ||
| 451 | while(Dbl_iszero_hidden(dbl_opndA)) { \ | ||
| 452 | Dbl_leftshiftby1(dbl_opndA,dbl_opndB); \ | ||
| 453 | exponent -= 1; \ | ||
| 454 | } | ||
| 455 | |||
| 456 | #define Twoword_add(src1dstA,src1dstB,src2A,src2B) \ | ||
| 457 | /* \ | ||
| 458 | * want this macro to generate: \ | ||
| 459 | * ADD src1dstB,src2B,src1dstB; \ | ||
| 460 | * ADDC src1dstA,src2A,src1dstA; \ | ||
| 461 | */ \ | ||
| 462 | if ((src1dstB) + (src2B) < (src1dstB)) Dallp1(src1dstA)++; \ | ||
| 463 | Dallp1(src1dstA) += (src2A); \ | ||
| 464 | Dallp2(src1dstB) += (src2B) | ||
| 465 | |||
| 466 | #define Twoword_subtract(src1dstA,src1dstB,src2A,src2B) \ | ||
| 467 | /* \ | ||
| 468 | * want this macro to generate: \ | ||
| 469 | * SUB src1dstB,src2B,src1dstB; \ | ||
| 470 | * SUBB src1dstA,src2A,src1dstA; \ | ||
| 471 | */ \ | ||
| 472 | if ((src1dstB) < (src2B)) Dallp1(src1dstA)--; \ | ||
| 473 | Dallp1(src1dstA) -= (src2A); \ | ||
| 474 | Dallp2(src1dstB) -= (src2B) | ||
| 475 | |||
| 476 | #define Dbl_setoverflow(resultA,resultB) \ | ||
| 477 | /* set result to infinity or largest number */ \ | ||
| 478 | switch (Rounding_mode()) { \ | ||
| 479 | case ROUNDPLUS: \ | ||
| 480 | if (Dbl_isone_sign(resultA)) { \ | ||
| 481 | Dbl_setlargestnegative(resultA,resultB); \ | ||
| 482 | } \ | ||
| 483 | else { \ | ||
| 484 | Dbl_setinfinitypositive(resultA,resultB); \ | ||
| 485 | } \ | ||
| 486 | break; \ | ||
| 487 | case ROUNDMINUS: \ | ||
| 488 | if (Dbl_iszero_sign(resultA)) { \ | ||
| 489 | Dbl_setlargestpositive(resultA,resultB); \ | ||
| 490 | } \ | ||
| 491 | else { \ | ||
| 492 | Dbl_setinfinitynegative(resultA,resultB); \ | ||
| 493 | } \ | ||
| 494 | break; \ | ||
| 495 | case ROUNDNEAREST: \ | ||
| 496 | Dbl_setinfinity_exponentmantissa(resultA,resultB); \ | ||
| 497 | break; \ | ||
| 498 | case ROUNDZERO: \ | ||
| 499 | Dbl_setlargest_exponentmantissa(resultA,resultB); \ | ||
| 500 | } | ||
| 501 | |||
| 502 | #define Dbl_denormalize(opndp1,opndp2,exponent,guard,sticky,inexact) \ | ||
| 503 | Dbl_clear_signexponent_set_hidden(opndp1); \ | ||
| 504 | if (exponent >= (1-DBL_P)) { \ | ||
| 505 | if (exponent >= -31) { \ | ||
| 506 | guard = (Dallp2(opndp2) >> -exponent) & 1; \ | ||
| 507 | if (exponent < 0) sticky |= Dallp2(opndp2) << (32+exponent); \ | ||
| 508 | if (exponent > -31) { \ | ||
| 509 | Variable_shift_double(opndp1,opndp2,1-exponent,opndp2); \ | ||
| 510 | Dallp1(opndp1) >>= 1-exponent; \ | ||
| 511 | } \ | ||
| 512 | else { \ | ||
| 513 | Dallp2(opndp2) = Dallp1(opndp1); \ | ||
| 514 | Dbl_setzerop1(opndp1); \ | ||
| 515 | } \ | ||
| 516 | } \ | ||
| 517 | else { \ | ||
| 518 | guard = (Dallp1(opndp1) >> -32-exponent) & 1; \ | ||
| 519 | if (exponent == -32) sticky |= Dallp2(opndp2); \ | ||
| 520 | else sticky |= (Dallp2(opndp2) | Dallp1(opndp1) << 64+exponent); \ | ||
| 521 | Dallp2(opndp2) = Dallp1(opndp1) >> -31-exponent; \ | ||
| 522 | Dbl_setzerop1(opndp1); \ | ||
| 523 | } \ | ||
| 524 | inexact = guard | sticky; \ | ||
| 525 | } \ | ||
| 526 | else { \ | ||
| 527 | guard = 0; \ | ||
| 528 | sticky |= (Dallp1(opndp1) | Dallp2(opndp2)); \ | ||
| 529 | Dbl_setzero(opndp1,opndp2); \ | ||
| 530 | inexact = sticky; \ | ||
| 531 | } | ||
| 532 | |||
| 533 | /* | ||
| 534 | * The fused multiply add instructions requires a double extended format, | ||
| 535 | * with 106 bits of mantissa. | ||
| 536 | */ | ||
| 537 | #define DBLEXT_THRESHOLD 106 | ||
| 538 | |||
| 539 | #define Dblext_setzero(valA,valB,valC,valD) \ | ||
| 540 | Dextallp1(valA) = 0; Dextallp2(valB) = 0; \ | ||
| 541 | Dextallp3(valC) = 0; Dextallp4(valD) = 0 | ||
| 542 | |||
| 543 | |||
| 544 | #define Dblext_isnotzero_mantissap3(valC) (Dextallp3(valC)!=0) | ||
| 545 | #define Dblext_isnotzero_mantissap4(valD) (Dextallp3(valD)!=0) | ||
| 546 | #define Dblext_isone_lowp2(val) (Dextlowp2(val)!=0) | ||
| 547 | #define Dblext_isone_highp3(val) (Dexthighp3(val)!=0) | ||
| 548 | #define Dblext_isnotzero_low31p3(val) (Dextlow31p3(val)!=0) | ||
| 549 | #define Dblext_iszero(valA,valB,valC,valD) (Dextallp1(valA)==0 && \ | ||
| 550 | Dextallp2(valB)==0 && Dextallp3(valC)==0 && Dextallp4(valD)==0) | ||
| 551 | |||
| 552 | #define Dblext_copy(srca,srcb,srcc,srcd,desta,destb,destc,destd) \ | ||
| 553 | Dextallp1(desta) = Dextallp4(srca); \ | ||
| 554 | Dextallp2(destb) = Dextallp4(srcb); \ | ||
| 555 | Dextallp3(destc) = Dextallp4(srcc); \ | ||
| 556 | Dextallp4(destd) = Dextallp4(srcd) | ||
| 557 | |||
| 558 | #define Dblext_swap_lower(leftp2,leftp3,leftp4,rightp2,rightp3,rightp4) \ | ||
| 559 | Dextallp2(leftp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \ | ||
| 560 | Dextallp2(rightp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \ | ||
| 561 | Dextallp2(leftp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2); \ | ||
| 562 | Dextallp3(leftp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \ | ||
| 563 | Dextallp3(rightp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \ | ||
| 564 | Dextallp3(leftp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3); \ | ||
| 565 | Dextallp4(leftp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4); \ | ||
| 566 | Dextallp4(rightp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4); \ | ||
| 567 | Dextallp4(leftp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4) | ||
| 568 | |||
| 569 | #define Dblext_setone_lowmantissap4(dbl_value) Deposit_dextlowp4(dbl_value,1) | ||
| 570 | |||
| 571 | /* The high bit is always zero so arithmetic or logical shifts will work. */ | ||
| 572 | #define Dblext_right_align(srcdstA,srcdstB,srcdstC,srcdstD,shift) \ | ||
| 573 | {int shiftamt, sticky; \ | ||
| 574 | shiftamt = shift % 32; \ | ||
| 575 | sticky = 0; \ | ||
| 576 | switch (shift/32) { \ | ||
| 577 | case 0: if (shiftamt > 0) { \ | ||
| 578 | sticky = Dextallp4(srcdstD) << 32 - (shiftamt); \ | ||
| 579 | Variable_shift_double(Dextallp3(srcdstC), \ | ||
| 580 | Dextallp4(srcdstD),shiftamt,Dextallp4(srcdstD)); \ | ||
| 581 | Variable_shift_double(Dextallp2(srcdstB), \ | ||
| 582 | Dextallp3(srcdstC),shiftamt,Dextallp3(srcdstC)); \ | ||
| 583 | Variable_shift_double(Dextallp1(srcdstA), \ | ||
| 584 | Dextallp2(srcdstB),shiftamt,Dextallp2(srcdstB)); \ | ||
| 585 | Dextallp1(srcdstA) >>= shiftamt; \ | ||
| 586 | } \ | ||
| 587 | break; \ | ||
| 588 | case 1: if (shiftamt > 0) { \ | ||
| 589 | sticky = (Dextallp3(srcdstC) << 31 - shiftamt) | \ | ||
| 590 | Dextallp4(srcdstD); \ | ||
| 591 | Variable_shift_double(Dextallp2(srcdstB), \ | ||
| 592 | Dextallp3(srcdstC),shiftamt,Dextallp4(srcdstD)); \ | ||
| 593 | Variable_shift_double(Dextallp1(srcdstA), \ | ||
| 594 | Dextallp2(srcdstB),shiftamt,Dextallp3(srcdstC)); \ | ||
| 595 | } \ | ||
| 596 | else { \ | ||
| 597 | sticky = Dextallp4(srcdstD); \ | ||
| 598 | Dextallp4(srcdstD) = Dextallp3(srcdstC); \ | ||
| 599 | Dextallp3(srcdstC) = Dextallp2(srcdstB); \ | ||
| 600 | } \ | ||
| 601 | Dextallp2(srcdstB) = Dextallp1(srcdstA) >> shiftamt; \ | ||
| 602 | Dextallp1(srcdstA) = 0; \ | ||
| 603 | break; \ | ||
| 604 | case 2: if (shiftamt > 0) { \ | ||
| 605 | sticky = (Dextallp2(srcdstB) << 31 - shiftamt) | \ | ||
| 606 | Dextallp3(srcdstC) | Dextallp4(srcdstD); \ | ||
| 607 | Variable_shift_double(Dextallp1(srcdstA), \ | ||
| 608 | Dextallp2(srcdstB),shiftamt,Dextallp4(srcdstD)); \ | ||
| 609 | } \ | ||
| 610 | else { \ | ||
| 611 | sticky = Dextallp3(srcdstC) | Dextallp4(srcdstD); \ | ||
| 612 | Dextallp4(srcdstD) = Dextallp2(srcdstB); \ | ||
| 613 | } \ | ||
| 614 | Dextallp3(srcdstC) = Dextallp1(srcdstA) >> shiftamt; \ | ||
| 615 | Dextallp1(srcdstA) = Dextallp2(srcdstB) = 0; \ | ||
| 616 | break; \ | ||
| 617 | case 3: if (shiftamt > 0) { \ | ||
| 618 | sticky = (Dextallp1(srcdstA) << 31 - shiftamt) | \ | ||
| 619 | Dextallp2(srcdstB) | Dextallp3(srcdstC) | \ | ||
| 620 | Dextallp4(srcdstD); \ | ||
| 621 | } \ | ||
| 622 | else { \ | ||
| 623 | sticky = Dextallp2(srcdstB) | Dextallp3(srcdstC) | \ | ||
| 624 | Dextallp4(srcdstD); \ | ||
| 625 | } \ | ||
| 626 | Dextallp4(srcdstD) = Dextallp1(srcdstA) >> shiftamt; \ | ||
| 627 | Dextallp1(srcdstA) = Dextallp2(srcdstB) = 0; \ | ||
| 628 | Dextallp3(srcdstC) = 0; \ | ||
| 629 | break; \ | ||
| 630 | } \ | ||
| 631 | if (sticky) Dblext_setone_lowmantissap4(srcdstD); \ | ||
| 632 | } | ||
| 633 | |||
| 634 | /* The left argument is never smaller than the right argument */ | ||
| 635 | #define Dblext_subtract(lefta,leftb,leftc,leftd,righta,rightb,rightc,rightd,resulta,resultb,resultc,resultd) \ | ||
| 636 | if( Dextallp4(rightd) > Dextallp4(leftd) ) \ | ||
| 637 | if( (Dextallp3(leftc)--) == 0) \ | ||
| 638 | if( (Dextallp2(leftb)--) == 0) Dextallp1(lefta)--; \ | ||
| 639 | Dextallp4(resultd) = Dextallp4(leftd) - Dextallp4(rightd); \ | ||
| 640 | if( Dextallp3(rightc) > Dextallp3(leftc) ) \ | ||
| 641 | if( (Dextallp2(leftb)--) == 0) Dextallp1(lefta)--; \ | ||
| 642 | Dextallp3(resultc) = Dextallp3(leftc) - Dextallp3(rightc); \ | ||
| 643 | if( Dextallp2(rightb) > Dextallp2(leftb) ) Dextallp1(lefta)--; \ | ||
| 644 | Dextallp2(resultb) = Dextallp2(leftb) - Dextallp2(rightb); \ | ||
| 645 | Dextallp1(resulta) = Dextallp1(lefta) - Dextallp1(righta) | ||
| 646 | |||
| 647 | #define Dblext_addition(lefta,leftb,leftc,leftd,righta,rightb,rightc,rightd,resulta,resultb,resultc,resultd) \ | ||
| 648 | /* If the sum of the low words is less than either source, then \ | ||
| 649 | * an overflow into the next word occurred. */ \ | ||
| 650 | if ((Dextallp4(resultd) = Dextallp4(leftd)+Dextallp4(rightd)) < \ | ||
| 651 | Dextallp4(rightd)) \ | ||
| 652 | if((Dextallp3(resultc) = Dextallp3(leftc)+Dextallp3(rightc)+1) <= \ | ||
| 653 | Dextallp3(rightc)) \ | ||
| 654 | if((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)+1) \ | ||
| 655 | <= Dextallp2(rightb)) \ | ||
| 656 | Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \ | ||
| 657 | else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \ | ||
| 658 | else \ | ||
| 659 | if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)) < \ | ||
| 660 | Dextallp2(rightb)) \ | ||
| 661 | Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \ | ||
| 662 | else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \ | ||
| 663 | else \ | ||
| 664 | if ((Dextallp3(resultc) = Dextallp3(leftc)+Dextallp3(rightc)) < \ | ||
| 665 | Dextallp3(rightc)) \ | ||
| 666 | if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)+1) \ | ||
| 667 | <= Dextallp2(rightb)) \ | ||
| 668 | Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \ | ||
| 669 | else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \ | ||
| 670 | else \ | ||
| 671 | if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)) < \ | ||
| 672 | Dextallp2(rightb)) \ | ||
| 673 | Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \ | ||
| 674 | else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta) | ||
| 675 | |||
| 676 | |||
| 677 | #define Dblext_arithrightshiftby1(srcdstA,srcdstB,srcdstC,srcdstD) \ | ||
| 678 | Shiftdouble(Dextallp3(srcdstC),Dextallp4(srcdstD),1,Dextallp4(srcdstD)); \ | ||
| 679 | Shiftdouble(Dextallp2(srcdstB),Dextallp3(srcdstC),1,Dextallp3(srcdstC)); \ | ||
| 680 | Shiftdouble(Dextallp1(srcdstA),Dextallp2(srcdstB),1,Dextallp2(srcdstB)); \ | ||
| 681 | Dextallp1(srcdstA) = (int)Dextallp1(srcdstA) >> 1 | ||
| 682 | |||
| 683 | #define Dblext_leftshiftby8(valA,valB,valC,valD) \ | ||
| 684 | Shiftdouble(Dextallp1(valA),Dextallp2(valB),24,Dextallp1(valA)); \ | ||
| 685 | Shiftdouble(Dextallp2(valB),Dextallp3(valC),24,Dextallp2(valB)); \ | ||
| 686 | Shiftdouble(Dextallp3(valC),Dextallp4(valD),24,Dextallp3(valC)); \ | ||
| 687 | Dextallp4(valD) <<= 8 | ||
| 688 | #define Dblext_leftshiftby4(valA,valB,valC,valD) \ | ||
| 689 | Shiftdouble(Dextallp1(valA),Dextallp2(valB),28,Dextallp1(valA)); \ | ||
| 690 | Shiftdouble(Dextallp2(valB),Dextallp3(valC),28,Dextallp2(valB)); \ | ||
| 691 | Shiftdouble(Dextallp3(valC),Dextallp4(valD),28,Dextallp3(valC)); \ | ||
| 692 | Dextallp4(valD) <<= 4 | ||
| 693 | #define Dblext_leftshiftby3(valA,valB,valC,valD) \ | ||
| 694 | Shiftdouble(Dextallp1(valA),Dextallp2(valB),29,Dextallp1(valA)); \ | ||
| 695 | Shiftdouble(Dextallp2(valB),Dextallp3(valC),29,Dextallp2(valB)); \ | ||
| 696 | Shiftdouble(Dextallp3(valC),Dextallp4(valD),29,Dextallp3(valC)); \ | ||
| 697 | Dextallp4(valD) <<= 3 | ||
| 698 | #define Dblext_leftshiftby2(valA,valB,valC,valD) \ | ||
| 699 | Shiftdouble(Dextallp1(valA),Dextallp2(valB),30,Dextallp1(valA)); \ | ||
| 700 | Shiftdouble(Dextallp2(valB),Dextallp3(valC),30,Dextallp2(valB)); \ | ||
| 701 | Shiftdouble(Dextallp3(valC),Dextallp4(valD),30,Dextallp3(valC)); \ | ||
| 702 | Dextallp4(valD) <<= 2 | ||
| 703 | #define Dblext_leftshiftby1(valA,valB,valC,valD) \ | ||
| 704 | Shiftdouble(Dextallp1(valA),Dextallp2(valB),31,Dextallp1(valA)); \ | ||
| 705 | Shiftdouble(Dextallp2(valB),Dextallp3(valC),31,Dextallp2(valB)); \ | ||
| 706 | Shiftdouble(Dextallp3(valC),Dextallp4(valD),31,Dextallp3(valC)); \ | ||
| 707 | Dextallp4(valD) <<= 1 | ||
| 708 | |||
| 709 | #define Dblext_rightshiftby4(valueA,valueB,valueC,valueD) \ | ||
| 710 | Shiftdouble(Dextallp3(valueC),Dextallp4(valueD),4,Dextallp4(valueD)); \ | ||
| 711 | Shiftdouble(Dextallp2(valueB),Dextallp3(valueC),4,Dextallp3(valueC)); \ | ||
| 712 | Shiftdouble(Dextallp1(valueA),Dextallp2(valueB),4,Dextallp2(valueB)); \ | ||
| 713 | Dextallp1(valueA) >>= 4 | ||
| 714 | #define Dblext_rightshiftby1(valueA,valueB,valueC,valueD) \ | ||
| 715 | Shiftdouble(Dextallp3(valueC),Dextallp4(valueD),1,Dextallp4(valueD)); \ | ||
| 716 | Shiftdouble(Dextallp2(valueB),Dextallp3(valueC),1,Dextallp3(valueC)); \ | ||
| 717 | Shiftdouble(Dextallp1(valueA),Dextallp2(valueB),1,Dextallp2(valueB)); \ | ||
| 718 | Dextallp1(valueA) >>= 1 | ||
| 719 | |||
| 720 | #define Dblext_xortointp1(left,right,result) Dbl_xortointp1(left,right,result) | ||
| 721 | |||
| 722 | #define Dblext_xorfromintp1(left,right,result) \ | ||
| 723 | Dbl_xorfromintp1(left,right,result) | ||
| 724 | |||
| 725 | #define Dblext_copytoint_exponentmantissap1(src,dest) \ | ||
| 726 | Dbl_copytoint_exponentmantissap1(src,dest) | ||
| 727 | |||
| 728 | #define Dblext_ismagnitudeless(leftB,rightB,signlessleft,signlessright) \ | ||
| 729 | Dbl_ismagnitudeless(leftB,rightB,signlessleft,signlessright) | ||
| 730 | |||
| 731 | #define Dbl_copyto_dblext(src1,src2,dest1,dest2,dest3,dest4) \ | ||
| 732 | Dextallp1(dest1) = Dallp1(src1); Dextallp2(dest2) = Dallp2(src2); \ | ||
| 733 | Dextallp3(dest3) = 0; Dextallp4(dest4) = 0 | ||
| 734 | |||
| 735 | #define Dblext_set_sign(dbl_value,sign) Dbl_set_sign(dbl_value,sign) | ||
| 736 | #define Dblext_clear_signexponent_set_hidden(srcdst) \ | ||
| 737 | Dbl_clear_signexponent_set_hidden(srcdst) | ||
| 738 | #define Dblext_clear_signexponent(srcdst) Dbl_clear_signexponent(srcdst) | ||
| 739 | #define Dblext_clear_sign(srcdst) Dbl_clear_sign(srcdst) | ||
| 740 | #define Dblext_isone_hidden(dbl_value) Dbl_isone_hidden(dbl_value) | ||
| 741 | |||
| 742 | /* | ||
| 743 | * The Fourword_add() macro assumes that integers are 4 bytes in size. | ||
| 744 | * It will break if this is not the case. | ||
| 745 | */ | ||
| 746 | |||
| 747 | #define Fourword_add(src1dstA,src1dstB,src1dstC,src1dstD,src2A,src2B,src2C,src2D) \ | ||
| 748 | /* \ | ||
| 749 | * want this macro to generate: \ | ||
| 750 | * ADD src1dstD,src2D,src1dstD; \ | ||
| 751 | * ADDC src1dstC,src2C,src1dstC; \ | ||
| 752 | * ADDC src1dstB,src2B,src1dstB; \ | ||
| 753 | * ADDC src1dstA,src2A,src1dstA; \ | ||
| 754 | */ \ | ||
| 755 | if ((unsigned int)(src1dstD += (src2D)) < (unsigned int)(src2D)) { \ | ||
| 756 | if ((unsigned int)(src1dstC += (src2C) + 1) <= \ | ||
| 757 | (unsigned int)(src2C)) { \ | ||
| 758 | if ((unsigned int)(src1dstB += (src2B) + 1) <= \ | ||
| 759 | (unsigned int)(src2B)) src1dstA++; \ | ||
| 760 | } \ | ||
| 761 | else if ((unsigned int)(src1dstB += (src2B)) < \ | ||
| 762 | (unsigned int)(src2B)) src1dstA++; \ | ||
| 763 | } \ | ||
| 764 | else { \ | ||
| 765 | if ((unsigned int)(src1dstC += (src2C)) < \ | ||
| 766 | (unsigned int)(src2C)) { \ | ||
| 767 | if ((unsigned int)(src1dstB += (src2B) + 1) <= \ | ||
| 768 | (unsigned int)(src2B)) src1dstA++; \ | ||
| 769 | } \ | ||
| 770 | else if ((unsigned int)(src1dstB += (src2B)) < \ | ||
| 771 | (unsigned int)(src2B)) src1dstA++; \ | ||
| 772 | } \ | ||
| 773 | src1dstA += (src2A) | ||
| 774 | |||
| 775 | #define Dblext_denormalize(opndp1,opndp2,opndp3,opndp4,exponent,is_tiny) \ | ||
| 776 | {int shiftamt, sticky; \ | ||
| 777 | is_tiny = TRUE; \ | ||
| 778 | if (exponent == 0 && (Dextallp3(opndp3) || Dextallp4(opndp4))) { \ | ||
| 779 | switch (Rounding_mode()) { \ | ||
| 780 | case ROUNDPLUS: \ | ||
| 781 | if (Dbl_iszero_sign(opndp1)) { \ | ||
| 782 | Dbl_increment(opndp1,opndp2); \ | ||
| 783 | if (Dbl_isone_hiddenoverflow(opndp1)) \ | ||
| 784 | is_tiny = FALSE; \ | ||
| 785 | Dbl_decrement(opndp1,opndp2); \ | ||
| 786 | } \ | ||
| 787 | break; \ | ||
| 788 | case ROUNDMINUS: \ | ||
| 789 | if (Dbl_isone_sign(opndp1)) { \ | ||
| 790 | Dbl_increment(opndp1,opndp2); \ | ||
| 791 | if (Dbl_isone_hiddenoverflow(opndp1)) \ | ||
| 792 | is_tiny = FALSE; \ | ||
| 793 | Dbl_decrement(opndp1,opndp2); \ | ||
| 794 | } \ | ||
| 795 | break; \ | ||
| 796 | case ROUNDNEAREST: \ | ||
| 797 | if (Dblext_isone_highp3(opndp3) && \ | ||
| 798 | (Dblext_isone_lowp2(opndp2) || \ | ||
| 799 | Dblext_isnotzero_low31p3(opndp3))) { \ | ||
| 800 | Dbl_increment(opndp1,opndp2); \ | ||
| 801 | if (Dbl_isone_hiddenoverflow(opndp1)) \ | ||
| 802 | is_tiny = FALSE; \ | ||
| 803 | Dbl_decrement(opndp1,opndp2); \ | ||
| 804 | } \ | ||
| 805 | break; \ | ||
| 806 | } \ | ||
| 807 | } \ | ||
| 808 | Dblext_clear_signexponent_set_hidden(opndp1); \ | ||
| 809 | if (exponent >= (1-QUAD_P)) { \ | ||
| 810 | shiftamt = (1-exponent) % 32; \ | ||
| 811 | switch((1-exponent)/32) { \ | ||
| 812 | case 0: sticky = Dextallp4(opndp4) << 32-(shiftamt); \ | ||
| 813 | Variableshiftdouble(opndp3,opndp4,shiftamt,opndp4); \ | ||
| 814 | Variableshiftdouble(opndp2,opndp3,shiftamt,opndp3); \ | ||
| 815 | Variableshiftdouble(opndp1,opndp2,shiftamt,opndp2); \ | ||
| 816 | Dextallp1(opndp1) >>= shiftamt; \ | ||
| 817 | break; \ | ||
| 818 | case 1: sticky = (Dextallp3(opndp3) << 32-(shiftamt)) | \ | ||
| 819 | Dextallp4(opndp4); \ | ||
| 820 | Variableshiftdouble(opndp2,opndp3,shiftamt,opndp4); \ | ||
| 821 | Variableshiftdouble(opndp1,opndp2,shiftamt,opndp3); \ | ||
| 822 | Dextallp2(opndp2) = Dextallp1(opndp1) >> shiftamt; \ | ||
| 823 | Dextallp1(opndp1) = 0; \ | ||
| 824 | break; \ | ||
| 825 | case 2: sticky = (Dextallp2(opndp2) << 32-(shiftamt)) | \ | ||
| 826 | Dextallp3(opndp3) | Dextallp4(opndp4); \ | ||
| 827 | Variableshiftdouble(opndp1,opndp2,shiftamt,opndp4); \ | ||
| 828 | Dextallp3(opndp3) = Dextallp1(opndp1) >> shiftamt; \ | ||
| 829 | Dextallp1(opndp1) = Dextallp2(opndp2) = 0; \ | ||
| 830 | break; \ | ||
| 831 | case 3: sticky = (Dextallp1(opndp1) << 32-(shiftamt)) | \ | ||
| 832 | Dextallp2(opndp2) | Dextallp3(opndp3) | \ | ||
| 833 | Dextallp4(opndp4); \ | ||
| 834 | Dextallp4(opndp4) = Dextallp1(opndp1) >> shiftamt; \ | ||
| 835 | Dextallp1(opndp1) = Dextallp2(opndp2) = 0; \ | ||
| 836 | Dextallp3(opndp3) = 0; \ | ||
| 837 | break; \ | ||
| 838 | } \ | ||
| 839 | } \ | ||
| 840 | else { \ | ||
| 841 | sticky = Dextallp1(opndp1) | Dextallp2(opndp2) | \ | ||
| 842 | Dextallp3(opndp3) | Dextallp4(opndp4); \ | ||
| 843 | Dblext_setzero(opndp1,opndp2,opndp3,opndp4); \ | ||
| 844 | } \ | ||
| 845 | if (sticky) Dblext_setone_lowmantissap4(opndp4); \ | ||
| 846 | exponent = 0; \ | ||
| 847 | } | ||
diff --git a/arch/parisc/math-emu/decode_exc.c b/arch/parisc/math-emu/decode_exc.c new file mode 100644 index 000000000000..f84f2586672b --- /dev/null +++ b/arch/parisc/math-emu/decode_exc.c | |||
| @@ -0,0 +1,368 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/fp/decode_exc.c $ Revision: $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * <<please update with a synopsis of the functionality provided by this file>> | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * <<the following list was autogenerated, please review>> | ||
| 32 | * decode_fpu(Fpu_register, trap_counts) | ||
| 33 | * | ||
| 34 | * Internal Interfaces: | ||
| 35 | * <<please update>> | ||
| 36 | * | ||
| 37 | * Theory: | ||
| 38 | * <<please update with a overview of the operation of this file>> | ||
| 39 | * | ||
| 40 | * END_DESC | ||
| 41 | */ | ||
| 42 | |||
| 43 | |||
| 44 | #include "float.h" | ||
| 45 | #include "sgl_float.h" | ||
| 46 | #include "dbl_float.h" | ||
| 47 | #include "cnv_float.h" | ||
| 48 | /* #include "types.h" */ | ||
| 49 | #include <asm/signal.h> | ||
| 50 | #include <asm/siginfo.h> | ||
| 51 | /* #include <machine/sys/mdep_private.h> */ | ||
| 52 | |||
| 53 | #undef Fpustatus_register | ||
| 54 | #define Fpustatus_register Fpu_register[0] | ||
| 55 | |||
| 56 | /* General definitions */ | ||
| 57 | #define DOESTRAP 1 | ||
| 58 | #define NOTRAP 0 | ||
| 59 | #define SIGNALCODE(signal, code) ((signal) << 24 | (code)); | ||
| 60 | #define copropbit 1<<31-2 /* bit position 2 */ | ||
| 61 | #define opclass 9 /* bits 21 & 22 */ | ||
| 62 | #define fmt 11 /* bits 19 & 20 */ | ||
| 63 | #define df 13 /* bits 17 & 18 */ | ||
| 64 | #define twobits 3 /* mask low-order 2 bits */ | ||
| 65 | #define fivebits 31 /* mask low-order 5 bits */ | ||
| 66 | #define MAX_EXCP_REG 7 /* number of excpeption registers to check */ | ||
| 67 | |||
| 68 | /* Exception register definitions */ | ||
| 69 | #define Excp_type(index) Exceptiontype(Fpu_register[index]) | ||
| 70 | #define Excp_instr(index) Instructionfield(Fpu_register[index]) | ||
| 71 | #define Clear_excp_register(index) Allexception(Fpu_register[index]) = 0 | ||
| 72 | #define Excp_format() \ | ||
| 73 | (current_ir >> ((current_ir>>opclass & twobits)==1 ? df : fmt) & twobits) | ||
| 74 | |||
| 75 | /* Miscellaneous definitions */ | ||
| 76 | #define Fpu_sgl(index) Fpu_register[index*2] | ||
| 77 | |||
| 78 | #define Fpu_dblp1(index) Fpu_register[index*2] | ||
| 79 | #define Fpu_dblp2(index) Fpu_register[(index*2)+1] | ||
| 80 | |||
| 81 | #define Fpu_quadp1(index) Fpu_register[index*2] | ||
| 82 | #define Fpu_quadp2(index) Fpu_register[(index*2)+1] | ||
| 83 | #define Fpu_quadp3(index) Fpu_register[(index*2)+2] | ||
| 84 | #define Fpu_quadp4(index) Fpu_register[(index*2)+3] | ||
| 85 | |||
| 86 | /* Single precision floating-point definitions */ | ||
| 87 | #ifndef Sgl_decrement | ||
| 88 | # define Sgl_decrement(sgl_value) Sall(sgl_value)-- | ||
| 89 | #endif | ||
| 90 | |||
| 91 | /* Double precision floating-point definitions */ | ||
| 92 | #ifndef Dbl_decrement | ||
| 93 | # define Dbl_decrement(dbl_valuep1,dbl_valuep2) \ | ||
| 94 | if ((Dallp2(dbl_valuep2)--) == 0) Dallp1(dbl_valuep1)-- | ||
| 95 | #endif | ||
| 96 | |||
| 97 | |||
| 98 | #define update_trap_counts(Fpu_register, aflags, bflags, trap_counts) { \ | ||
| 99 | aflags=(Fpu_register[0])>>27; /* assumes zero fill. 32 bit */ \ | ||
| 100 | Fpu_register[0] |= bflags; \ | ||
| 101 | } | ||
| 102 | |||
| 103 | u_int | ||
| 104 | decode_fpu(unsigned int Fpu_register[], unsigned int trap_counts[]) | ||
| 105 | { | ||
| 106 | unsigned int current_ir, excp; | ||
| 107 | int target, exception_index = 1; | ||
| 108 | boolean inexact; | ||
| 109 | unsigned int aflags; | ||
| 110 | unsigned int bflags; | ||
| 111 | unsigned int excptype; | ||
| 112 | |||
| 113 | |||
| 114 | /* Keep stats on how many floating point exceptions (based on type) | ||
| 115 | * that happen. Want to keep this overhead low, but still provide | ||
| 116 | * some information to the customer. All exits from this routine | ||
| 117 | * need to restore Fpu_register[0] | ||
| 118 | */ | ||
| 119 | |||
| 120 | bflags=(Fpu_register[0] & 0xf8000000); | ||
| 121 | Fpu_register[0] &= 0x07ffffff; | ||
| 122 | |||
| 123 | /* exception_index is used to index the exception register queue. It | ||
| 124 | * always points at the last register that contains a valid exception. A | ||
| 125 | * zero value implies no exceptions (also the initialized value). Setting | ||
| 126 | * the T-bit resets the exception_index to zero. | ||
| 127 | */ | ||
| 128 | |||
| 129 | /* | ||
| 130 | * Check for reserved-op exception. A reserved-op exception does not | ||
| 131 | * set any exception registers nor does it set the T-bit. If the T-bit | ||
| 132 | * is not set then a reserved-op exception occurred. | ||
| 133 | * | ||
| 134 | * At some point, we may want to report reserved op exceptions as | ||
| 135 | * illegal instructions. | ||
| 136 | */ | ||
| 137 | |||
| 138 | if (!Is_tbit_set()) { | ||
| 139 | update_trap_counts(Fpu_register, aflags, bflags, trap_counts); | ||
| 140 | return SIGNALCODE(SIGILL, ILL_COPROC); | ||
| 141 | } | ||
| 142 | |||
| 143 | /* | ||
| 144 | * Is a coprocessor op. | ||
| 145 | * | ||
| 146 | * Now we need to determine what type of exception occurred. | ||
| 147 | */ | ||
| 148 | for (exception_index=1; exception_index<=MAX_EXCP_REG; exception_index++) { | ||
| 149 | current_ir = Excp_instr(exception_index); | ||
| 150 | /* | ||
| 151 | * On PA89: there are 5 different unimplemented exception | ||
| 152 | * codes: 0x1, 0x9, 0xb, 0x3, and 0x23. PA-RISC 2.0 adds | ||
| 153 | * another, 0x2b. Only these have the low order bit set. | ||
| 154 | */ | ||
| 155 | excptype = Excp_type(exception_index); | ||
| 156 | if (excptype & UNIMPLEMENTEDEXCEPTION) { | ||
| 157 | /* | ||
| 158 | * Clear T-bit and exception register so that | ||
| 159 | * we can tell if a trap really occurs while | ||
| 160 | * emulating the instruction. | ||
| 161 | */ | ||
| 162 | Clear_tbit(); | ||
| 163 | Clear_excp_register(exception_index); | ||
| 164 | /* | ||
| 165 | * Now emulate this instruction. If a trap occurs, | ||
| 166 | * fpudispatch will return a non-zero number | ||
| 167 | */ | ||
| 168 | excp = fpudispatch(current_ir,excptype,0,Fpu_register); | ||
| 169 | /* accumulate the status flags, don't lose them as in hpux */ | ||
| 170 | if (excp) { | ||
| 171 | /* | ||
| 172 | * We now need to make sure that the T-bit and the | ||
| 173 | * exception register contain the correct values | ||
| 174 | * before continuing. | ||
| 175 | */ | ||
| 176 | /* | ||
| 177 | * Set t-bit since it might still be needed for a | ||
| 178 | * subsequent real trap (I don't understand fully -PB) | ||
| 179 | */ | ||
| 180 | Set_tbit(); | ||
| 181 | /* some of the following code uses | ||
| 182 | * Excp_type(exception_index) so fix that up */ | ||
| 183 | Set_exceptiontype_and_instr_field(excp,current_ir, | ||
| 184 | Fpu_register[exception_index]); | ||
| 185 | if (excp == UNIMPLEMENTEDEXCEPTION) { | ||
| 186 | /* | ||
| 187 | * it is really unimplemented, so restore the | ||
| 188 | * TIMEX extended unimplemented exception code | ||
| 189 | */ | ||
| 190 | excp = excptype; | ||
| 191 | update_trap_counts(Fpu_register, aflags, bflags, | ||
| 192 | trap_counts); | ||
| 193 | return SIGNALCODE(SIGILL, ILL_COPROC); | ||
| 194 | } | ||
| 195 | /* some of the following code uses excptype, so | ||
| 196 | * fix that up too */ | ||
| 197 | excptype = excp; | ||
| 198 | } | ||
| 199 | /* handle exceptions other than the real UNIMPLIMENTED the | ||
| 200 | * same way as if the hardware had caused them */ | ||
| 201 | if (excp == NOEXCEPTION) | ||
| 202 | /* For now use 'break', should technically be 'continue' */ | ||
| 203 | break; | ||
| 204 | } | ||
| 205 | |||
| 206 | /* | ||
| 207 | * In PA89, the underflow exception has been extended to encode | ||
| 208 | * additional information. The exception looks like pp01x0, | ||
| 209 | * where x is 1 if inexact and pp represent the inexact bit (I) | ||
| 210 | * and the round away bit (RA) | ||
| 211 | */ | ||
| 212 | if (excptype & UNDERFLOWEXCEPTION) { | ||
| 213 | /* check for underflow trap enabled */ | ||
| 214 | if (Is_underflowtrap_enabled()) { | ||
| 215 | update_trap_counts(Fpu_register, aflags, bflags, | ||
| 216 | trap_counts); | ||
| 217 | return SIGNALCODE(SIGFPE, FPE_FLTUND); | ||
| 218 | } else { | ||
| 219 | /* | ||
| 220 | * Isn't a real trap; we need to | ||
| 221 | * return the default value. | ||
| 222 | */ | ||
| 223 | target = current_ir & fivebits; | ||
| 224 | #ifndef lint | ||
| 225 | if (Ibit(Fpu_register[exception_index])) inexact = TRUE; | ||
| 226 | else inexact = FALSE; | ||
| 227 | #endif | ||
| 228 | switch (Excp_format()) { | ||
| 229 | case SGL: | ||
| 230 | /* | ||
| 231 | * If ra (round-away) is set, will | ||
| 232 | * want to undo the rounding done | ||
| 233 | * by the hardware. | ||
| 234 | */ | ||
| 235 | if (Rabit(Fpu_register[exception_index])) | ||
| 236 | Sgl_decrement(Fpu_sgl(target)); | ||
| 237 | |||
| 238 | /* now denormalize */ | ||
| 239 | sgl_denormalize(&Fpu_sgl(target),&inexact,Rounding_mode()); | ||
| 240 | break; | ||
| 241 | case DBL: | ||
| 242 | /* | ||
| 243 | * If ra (round-away) is set, will | ||
| 244 | * want to undo the rounding done | ||
| 245 | * by the hardware. | ||
| 246 | */ | ||
| 247 | if (Rabit(Fpu_register[exception_index])) | ||
| 248 | Dbl_decrement(Fpu_dblp1(target),Fpu_dblp2(target)); | ||
| 249 | |||
| 250 | /* now denormalize */ | ||
| 251 | dbl_denormalize(&Fpu_dblp1(target),&Fpu_dblp2(target), | ||
| 252 | &inexact,Rounding_mode()); | ||
| 253 | break; | ||
| 254 | } | ||
| 255 | if (inexact) Set_underflowflag(); | ||
| 256 | /* | ||
| 257 | * Underflow can generate an inexact | ||
| 258 | * exception. If inexact trap is enabled, | ||
| 259 | * want to do an inexact trap, otherwise | ||
| 260 | * set inexact flag. | ||
| 261 | */ | ||
| 262 | if (inexact && Is_inexacttrap_enabled()) { | ||
| 263 | /* | ||
| 264 | * Set exception field of exception register | ||
| 265 | * to inexact, parm field to zero. | ||
| 266 | * Underflow bit should be cleared. | ||
| 267 | */ | ||
| 268 | Set_exceptiontype(Fpu_register[exception_index], | ||
| 269 | INEXACTEXCEPTION); | ||
| 270 | Set_parmfield(Fpu_register[exception_index],0); | ||
| 271 | update_trap_counts(Fpu_register, aflags, bflags, | ||
| 272 | trap_counts); | ||
| 273 | return SIGNALCODE(SIGFPE, FPE_FLTRES); | ||
| 274 | } | ||
| 275 | else { | ||
| 276 | /* | ||
| 277 | * Exception register needs to be cleared. | ||
| 278 | * Inexact flag needs to be set if inexact. | ||
| 279 | */ | ||
| 280 | Clear_excp_register(exception_index); | ||
| 281 | if (inexact) Set_inexactflag(); | ||
| 282 | } | ||
| 283 | } | ||
| 284 | continue; | ||
| 285 | } | ||
| 286 | switch(Excp_type(exception_index)) { | ||
| 287 | case OVERFLOWEXCEPTION: | ||
| 288 | case OVERFLOWEXCEPTION | INEXACTEXCEPTION: | ||
| 289 | /* check for overflow trap enabled */ | ||
| 290 | update_trap_counts(Fpu_register, aflags, bflags, | ||
| 291 | trap_counts); | ||
| 292 | if (Is_overflowtrap_enabled()) { | ||
| 293 | update_trap_counts(Fpu_register, aflags, bflags, | ||
| 294 | trap_counts); | ||
| 295 | return SIGNALCODE(SIGFPE, FPE_FLTOVF); | ||
| 296 | } else { | ||
| 297 | /* | ||
| 298 | * Isn't a real trap; we need to | ||
| 299 | * return the default value. | ||
| 300 | */ | ||
| 301 | target = current_ir & fivebits; | ||
| 302 | switch (Excp_format()) { | ||
| 303 | case SGL: | ||
| 304 | Sgl_setoverflow(Fpu_sgl(target)); | ||
| 305 | break; | ||
| 306 | case DBL: | ||
| 307 | Dbl_setoverflow(Fpu_dblp1(target),Fpu_dblp2(target)); | ||
| 308 | break; | ||
| 309 | } | ||
| 310 | Set_overflowflag(); | ||
| 311 | /* | ||
| 312 | * Overflow always generates an inexact | ||
| 313 | * exception. If inexact trap is enabled, | ||
| 314 | * want to do an inexact trap, otherwise | ||
| 315 | * set inexact flag. | ||
| 316 | */ | ||
| 317 | if (Is_inexacttrap_enabled()) { | ||
| 318 | /* | ||
| 319 | * Set exception field of exception | ||
| 320 | * register to inexact. Overflow | ||
| 321 | * bit should be cleared. | ||
| 322 | */ | ||
| 323 | Set_exceptiontype(Fpu_register[exception_index], | ||
| 324 | INEXACTEXCEPTION); | ||
| 325 | update_trap_counts(Fpu_register, aflags, bflags, | ||
| 326 | trap_counts); | ||
| 327 | return SIGNALCODE(SIGFPE, FPE_FLTRES); | ||
| 328 | } | ||
| 329 | else { | ||
| 330 | /* | ||
| 331 | * Exception register needs to be cleared. | ||
| 332 | * Inexact flag needs to be set. | ||
| 333 | */ | ||
| 334 | Clear_excp_register(exception_index); | ||
| 335 | Set_inexactflag(); | ||
| 336 | } | ||
| 337 | } | ||
| 338 | break; | ||
| 339 | case INVALIDEXCEPTION: | ||
| 340 | update_trap_counts(Fpu_register, aflags, bflags, trap_counts); | ||
| 341 | return SIGNALCODE(SIGFPE, FPE_FLTINV); | ||
| 342 | case DIVISIONBYZEROEXCEPTION: | ||
| 343 | update_trap_counts(Fpu_register, aflags, bflags, trap_counts); | ||
| 344 | return SIGNALCODE(SIGFPE, FPE_FLTDIV); | ||
| 345 | case INEXACTEXCEPTION: | ||
| 346 | update_trap_counts(Fpu_register, aflags, bflags, trap_counts); | ||
| 347 | return SIGNALCODE(SIGFPE, FPE_FLTRES); | ||
| 348 | default: | ||
| 349 | update_trap_counts(Fpu_register, aflags, bflags, trap_counts); | ||
| 350 | printk("%s(%d) Unknown FPU exception 0x%x\n", __FILE__, | ||
| 351 | __LINE__, Excp_type(exception_index)); | ||
| 352 | return SIGNALCODE(SIGILL, ILL_COPROC); | ||
| 353 | case NOEXCEPTION: /* no exception */ | ||
| 354 | /* | ||
| 355 | * Clear exception register in case | ||
| 356 | * other fields are non-zero. | ||
| 357 | */ | ||
| 358 | Clear_excp_register(exception_index); | ||
| 359 | break; | ||
| 360 | } | ||
| 361 | } | ||
| 362 | /* | ||
| 363 | * No real exceptions occurred. | ||
| 364 | */ | ||
| 365 | Clear_tbit(); | ||
| 366 | update_trap_counts(Fpu_register, aflags, bflags, trap_counts); | ||
| 367 | return(NOTRAP); | ||
| 368 | } | ||
diff --git a/arch/parisc/math-emu/denormal.c b/arch/parisc/math-emu/denormal.c new file mode 100644 index 000000000000..60687e13c34f --- /dev/null +++ b/arch/parisc/math-emu/denormal.c | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/fp/denormal.c $ Revision: $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * <<please update with a synopsis of the functionality provided by this file>> | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * <<the following list was autogenerated, please review>> | ||
| 32 | * dbl_denormalize(dbl_opndp1,dbl_opndp2,inexactflag,rmode) | ||
| 33 | * sgl_denormalize(sgl_opnd,inexactflag,rmode) | ||
| 34 | * | ||
| 35 | * Internal Interfaces: | ||
| 36 | * <<please update>> | ||
| 37 | * | ||
| 38 | * Theory: | ||
| 39 | * <<please update with a overview of the operation of this file>> | ||
| 40 | * | ||
| 41 | * END_DESC | ||
| 42 | */ | ||
| 43 | |||
| 44 | |||
| 45 | |||
| 46 | #include "float.h" | ||
| 47 | #include "sgl_float.h" | ||
| 48 | #include "dbl_float.h" | ||
| 49 | #include "hppa.h" | ||
| 50 | #include <linux/kernel.h> | ||
| 51 | /* #include <machine/sys/mdep_private.h> */ | ||
| 52 | |||
| 53 | #undef Fpustatus_register | ||
| 54 | #define Fpustatus_register Fpu_register[0] | ||
| 55 | |||
| 56 | void | ||
| 57 | sgl_denormalize(unsigned int *sgl_opnd, boolean *inexactflag, int rmode) | ||
| 58 | { | ||
| 59 | unsigned int opnd; | ||
| 60 | int sign, exponent; | ||
| 61 | boolean guardbit = FALSE, stickybit, inexact; | ||
| 62 | |||
| 63 | opnd = *sgl_opnd; | ||
| 64 | stickybit = *inexactflag; | ||
| 65 | exponent = Sgl_exponent(opnd) - SGL_WRAP; | ||
| 66 | sign = Sgl_sign(opnd); | ||
| 67 | Sgl_denormalize(opnd,exponent,guardbit,stickybit,inexact); | ||
| 68 | if (inexact) { | ||
| 69 | switch (rmode) { | ||
| 70 | case ROUNDPLUS: | ||
| 71 | if (sign == 0) { | ||
| 72 | Sgl_increment(opnd); | ||
| 73 | } | ||
| 74 | break; | ||
| 75 | case ROUNDMINUS: | ||
| 76 | if (sign != 0) { | ||
| 77 | Sgl_increment(opnd); | ||
| 78 | } | ||
| 79 | break; | ||
| 80 | case ROUNDNEAREST: | ||
| 81 | if (guardbit && (stickybit || | ||
| 82 | Sgl_isone_lowmantissa(opnd))) { | ||
| 83 | Sgl_increment(opnd); | ||
| 84 | } | ||
| 85 | break; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | Sgl_set_sign(opnd,sign); | ||
| 89 | *sgl_opnd = opnd; | ||
| 90 | *inexactflag = inexact; | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | |||
| 94 | void | ||
| 95 | dbl_denormalize(unsigned int *dbl_opndp1, | ||
| 96 | unsigned int * dbl_opndp2, | ||
| 97 | boolean *inexactflag, | ||
| 98 | int rmode) | ||
| 99 | { | ||
| 100 | unsigned int opndp1, opndp2; | ||
| 101 | int sign, exponent; | ||
| 102 | boolean guardbit = FALSE, stickybit, inexact; | ||
| 103 | |||
| 104 | opndp1 = *dbl_opndp1; | ||
| 105 | opndp2 = *dbl_opndp2; | ||
| 106 | stickybit = *inexactflag; | ||
| 107 | exponent = Dbl_exponent(opndp1) - DBL_WRAP; | ||
| 108 | sign = Dbl_sign(opndp1); | ||
| 109 | Dbl_denormalize(opndp1,opndp2,exponent,guardbit,stickybit,inexact); | ||
| 110 | if (inexact) { | ||
| 111 | switch (rmode) { | ||
| 112 | case ROUNDPLUS: | ||
| 113 | if (sign == 0) { | ||
| 114 | Dbl_increment(opndp1,opndp2); | ||
| 115 | } | ||
| 116 | break; | ||
| 117 | case ROUNDMINUS: | ||
| 118 | if (sign != 0) { | ||
| 119 | Dbl_increment(opndp1,opndp2); | ||
| 120 | } | ||
| 121 | break; | ||
| 122 | case ROUNDNEAREST: | ||
| 123 | if (guardbit && (stickybit || | ||
| 124 | Dbl_isone_lowmantissap2(opndp2))) { | ||
| 125 | Dbl_increment(opndp1,opndp2); | ||
| 126 | } | ||
| 127 | break; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | Dbl_set_sign(opndp1,sign); | ||
| 131 | *dbl_opndp1 = opndp1; | ||
| 132 | *dbl_opndp2 = opndp2; | ||
| 133 | *inexactflag = inexact; | ||
| 134 | return; | ||
| 135 | } | ||
diff --git a/arch/parisc/math-emu/dfadd.c b/arch/parisc/math-emu/dfadd.c new file mode 100644 index 000000000000..e147d7d3b0f4 --- /dev/null +++ b/arch/parisc/math-emu/dfadd.c | |||
| @@ -0,0 +1,524 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/dfadd.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Double_add: add two double precision values. | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * dbl_fadd(leftptr, rightptr, dstptr, status) | ||
| 32 | * | ||
| 33 | * Internal Interfaces: | ||
| 34 | * | ||
| 35 | * Theory: | ||
| 36 | * <<please update with a overview of the operation of this file>> | ||
| 37 | * | ||
| 38 | * END_DESC | ||
| 39 | */ | ||
| 40 | |||
| 41 | |||
| 42 | #include "float.h" | ||
| 43 | #include "dbl_float.h" | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Double_add: add two double precision values. | ||
| 47 | */ | ||
| 48 | dbl_fadd( | ||
| 49 | dbl_floating_point *leftptr, | ||
| 50 | dbl_floating_point *rightptr, | ||
| 51 | dbl_floating_point *dstptr, | ||
| 52 | unsigned int *status) | ||
| 53 | { | ||
| 54 | register unsigned int signless_upper_left, signless_upper_right, save; | ||
| 55 | register unsigned int leftp1, leftp2, rightp1, rightp2, extent; | ||
| 56 | register unsigned int resultp1 = 0, resultp2 = 0; | ||
| 57 | |||
| 58 | register int result_exponent, right_exponent, diff_exponent; | ||
| 59 | register int sign_save, jumpsize; | ||
| 60 | register boolean inexact = FALSE; | ||
| 61 | register boolean underflowtrap; | ||
| 62 | |||
| 63 | /* Create local copies of the numbers */ | ||
| 64 | Dbl_copyfromptr(leftptr,leftp1,leftp2); | ||
| 65 | Dbl_copyfromptr(rightptr,rightp1,rightp2); | ||
| 66 | |||
| 67 | /* A zero "save" helps discover equal operands (for later), * | ||
| 68 | * and is used in swapping operands (if needed). */ | ||
| 69 | Dbl_xortointp1(leftp1,rightp1,/*to*/save); | ||
| 70 | |||
| 71 | /* | ||
| 72 | * check first operand for NaN's or infinity | ||
| 73 | */ | ||
| 74 | if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT) | ||
| 75 | { | ||
| 76 | if (Dbl_iszero_mantissa(leftp1,leftp2)) | ||
| 77 | { | ||
| 78 | if (Dbl_isnotnan(rightp1,rightp2)) | ||
| 79 | { | ||
| 80 | if (Dbl_isinfinity(rightp1,rightp2) && save!=0) | ||
| 81 | { | ||
| 82 | /* | ||
| 83 | * invalid since operands are opposite signed infinity's | ||
| 84 | */ | ||
| 85 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 86 | Set_invalidflag(); | ||
| 87 | Dbl_makequietnan(resultp1,resultp2); | ||
| 88 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 89 | return(NOEXCEPTION); | ||
| 90 | } | ||
| 91 | /* | ||
| 92 | * return infinity | ||
| 93 | */ | ||
| 94 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
| 95 | return(NOEXCEPTION); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | else | ||
| 99 | { | ||
| 100 | /* | ||
| 101 | * is NaN; signaling or quiet? | ||
| 102 | */ | ||
| 103 | if (Dbl_isone_signaling(leftp1)) | ||
| 104 | { | ||
| 105 | /* trap if INVALIDTRAP enabled */ | ||
| 106 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 107 | /* make NaN quiet */ | ||
| 108 | Set_invalidflag(); | ||
| 109 | Dbl_set_quiet(leftp1); | ||
| 110 | } | ||
| 111 | /* | ||
| 112 | * is second operand a signaling NaN? | ||
| 113 | */ | ||
| 114 | else if (Dbl_is_signalingnan(rightp1)) | ||
| 115 | { | ||
| 116 | /* trap if INVALIDTRAP enabled */ | ||
| 117 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 118 | /* make NaN quiet */ | ||
| 119 | Set_invalidflag(); | ||
| 120 | Dbl_set_quiet(rightp1); | ||
| 121 | Dbl_copytoptr(rightp1,rightp2,dstptr); | ||
| 122 | return(NOEXCEPTION); | ||
| 123 | } | ||
| 124 | /* | ||
| 125 | * return quiet NaN | ||
| 126 | */ | ||
| 127 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
| 128 | return(NOEXCEPTION); | ||
| 129 | } | ||
| 130 | } /* End left NaN or Infinity processing */ | ||
| 131 | /* | ||
| 132 | * check second operand for NaN's or infinity | ||
| 133 | */ | ||
| 134 | if (Dbl_isinfinity_exponent(rightp1)) | ||
| 135 | { | ||
| 136 | if (Dbl_iszero_mantissa(rightp1,rightp2)) | ||
| 137 | { | ||
| 138 | /* return infinity */ | ||
| 139 | Dbl_copytoptr(rightp1,rightp2,dstptr); | ||
| 140 | return(NOEXCEPTION); | ||
| 141 | } | ||
| 142 | /* | ||
| 143 | * is NaN; signaling or quiet? | ||
| 144 | */ | ||
| 145 | if (Dbl_isone_signaling(rightp1)) | ||
| 146 | { | ||
| 147 | /* trap if INVALIDTRAP enabled */ | ||
| 148 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 149 | /* make NaN quiet */ | ||
| 150 | Set_invalidflag(); | ||
| 151 | Dbl_set_quiet(rightp1); | ||
| 152 | } | ||
| 153 | /* | ||
| 154 | * return quiet NaN | ||
| 155 | */ | ||
| 156 | Dbl_copytoptr(rightp1,rightp2,dstptr); | ||
| 157 | return(NOEXCEPTION); | ||
| 158 | } /* End right NaN or Infinity processing */ | ||
| 159 | |||
| 160 | /* Invariant: Must be dealing with finite numbers */ | ||
| 161 | |||
| 162 | /* Compare operands by removing the sign */ | ||
| 163 | Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left); | ||
| 164 | Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right); | ||
| 165 | |||
| 166 | /* sign difference selects add or sub operation. */ | ||
| 167 | if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right)) | ||
| 168 | { | ||
| 169 | /* Set the left operand to the larger one by XOR swap * | ||
| 170 | * First finish the first word using "save" */ | ||
| 171 | Dbl_xorfromintp1(save,rightp1,/*to*/rightp1); | ||
| 172 | Dbl_xorfromintp1(save,leftp1,/*to*/leftp1); | ||
| 173 | Dbl_swap_lower(leftp2,rightp2); | ||
| 174 | result_exponent = Dbl_exponent(leftp1); | ||
| 175 | } | ||
| 176 | /* Invariant: left is not smaller than right. */ | ||
| 177 | |||
| 178 | if((right_exponent = Dbl_exponent(rightp1)) == 0) | ||
| 179 | { | ||
| 180 | /* Denormalized operands. First look for zeroes */ | ||
| 181 | if(Dbl_iszero_mantissa(rightp1,rightp2)) | ||
| 182 | { | ||
| 183 | /* right is zero */ | ||
| 184 | if(Dbl_iszero_exponentmantissa(leftp1,leftp2)) | ||
| 185 | { | ||
| 186 | /* Both operands are zeros */ | ||
| 187 | if(Is_rounding_mode(ROUNDMINUS)) | ||
| 188 | { | ||
| 189 | Dbl_or_signs(leftp1,/*with*/rightp1); | ||
| 190 | } | ||
| 191 | else | ||
| 192 | { | ||
| 193 | Dbl_and_signs(leftp1,/*with*/rightp1); | ||
| 194 | } | ||
| 195 | } | ||
| 196 | else | ||
| 197 | { | ||
| 198 | /* Left is not a zero and must be the result. Trapped | ||
| 199 | * underflows are signaled if left is denormalized. Result | ||
| 200 | * is always exact. */ | ||
| 201 | if( (result_exponent == 0) && Is_underflowtrap_enabled() ) | ||
| 202 | { | ||
| 203 | /* need to normalize results mantissa */ | ||
| 204 | sign_save = Dbl_signextendedsign(leftp1); | ||
| 205 | Dbl_leftshiftby1(leftp1,leftp2); | ||
| 206 | Dbl_normalize(leftp1,leftp2,result_exponent); | ||
| 207 | Dbl_set_sign(leftp1,/*using*/sign_save); | ||
| 208 | Dbl_setwrapped_exponent(leftp1,result_exponent,unfl); | ||
| 209 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
| 210 | /* inexact = FALSE */ | ||
| 211 | return(UNDERFLOWEXCEPTION); | ||
| 212 | } | ||
| 213 | } | ||
| 214 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
| 215 | return(NOEXCEPTION); | ||
| 216 | } | ||
| 217 | |||
| 218 | /* Neither are zeroes */ | ||
| 219 | Dbl_clear_sign(rightp1); /* Exponent is already cleared */ | ||
| 220 | if(result_exponent == 0 ) | ||
| 221 | { | ||
| 222 | /* Both operands are denormalized. The result must be exact | ||
| 223 | * and is simply calculated. A sum could become normalized and a | ||
| 224 | * difference could cancel to a true zero. */ | ||
| 225 | if( (/*signed*/int) save < 0 ) | ||
| 226 | { | ||
| 227 | Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2, | ||
| 228 | /*into*/resultp1,resultp2); | ||
| 229 | if(Dbl_iszero_mantissa(resultp1,resultp2)) | ||
| 230 | { | ||
| 231 | if(Is_rounding_mode(ROUNDMINUS)) | ||
| 232 | { | ||
| 233 | Dbl_setone_sign(resultp1); | ||
| 234 | } | ||
| 235 | else | ||
| 236 | { | ||
| 237 | Dbl_setzero_sign(resultp1); | ||
| 238 | } | ||
| 239 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 240 | return(NOEXCEPTION); | ||
| 241 | } | ||
| 242 | } | ||
| 243 | else | ||
| 244 | { | ||
| 245 | Dbl_addition(leftp1,leftp2,rightp1,rightp2, | ||
| 246 | /*into*/resultp1,resultp2); | ||
| 247 | if(Dbl_isone_hidden(resultp1)) | ||
| 248 | { | ||
| 249 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 250 | return(NOEXCEPTION); | ||
| 251 | } | ||
| 252 | } | ||
| 253 | if(Is_underflowtrap_enabled()) | ||
| 254 | { | ||
| 255 | /* need to normalize result */ | ||
| 256 | sign_save = Dbl_signextendedsign(resultp1); | ||
| 257 | Dbl_leftshiftby1(resultp1,resultp2); | ||
| 258 | Dbl_normalize(resultp1,resultp2,result_exponent); | ||
| 259 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
| 260 | Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
| 261 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 262 | /* inexact = FALSE */ | ||
| 263 | return(UNDERFLOWEXCEPTION); | ||
| 264 | } | ||
| 265 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 266 | return(NOEXCEPTION); | ||
| 267 | } | ||
| 268 | right_exponent = 1; /* Set exponent to reflect different bias | ||
| 269 | * with denomalized numbers. */ | ||
| 270 | } | ||
| 271 | else | ||
| 272 | { | ||
| 273 | Dbl_clear_signexponent_set_hidden(rightp1); | ||
| 274 | } | ||
| 275 | Dbl_clear_exponent_set_hidden(leftp1); | ||
| 276 | diff_exponent = result_exponent - right_exponent; | ||
| 277 | |||
| 278 | /* | ||
| 279 | * Special case alignment of operands that would force alignment | ||
| 280 | * beyond the extent of the extension. A further optimization | ||
| 281 | * could special case this but only reduces the path length for this | ||
| 282 | * infrequent case. | ||
| 283 | */ | ||
| 284 | if(diff_exponent > DBL_THRESHOLD) | ||
| 285 | { | ||
| 286 | diff_exponent = DBL_THRESHOLD; | ||
| 287 | } | ||
| 288 | |||
| 289 | /* Align right operand by shifting to right */ | ||
| 290 | Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent, | ||
| 291 | /*and lower to*/extent); | ||
| 292 | |||
| 293 | /* Treat sum and difference of the operands separately. */ | ||
| 294 | if( (/*signed*/int) save < 0 ) | ||
| 295 | { | ||
| 296 | /* | ||
| 297 | * Difference of the two operands. Their can be no overflow. A | ||
| 298 | * borrow can occur out of the hidden bit and force a post | ||
| 299 | * normalization phase. | ||
| 300 | */ | ||
| 301 | Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2, | ||
| 302 | /*with*/extent,/*into*/resultp1,resultp2); | ||
| 303 | if(Dbl_iszero_hidden(resultp1)) | ||
| 304 | { | ||
| 305 | /* Handle normalization */ | ||
| 306 | /* A straight foward algorithm would now shift the result | ||
| 307 | * and extension left until the hidden bit becomes one. Not | ||
| 308 | * all of the extension bits need participate in the shift. | ||
| 309 | * Only the two most significant bits (round and guard) are | ||
| 310 | * needed. If only a single shift is needed then the guard | ||
| 311 | * bit becomes a significant low order bit and the extension | ||
| 312 | * must participate in the rounding. If more than a single | ||
| 313 | * shift is needed, then all bits to the right of the guard | ||
| 314 | * bit are zeros, and the guard bit may or may not be zero. */ | ||
| 315 | sign_save = Dbl_signextendedsign(resultp1); | ||
| 316 | Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2); | ||
| 317 | |||
| 318 | /* Need to check for a zero result. The sign and exponent | ||
| 319 | * fields have already been zeroed. The more efficient test | ||
| 320 | * of the full object can be used. | ||
| 321 | */ | ||
| 322 | if(Dbl_iszero(resultp1,resultp2)) | ||
| 323 | /* Must have been "x-x" or "x+(-x)". */ | ||
| 324 | { | ||
| 325 | if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1); | ||
| 326 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 327 | return(NOEXCEPTION); | ||
| 328 | } | ||
| 329 | result_exponent--; | ||
| 330 | /* Look to see if normalization is finished. */ | ||
| 331 | if(Dbl_isone_hidden(resultp1)) | ||
| 332 | { | ||
| 333 | if(result_exponent==0) | ||
| 334 | { | ||
| 335 | /* Denormalized, exponent should be zero. Left operand * | ||
| 336 | * was normalized, so extent (guard, round) was zero */ | ||
| 337 | goto underflow; | ||
| 338 | } | ||
| 339 | else | ||
| 340 | { | ||
| 341 | /* No further normalization is needed. */ | ||
| 342 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
| 343 | Ext_leftshiftby1(extent); | ||
| 344 | goto round; | ||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 348 | /* Check for denormalized, exponent should be zero. Left * | ||
| 349 | * operand was normalized, so extent (guard, round) was zero */ | ||
| 350 | if(!(underflowtrap = Is_underflowtrap_enabled()) && | ||
| 351 | result_exponent==0) goto underflow; | ||
| 352 | |||
| 353 | /* Shift extension to complete one bit of normalization and | ||
| 354 | * update exponent. */ | ||
| 355 | Ext_leftshiftby1(extent); | ||
| 356 | |||
| 357 | /* Discover first one bit to determine shift amount. Use a | ||
| 358 | * modified binary search. We have already shifted the result | ||
| 359 | * one position right and still not found a one so the remainder | ||
| 360 | * of the extension must be zero and simplifies rounding. */ | ||
| 361 | /* Scan bytes */ | ||
| 362 | while(Dbl_iszero_hiddenhigh7mantissa(resultp1)) | ||
| 363 | { | ||
| 364 | Dbl_leftshiftby8(resultp1,resultp2); | ||
| 365 | if((result_exponent -= 8) <= 0 && !underflowtrap) | ||
| 366 | goto underflow; | ||
| 367 | } | ||
| 368 | /* Now narrow it down to the nibble */ | ||
| 369 | if(Dbl_iszero_hiddenhigh3mantissa(resultp1)) | ||
| 370 | { | ||
| 371 | /* The lower nibble contains the normalizing one */ | ||
| 372 | Dbl_leftshiftby4(resultp1,resultp2); | ||
| 373 | if((result_exponent -= 4) <= 0 && !underflowtrap) | ||
| 374 | goto underflow; | ||
| 375 | } | ||
| 376 | /* Select case were first bit is set (already normalized) | ||
| 377 | * otherwise select the proper shift. */ | ||
| 378 | if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7) | ||
| 379 | { | ||
| 380 | /* Already normalized */ | ||
| 381 | if(result_exponent <= 0) goto underflow; | ||
| 382 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
| 383 | Dbl_set_exponent(resultp1,/*using*/result_exponent); | ||
| 384 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 385 | return(NOEXCEPTION); | ||
| 386 | } | ||
| 387 | Dbl_sethigh4bits(resultp1,/*using*/sign_save); | ||
| 388 | switch(jumpsize) | ||
| 389 | { | ||
| 390 | case 1: | ||
| 391 | { | ||
| 392 | Dbl_leftshiftby3(resultp1,resultp2); | ||
| 393 | result_exponent -= 3; | ||
| 394 | break; | ||
| 395 | } | ||
| 396 | case 2: | ||
| 397 | case 3: | ||
| 398 | { | ||
| 399 | Dbl_leftshiftby2(resultp1,resultp2); | ||
| 400 | result_exponent -= 2; | ||
| 401 | break; | ||
| 402 | } | ||
| 403 | case 4: | ||
| 404 | case 5: | ||
| 405 | case 6: | ||
| 406 | case 7: | ||
| 407 | { | ||
| 408 | Dbl_leftshiftby1(resultp1,resultp2); | ||
| 409 | result_exponent -= 1; | ||
| 410 | break; | ||
| 411 | } | ||
| 412 | } | ||
| 413 | if(result_exponent > 0) | ||
| 414 | { | ||
| 415 | Dbl_set_exponent(resultp1,/*using*/result_exponent); | ||
| 416 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 417 | return(NOEXCEPTION); /* Sign bit is already set */ | ||
| 418 | } | ||
| 419 | /* Fixup potential underflows */ | ||
| 420 | underflow: | ||
| 421 | if(Is_underflowtrap_enabled()) | ||
| 422 | { | ||
| 423 | Dbl_set_sign(resultp1,sign_save); | ||
| 424 | Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
| 425 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 426 | /* inexact = FALSE */ | ||
| 427 | return(UNDERFLOWEXCEPTION); | ||
| 428 | } | ||
| 429 | /* | ||
| 430 | * Since we cannot get an inexact denormalized result, | ||
| 431 | * we can now return. | ||
| 432 | */ | ||
| 433 | Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent); | ||
| 434 | Dbl_clear_signexponent(resultp1); | ||
| 435 | Dbl_set_sign(resultp1,sign_save); | ||
| 436 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 437 | return(NOEXCEPTION); | ||
| 438 | } /* end if(hidden...)... */ | ||
| 439 | /* Fall through and round */ | ||
| 440 | } /* end if(save < 0)... */ | ||
| 441 | else | ||
| 442 | { | ||
| 443 | /* Add magnitudes */ | ||
| 444 | Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2); | ||
| 445 | if(Dbl_isone_hiddenoverflow(resultp1)) | ||
| 446 | { | ||
| 447 | /* Prenormalization required. */ | ||
| 448 | Dbl_rightshiftby1_withextent(resultp2,extent,extent); | ||
| 449 | Dbl_arithrightshiftby1(resultp1,resultp2); | ||
| 450 | result_exponent++; | ||
| 451 | } /* end if hiddenoverflow... */ | ||
| 452 | } /* end else ...add magnitudes... */ | ||
| 453 | |||
| 454 | /* Round the result. If the extension is all zeros,then the result is | ||
| 455 | * exact. Otherwise round in the correct direction. No underflow is | ||
| 456 | * possible. If a postnormalization is necessary, then the mantissa is | ||
| 457 | * all zeros so no shift is needed. */ | ||
| 458 | round: | ||
| 459 | if(Ext_isnotzero(extent)) | ||
| 460 | { | ||
| 461 | inexact = TRUE; | ||
| 462 | switch(Rounding_mode()) | ||
| 463 | { | ||
| 464 | case ROUNDNEAREST: /* The default. */ | ||
| 465 | if(Ext_isone_sign(extent)) | ||
| 466 | { | ||
| 467 | /* at least 1/2 ulp */ | ||
| 468 | if(Ext_isnotzero_lower(extent) || | ||
| 469 | Dbl_isone_lowmantissap2(resultp2)) | ||
| 470 | { | ||
| 471 | /* either exactly half way and odd or more than 1/2ulp */ | ||
| 472 | Dbl_increment(resultp1,resultp2); | ||
| 473 | } | ||
| 474 | } | ||
| 475 | break; | ||
| 476 | |||
| 477 | case ROUNDPLUS: | ||
| 478 | if(Dbl_iszero_sign(resultp1)) | ||
| 479 | { | ||
| 480 | /* Round up positive results */ | ||
| 481 | Dbl_increment(resultp1,resultp2); | ||
| 482 | } | ||
| 483 | break; | ||
| 484 | |||
| 485 | case ROUNDMINUS: | ||
| 486 | if(Dbl_isone_sign(resultp1)) | ||
| 487 | { | ||
| 488 | /* Round down negative results */ | ||
| 489 | Dbl_increment(resultp1,resultp2); | ||
| 490 | } | ||
| 491 | |||
| 492 | case ROUNDZERO:; | ||
| 493 | /* truncate is simple */ | ||
| 494 | } /* end switch... */ | ||
| 495 | if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++; | ||
| 496 | } | ||
| 497 | if(result_exponent == DBL_INFINITY_EXPONENT) | ||
| 498 | { | ||
| 499 | /* Overflow */ | ||
| 500 | if(Is_overflowtrap_enabled()) | ||
| 501 | { | ||
| 502 | Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl); | ||
| 503 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 504 | if (inexact) | ||
| 505 | if (Is_inexacttrap_enabled()) | ||
| 506 | return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
| 507 | else Set_inexactflag(); | ||
| 508 | return(OVERFLOWEXCEPTION); | ||
| 509 | } | ||
| 510 | else | ||
| 511 | { | ||
| 512 | inexact = TRUE; | ||
| 513 | Set_overflowflag(); | ||
| 514 | Dbl_setoverflow(resultp1,resultp2); | ||
| 515 | } | ||
| 516 | } | ||
| 517 | else Dbl_set_exponent(resultp1,result_exponent); | ||
| 518 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 519 | if(inexact) | ||
| 520 | if(Is_inexacttrap_enabled()) | ||
| 521 | return(INEXACTEXCEPTION); | ||
| 522 | else Set_inexactflag(); | ||
| 523 | return(NOEXCEPTION); | ||
| 524 | } | ||
diff --git a/arch/parisc/math-emu/dfcmp.c b/arch/parisc/math-emu/dfcmp.c new file mode 100644 index 000000000000..59521267ffcc --- /dev/null +++ b/arch/parisc/math-emu/dfcmp.c | |||
| @@ -0,0 +1,181 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/dfcmp.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * dbl_cmp: compare two values | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * dbl_fcmp(leftptr, rightptr, cond, status) | ||
| 32 | * | ||
| 33 | * Internal Interfaces: | ||
| 34 | * | ||
| 35 | * Theory: | ||
| 36 | * <<please update with a overview of the operation of this file>> | ||
| 37 | * | ||
| 38 | * END_DESC | ||
| 39 | */ | ||
| 40 | |||
| 41 | |||
| 42 | |||
| 43 | #include "float.h" | ||
| 44 | #include "dbl_float.h" | ||
| 45 | |||
| 46 | /* | ||
| 47 | * dbl_cmp: compare two values | ||
| 48 | */ | ||
| 49 | int | ||
| 50 | dbl_fcmp (dbl_floating_point * leftptr, dbl_floating_point * rightptr, | ||
| 51 | unsigned int cond, unsigned int *status) | ||
| 52 | |||
| 53 | /* The predicate to be tested */ | ||
| 54 | |||
| 55 | { | ||
| 56 | register unsigned int leftp1, leftp2, rightp1, rightp2; | ||
| 57 | register int xorresult; | ||
| 58 | |||
| 59 | /* Create local copies of the numbers */ | ||
| 60 | Dbl_copyfromptr(leftptr,leftp1,leftp2); | ||
| 61 | Dbl_copyfromptr(rightptr,rightp1,rightp2); | ||
| 62 | /* | ||
| 63 | * Test for NaN | ||
| 64 | */ | ||
| 65 | if( (Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT) | ||
| 66 | || (Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) ) | ||
| 67 | { | ||
| 68 | /* Check if a NaN is involved. Signal an invalid exception when | ||
| 69 | * comparing a signaling NaN or when comparing quiet NaNs and the | ||
| 70 | * low bit of the condition is set */ | ||
| 71 | if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT) | ||
| 72 | && Dbl_isnotzero_mantissa(leftp1,leftp2) | ||
| 73 | && (Exception(cond) || Dbl_isone_signaling(leftp1))) | ||
| 74 | || | ||
| 75 | ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) | ||
| 76 | && Dbl_isnotzero_mantissa(rightp1,rightp2) | ||
| 77 | && (Exception(cond) || Dbl_isone_signaling(rightp1))) ) | ||
| 78 | { | ||
| 79 | if( Is_invalidtrap_enabled() ) { | ||
| 80 | Set_status_cbit(Unordered(cond)); | ||
| 81 | return(INVALIDEXCEPTION); | ||
| 82 | } | ||
| 83 | else Set_invalidflag(); | ||
| 84 | Set_status_cbit(Unordered(cond)); | ||
| 85 | return(NOEXCEPTION); | ||
| 86 | } | ||
| 87 | /* All the exceptional conditions are handled, now special case | ||
| 88 | NaN compares */ | ||
| 89 | else if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT) | ||
| 90 | && Dbl_isnotzero_mantissa(leftp1,leftp2)) | ||
| 91 | || | ||
| 92 | ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) | ||
| 93 | && Dbl_isnotzero_mantissa(rightp1,rightp2)) ) | ||
| 94 | { | ||
| 95 | /* NaNs always compare unordered. */ | ||
| 96 | Set_status_cbit(Unordered(cond)); | ||
| 97 | return(NOEXCEPTION); | ||
| 98 | } | ||
| 99 | /* infinities will drop down to the normal compare mechanisms */ | ||
| 100 | } | ||
| 101 | /* First compare for unequal signs => less or greater or | ||
| 102 | * special equal case */ | ||
| 103 | Dbl_xortointp1(leftp1,rightp1,xorresult); | ||
| 104 | if( xorresult < 0 ) | ||
| 105 | { | ||
| 106 | /* left negative => less, left positive => greater. | ||
| 107 | * equal is possible if both operands are zeros. */ | ||
| 108 | if( Dbl_iszero_exponentmantissa(leftp1,leftp2) | ||
| 109 | && Dbl_iszero_exponentmantissa(rightp1,rightp2) ) | ||
| 110 | { | ||
| 111 | Set_status_cbit(Equal(cond)); | ||
| 112 | } | ||
| 113 | else if( Dbl_isone_sign(leftp1) ) | ||
| 114 | { | ||
| 115 | Set_status_cbit(Lessthan(cond)); | ||
| 116 | } | ||
| 117 | else | ||
| 118 | { | ||
| 119 | Set_status_cbit(Greaterthan(cond)); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | /* Signs are the same. Treat negative numbers separately | ||
| 123 | * from the positives because of the reversed sense. */ | ||
| 124 | else if(Dbl_isequal(leftp1,leftp2,rightp1,rightp2)) | ||
| 125 | { | ||
| 126 | Set_status_cbit(Equal(cond)); | ||
| 127 | } | ||
| 128 | else if( Dbl_iszero_sign(leftp1) ) | ||
| 129 | { | ||
| 130 | /* Positive compare */ | ||
| 131 | if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) ) | ||
| 132 | { | ||
| 133 | Set_status_cbit(Lessthan(cond)); | ||
| 134 | } | ||
| 135 | else if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) ) | ||
| 136 | { | ||
| 137 | Set_status_cbit(Greaterthan(cond)); | ||
| 138 | } | ||
| 139 | else | ||
| 140 | { | ||
| 141 | /* Equal first parts. Now we must use unsigned compares to | ||
| 142 | * resolve the two possibilities. */ | ||
| 143 | if( Dbl_allp2(leftp2) < Dbl_allp2(rightp2) ) | ||
| 144 | { | ||
| 145 | Set_status_cbit(Lessthan(cond)); | ||
| 146 | } | ||
| 147 | else | ||
| 148 | { | ||
| 149 | Set_status_cbit(Greaterthan(cond)); | ||
| 150 | } | ||
| 151 | } | ||
| 152 | } | ||
| 153 | else | ||
| 154 | { | ||
| 155 | /* Negative compare. Signed or unsigned compares | ||
| 156 | * both work the same. That distinction is only | ||
| 157 | * important when the sign bits differ. */ | ||
| 158 | if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) ) | ||
| 159 | { | ||
| 160 | Set_status_cbit(Lessthan(cond)); | ||
| 161 | } | ||
| 162 | else if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) ) | ||
| 163 | { | ||
| 164 | Set_status_cbit(Greaterthan(cond)); | ||
| 165 | } | ||
| 166 | else | ||
| 167 | { | ||
| 168 | /* Equal first parts. Now we must use unsigned compares to | ||
| 169 | * resolve the two possibilities. */ | ||
| 170 | if( Dbl_allp2(leftp2) > Dbl_allp2(rightp2) ) | ||
| 171 | { | ||
| 172 | Set_status_cbit(Lessthan(cond)); | ||
| 173 | } | ||
| 174 | else | ||
| 175 | { | ||
| 176 | Set_status_cbit(Greaterthan(cond)); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | } | ||
| 180 | return(NOEXCEPTION); | ||
| 181 | } | ||
diff --git a/arch/parisc/math-emu/dfdiv.c b/arch/parisc/math-emu/dfdiv.c new file mode 100644 index 000000000000..d7d4bec0e76f --- /dev/null +++ b/arch/parisc/math-emu/dfdiv.c | |||
| @@ -0,0 +1,400 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/dfdiv.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Double Precision Floating-point Divide | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * dbl_fdiv(srcptr1,srcptr2,dstptr,status) | ||
| 32 | * | ||
| 33 | * Internal Interfaces: | ||
| 34 | * | ||
| 35 | * Theory: | ||
| 36 | * <<please update with a overview of the operation of this file>> | ||
| 37 | * | ||
| 38 | * END_DESC | ||
| 39 | */ | ||
| 40 | |||
| 41 | |||
| 42 | #include "float.h" | ||
| 43 | #include "dbl_float.h" | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Double Precision Floating-point Divide | ||
| 47 | */ | ||
| 48 | |||
| 49 | int | ||
| 50 | dbl_fdiv (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2, | ||
| 51 | dbl_floating_point * dstptr, unsigned int *status) | ||
| 52 | { | ||
| 53 | register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2; | ||
| 54 | register unsigned int opnd3p1, opnd3p2, resultp1, resultp2; | ||
| 55 | register int dest_exponent, count; | ||
| 56 | register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; | ||
| 57 | boolean is_tiny; | ||
| 58 | |||
| 59 | Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2); | ||
| 60 | Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2); | ||
| 61 | /* | ||
| 62 | * set sign bit of result | ||
| 63 | */ | ||
| 64 | if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) | ||
| 65 | Dbl_setnegativezerop1(resultp1); | ||
| 66 | else Dbl_setzerop1(resultp1); | ||
| 67 | /* | ||
| 68 | * check first operand for NaN's or infinity | ||
| 69 | */ | ||
| 70 | if (Dbl_isinfinity_exponent(opnd1p1)) { | ||
| 71 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
| 72 | if (Dbl_isnotnan(opnd2p1,opnd2p2)) { | ||
| 73 | if (Dbl_isinfinity(opnd2p1,opnd2p2)) { | ||
| 74 | /* | ||
| 75 | * invalid since both operands | ||
| 76 | * are infinity | ||
| 77 | */ | ||
| 78 | if (Is_invalidtrap_enabled()) | ||
| 79 | return(INVALIDEXCEPTION); | ||
| 80 | Set_invalidflag(); | ||
| 81 | Dbl_makequietnan(resultp1,resultp2); | ||
| 82 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 83 | return(NOEXCEPTION); | ||
| 84 | } | ||
| 85 | /* | ||
| 86 | * return infinity | ||
| 87 | */ | ||
| 88 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
| 89 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 90 | return(NOEXCEPTION); | ||
| 91 | } | ||
| 92 | } | ||
| 93 | else { | ||
| 94 | /* | ||
| 95 | * is NaN; signaling or quiet? | ||
| 96 | */ | ||
| 97 | if (Dbl_isone_signaling(opnd1p1)) { | ||
| 98 | /* trap if INVALIDTRAP enabled */ | ||
| 99 | if (Is_invalidtrap_enabled()) | ||
| 100 | return(INVALIDEXCEPTION); | ||
| 101 | /* make NaN quiet */ | ||
| 102 | Set_invalidflag(); | ||
| 103 | Dbl_set_quiet(opnd1p1); | ||
| 104 | } | ||
| 105 | /* | ||
| 106 | * is second operand a signaling NaN? | ||
| 107 | */ | ||
| 108 | else if (Dbl_is_signalingnan(opnd2p1)) { | ||
| 109 | /* trap if INVALIDTRAP enabled */ | ||
| 110 | if (Is_invalidtrap_enabled()) | ||
| 111 | return(INVALIDEXCEPTION); | ||
| 112 | /* make NaN quiet */ | ||
| 113 | Set_invalidflag(); | ||
| 114 | Dbl_set_quiet(opnd2p1); | ||
| 115 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
| 116 | return(NOEXCEPTION); | ||
| 117 | } | ||
| 118 | /* | ||
| 119 | * return quiet NaN | ||
| 120 | */ | ||
| 121 | Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); | ||
| 122 | return(NOEXCEPTION); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | /* | ||
| 126 | * check second operand for NaN's or infinity | ||
| 127 | */ | ||
| 128 | if (Dbl_isinfinity_exponent(opnd2p1)) { | ||
| 129 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
| 130 | /* | ||
| 131 | * return zero | ||
| 132 | */ | ||
| 133 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
| 134 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 135 | return(NOEXCEPTION); | ||
| 136 | } | ||
| 137 | /* | ||
| 138 | * is NaN; signaling or quiet? | ||
| 139 | */ | ||
| 140 | if (Dbl_isone_signaling(opnd2p1)) { | ||
| 141 | /* trap if INVALIDTRAP enabled */ | ||
| 142 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 143 | /* make NaN quiet */ | ||
| 144 | Set_invalidflag(); | ||
| 145 | Dbl_set_quiet(opnd2p1); | ||
| 146 | } | ||
| 147 | /* | ||
| 148 | * return quiet NaN | ||
| 149 | */ | ||
| 150 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
| 151 | return(NOEXCEPTION); | ||
| 152 | } | ||
| 153 | /* | ||
| 154 | * check for division by zero | ||
| 155 | */ | ||
| 156 | if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { | ||
| 157 | if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { | ||
| 158 | /* invalid since both operands are zero */ | ||
| 159 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 160 | Set_invalidflag(); | ||
| 161 | Dbl_makequietnan(resultp1,resultp2); | ||
| 162 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 163 | return(NOEXCEPTION); | ||
| 164 | } | ||
| 165 | if (Is_divisionbyzerotrap_enabled()) | ||
| 166 | return(DIVISIONBYZEROEXCEPTION); | ||
| 167 | Set_divisionbyzeroflag(); | ||
| 168 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
| 169 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 170 | return(NOEXCEPTION); | ||
| 171 | } | ||
| 172 | /* | ||
| 173 | * Generate exponent | ||
| 174 | */ | ||
| 175 | dest_exponent = Dbl_exponent(opnd1p1) - Dbl_exponent(opnd2p1) + DBL_BIAS; | ||
| 176 | |||
| 177 | /* | ||
| 178 | * Generate mantissa | ||
| 179 | */ | ||
| 180 | if (Dbl_isnotzero_exponent(opnd1p1)) { | ||
| 181 | /* set hidden bit */ | ||
| 182 | Dbl_clear_signexponent_set_hidden(opnd1p1); | ||
| 183 | } | ||
| 184 | else { | ||
| 185 | /* check for zero */ | ||
| 186 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
| 187 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
| 188 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 189 | return(NOEXCEPTION); | ||
| 190 | } | ||
| 191 | /* is denormalized, want to normalize */ | ||
| 192 | Dbl_clear_signexponent(opnd1p1); | ||
| 193 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
| 194 | Dbl_normalize(opnd1p1,opnd1p2,dest_exponent); | ||
| 195 | } | ||
| 196 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
| 197 | if (Dbl_isnotzero_exponent(opnd2p1)) { | ||
| 198 | Dbl_clear_signexponent_set_hidden(opnd2p1); | ||
| 199 | } | ||
| 200 | else { | ||
| 201 | /* is denormalized; want to normalize */ | ||
| 202 | Dbl_clear_signexponent(opnd2p1); | ||
| 203 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
| 204 | while (Dbl_iszero_hiddenhigh7mantissa(opnd2p1)) { | ||
| 205 | dest_exponent+=8; | ||
| 206 | Dbl_leftshiftby8(opnd2p1,opnd2p2); | ||
| 207 | } | ||
| 208 | if (Dbl_iszero_hiddenhigh3mantissa(opnd2p1)) { | ||
| 209 | dest_exponent+=4; | ||
| 210 | Dbl_leftshiftby4(opnd2p1,opnd2p2); | ||
| 211 | } | ||
| 212 | while (Dbl_iszero_hidden(opnd2p1)) { | ||
| 213 | dest_exponent++; | ||
| 214 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | /* Divide the source mantissas */ | ||
| 219 | |||
| 220 | /* | ||
| 221 | * A non-restoring divide algorithm is used. | ||
| 222 | */ | ||
| 223 | Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2); | ||
| 224 | Dbl_setzero(opnd3p1,opnd3p2); | ||
| 225 | for (count=1; count <= DBL_P && (opnd1p1 || opnd1p2); count++) { | ||
| 226 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
| 227 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
| 228 | if (Dbl_iszero_sign(opnd1p1)) { | ||
| 229 | Dbl_setone_lowmantissap2(opnd3p2); | ||
| 230 | Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2); | ||
| 231 | } | ||
| 232 | else { | ||
| 233 | Twoword_add(opnd1p1, opnd1p2, opnd2p1, opnd2p2); | ||
| 234 | } | ||
| 235 | } | ||
| 236 | if (count <= DBL_P) { | ||
| 237 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
| 238 | Dbl_setone_lowmantissap2(opnd3p2); | ||
| 239 | Dbl_leftshift(opnd3p1,opnd3p2,(DBL_P-count)); | ||
| 240 | if (Dbl_iszero_hidden(opnd3p1)) { | ||
| 241 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
| 242 | dest_exponent--; | ||
| 243 | } | ||
| 244 | } | ||
| 245 | else { | ||
| 246 | if (Dbl_iszero_hidden(opnd3p1)) { | ||
| 247 | /* need to get one more bit of result */ | ||
| 248 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
| 249 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
| 250 | if (Dbl_iszero_sign(opnd1p1)) { | ||
| 251 | Dbl_setone_lowmantissap2(opnd3p2); | ||
| 252 | Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2); | ||
| 253 | } | ||
| 254 | else { | ||
| 255 | Twoword_add(opnd1p1,opnd1p2,opnd2p1,opnd2p2); | ||
| 256 | } | ||
| 257 | dest_exponent--; | ||
| 258 | } | ||
| 259 | if (Dbl_iszero_sign(opnd1p1)) guardbit = TRUE; | ||
| 260 | stickybit = Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2); | ||
| 261 | } | ||
| 262 | inexact = guardbit | stickybit; | ||
| 263 | |||
| 264 | /* | ||
| 265 | * round result | ||
| 266 | */ | ||
| 267 | if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) { | ||
| 268 | Dbl_clear_signexponent(opnd3p1); | ||
| 269 | switch (Rounding_mode()) { | ||
| 270 | case ROUNDPLUS: | ||
| 271 | if (Dbl_iszero_sign(resultp1)) | ||
| 272 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 273 | break; | ||
| 274 | case ROUNDMINUS: | ||
| 275 | if (Dbl_isone_sign(resultp1)) | ||
| 276 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 277 | break; | ||
| 278 | case ROUNDNEAREST: | ||
| 279 | if (guardbit && (stickybit || | ||
| 280 | Dbl_isone_lowmantissap2(opnd3p2))) { | ||
| 281 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 282 | } | ||
| 283 | } | ||
| 284 | if (Dbl_isone_hidden(opnd3p1)) dest_exponent++; | ||
| 285 | } | ||
| 286 | Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2); | ||
| 287 | |||
| 288 | /* | ||
| 289 | * Test for overflow | ||
| 290 | */ | ||
| 291 | if (dest_exponent >= DBL_INFINITY_EXPONENT) { | ||
| 292 | /* trap if OVERFLOWTRAP enabled */ | ||
| 293 | if (Is_overflowtrap_enabled()) { | ||
| 294 | /* | ||
| 295 | * Adjust bias of result | ||
| 296 | */ | ||
| 297 | Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl); | ||
| 298 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 299 | if (inexact) | ||
| 300 | if (Is_inexacttrap_enabled()) | ||
| 301 | return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
| 302 | else Set_inexactflag(); | ||
| 303 | return(OVERFLOWEXCEPTION); | ||
| 304 | } | ||
| 305 | Set_overflowflag(); | ||
| 306 | /* set result to infinity or largest number */ | ||
| 307 | Dbl_setoverflow(resultp1,resultp2); | ||
| 308 | inexact = TRUE; | ||
| 309 | } | ||
| 310 | /* | ||
| 311 | * Test for underflow | ||
| 312 | */ | ||
| 313 | else if (dest_exponent <= 0) { | ||
| 314 | /* trap if UNDERFLOWTRAP enabled */ | ||
| 315 | if (Is_underflowtrap_enabled()) { | ||
| 316 | /* | ||
| 317 | * Adjust bias of result | ||
| 318 | */ | ||
| 319 | Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl); | ||
| 320 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 321 | if (inexact) | ||
| 322 | if (Is_inexacttrap_enabled()) | ||
| 323 | return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
| 324 | else Set_inexactflag(); | ||
| 325 | return(UNDERFLOWEXCEPTION); | ||
| 326 | } | ||
| 327 | |||
| 328 | /* Determine if should set underflow flag */ | ||
| 329 | is_tiny = TRUE; | ||
| 330 | if (dest_exponent == 0 && inexact) { | ||
| 331 | switch (Rounding_mode()) { | ||
| 332 | case ROUNDPLUS: | ||
| 333 | if (Dbl_iszero_sign(resultp1)) { | ||
| 334 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 335 | if (Dbl_isone_hiddenoverflow(opnd3p1)) | ||
| 336 | is_tiny = FALSE; | ||
| 337 | Dbl_decrement(opnd3p1,opnd3p2); | ||
| 338 | } | ||
| 339 | break; | ||
| 340 | case ROUNDMINUS: | ||
| 341 | if (Dbl_isone_sign(resultp1)) { | ||
| 342 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 343 | if (Dbl_isone_hiddenoverflow(opnd3p1)) | ||
| 344 | is_tiny = FALSE; | ||
| 345 | Dbl_decrement(opnd3p1,opnd3p2); | ||
| 346 | } | ||
| 347 | break; | ||
| 348 | case ROUNDNEAREST: | ||
| 349 | if (guardbit && (stickybit || | ||
| 350 | Dbl_isone_lowmantissap2(opnd3p2))) { | ||
| 351 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 352 | if (Dbl_isone_hiddenoverflow(opnd3p1)) | ||
| 353 | is_tiny = FALSE; | ||
| 354 | Dbl_decrement(opnd3p1,opnd3p2); | ||
| 355 | } | ||
| 356 | break; | ||
| 357 | } | ||
| 358 | } | ||
| 359 | |||
| 360 | /* | ||
| 361 | * denormalize result or set to signed zero | ||
| 362 | */ | ||
| 363 | stickybit = inexact; | ||
| 364 | Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit, | ||
| 365 | stickybit,inexact); | ||
| 366 | |||
| 367 | /* return rounded number */ | ||
| 368 | if (inexact) { | ||
| 369 | switch (Rounding_mode()) { | ||
| 370 | case ROUNDPLUS: | ||
| 371 | if (Dbl_iszero_sign(resultp1)) { | ||
| 372 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 373 | } | ||
| 374 | break; | ||
| 375 | case ROUNDMINUS: | ||
| 376 | if (Dbl_isone_sign(resultp1)) { | ||
| 377 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 378 | } | ||
| 379 | break; | ||
| 380 | case ROUNDNEAREST: | ||
| 381 | if (guardbit && (stickybit || | ||
| 382 | Dbl_isone_lowmantissap2(opnd3p2))) { | ||
| 383 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 384 | } | ||
| 385 | break; | ||
| 386 | } | ||
| 387 | if (is_tiny) Set_underflowflag(); | ||
| 388 | } | ||
| 389 | Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2); | ||
| 390 | } | ||
| 391 | else Dbl_set_exponent(resultp1,dest_exponent); | ||
| 392 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 393 | |||
| 394 | /* check for inexact */ | ||
| 395 | if (inexact) { | ||
| 396 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 397 | else Set_inexactflag(); | ||
| 398 | } | ||
| 399 | return(NOEXCEPTION); | ||
| 400 | } | ||
diff --git a/arch/parisc/math-emu/dfmpy.c b/arch/parisc/math-emu/dfmpy.c new file mode 100644 index 000000000000..4380f5a62ad1 --- /dev/null +++ b/arch/parisc/math-emu/dfmpy.c | |||
| @@ -0,0 +1,394 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/dfmpy.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Double Precision Floating-point Multiply | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * dbl_fmpy(srcptr1,srcptr2,dstptr,status) | ||
| 32 | * | ||
| 33 | * Internal Interfaces: | ||
| 34 | * | ||
| 35 | * Theory: | ||
| 36 | * <<please update with a overview of the operation of this file>> | ||
| 37 | * | ||
| 38 | * END_DESC | ||
| 39 | */ | ||
| 40 | |||
| 41 | |||
| 42 | #include "float.h" | ||
| 43 | #include "dbl_float.h" | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Double Precision Floating-point Multiply | ||
| 47 | */ | ||
| 48 | |||
| 49 | int | ||
| 50 | dbl_fmpy( | ||
| 51 | dbl_floating_point *srcptr1, | ||
| 52 | dbl_floating_point *srcptr2, | ||
| 53 | dbl_floating_point *dstptr, | ||
| 54 | unsigned int *status) | ||
| 55 | { | ||
| 56 | register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2; | ||
| 57 | register unsigned int opnd3p1, opnd3p2, resultp1, resultp2; | ||
| 58 | register int dest_exponent, count; | ||
| 59 | register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; | ||
| 60 | boolean is_tiny; | ||
| 61 | |||
| 62 | Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2); | ||
| 63 | Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2); | ||
| 64 | |||
| 65 | /* | ||
| 66 | * set sign bit of result | ||
| 67 | */ | ||
| 68 | if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) | ||
| 69 | Dbl_setnegativezerop1(resultp1); | ||
| 70 | else Dbl_setzerop1(resultp1); | ||
| 71 | /* | ||
| 72 | * check first operand for NaN's or infinity | ||
| 73 | */ | ||
| 74 | if (Dbl_isinfinity_exponent(opnd1p1)) { | ||
| 75 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
| 76 | if (Dbl_isnotnan(opnd2p1,opnd2p2)) { | ||
| 77 | if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { | ||
| 78 | /* | ||
| 79 | * invalid since operands are infinity | ||
| 80 | * and zero | ||
| 81 | */ | ||
| 82 | if (Is_invalidtrap_enabled()) | ||
| 83 | return(INVALIDEXCEPTION); | ||
| 84 | Set_invalidflag(); | ||
| 85 | Dbl_makequietnan(resultp1,resultp2); | ||
| 86 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 87 | return(NOEXCEPTION); | ||
| 88 | } | ||
| 89 | /* | ||
| 90 | * return infinity | ||
| 91 | */ | ||
| 92 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
| 93 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 94 | return(NOEXCEPTION); | ||
| 95 | } | ||
| 96 | } | ||
| 97 | else { | ||
| 98 | /* | ||
| 99 | * is NaN; signaling or quiet? | ||
| 100 | */ | ||
| 101 | if (Dbl_isone_signaling(opnd1p1)) { | ||
| 102 | /* trap if INVALIDTRAP enabled */ | ||
| 103 | if (Is_invalidtrap_enabled()) | ||
| 104 | return(INVALIDEXCEPTION); | ||
| 105 | /* make NaN quiet */ | ||
| 106 | Set_invalidflag(); | ||
| 107 | Dbl_set_quiet(opnd1p1); | ||
| 108 | } | ||
| 109 | /* | ||
| 110 | * is second operand a signaling NaN? | ||
| 111 | */ | ||
| 112 | else if (Dbl_is_signalingnan(opnd2p1)) { | ||
| 113 | /* trap if INVALIDTRAP enabled */ | ||
| 114 | if (Is_invalidtrap_enabled()) | ||
| 115 | return(INVALIDEXCEPTION); | ||
| 116 | /* make NaN quiet */ | ||
| 117 | Set_invalidflag(); | ||
| 118 | Dbl_set_quiet(opnd2p1); | ||
| 119 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
| 120 | return(NOEXCEPTION); | ||
| 121 | } | ||
| 122 | /* | ||
| 123 | * return quiet NaN | ||
| 124 | */ | ||
| 125 | Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); | ||
| 126 | return(NOEXCEPTION); | ||
| 127 | } | ||
| 128 | } | ||
| 129 | /* | ||
| 130 | * check second operand for NaN's or infinity | ||
| 131 | */ | ||
| 132 | if (Dbl_isinfinity_exponent(opnd2p1)) { | ||
| 133 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
| 134 | if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { | ||
| 135 | /* invalid since operands are zero & infinity */ | ||
| 136 | if (Is_invalidtrap_enabled()) | ||
| 137 | return(INVALIDEXCEPTION); | ||
| 138 | Set_invalidflag(); | ||
| 139 | Dbl_makequietnan(opnd2p1,opnd2p2); | ||
| 140 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
| 141 | return(NOEXCEPTION); | ||
| 142 | } | ||
| 143 | /* | ||
| 144 | * return infinity | ||
| 145 | */ | ||
| 146 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
| 147 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 148 | return(NOEXCEPTION); | ||
| 149 | } | ||
| 150 | /* | ||
| 151 | * is NaN; signaling or quiet? | ||
| 152 | */ | ||
| 153 | if (Dbl_isone_signaling(opnd2p1)) { | ||
| 154 | /* trap if INVALIDTRAP enabled */ | ||
| 155 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 156 | /* make NaN quiet */ | ||
| 157 | Set_invalidflag(); | ||
| 158 | Dbl_set_quiet(opnd2p1); | ||
| 159 | } | ||
| 160 | /* | ||
| 161 | * return quiet NaN | ||
| 162 | */ | ||
| 163 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
| 164 | return(NOEXCEPTION); | ||
| 165 | } | ||
| 166 | /* | ||
| 167 | * Generate exponent | ||
| 168 | */ | ||
| 169 | dest_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) -DBL_BIAS; | ||
| 170 | |||
| 171 | /* | ||
| 172 | * Generate mantissa | ||
| 173 | */ | ||
| 174 | if (Dbl_isnotzero_exponent(opnd1p1)) { | ||
| 175 | /* set hidden bit */ | ||
| 176 | Dbl_clear_signexponent_set_hidden(opnd1p1); | ||
| 177 | } | ||
| 178 | else { | ||
| 179 | /* check for zero */ | ||
| 180 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
| 181 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
| 182 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 183 | return(NOEXCEPTION); | ||
| 184 | } | ||
| 185 | /* is denormalized, adjust exponent */ | ||
| 186 | Dbl_clear_signexponent(opnd1p1); | ||
| 187 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
| 188 | Dbl_normalize(opnd1p1,opnd1p2,dest_exponent); | ||
| 189 | } | ||
| 190 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
| 191 | if (Dbl_isnotzero_exponent(opnd2p1)) { | ||
| 192 | Dbl_clear_signexponent_set_hidden(opnd2p1); | ||
| 193 | } | ||
| 194 | else { | ||
| 195 | /* check for zero */ | ||
| 196 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
| 197 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
| 198 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 199 | return(NOEXCEPTION); | ||
| 200 | } | ||
| 201 | /* is denormalized; want to normalize */ | ||
| 202 | Dbl_clear_signexponent(opnd2p1); | ||
| 203 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
| 204 | Dbl_normalize(opnd2p1,opnd2p2,dest_exponent); | ||
| 205 | } | ||
| 206 | |||
| 207 | /* Multiply two source mantissas together */ | ||
| 208 | |||
| 209 | /* make room for guard bits */ | ||
| 210 | Dbl_leftshiftby7(opnd2p1,opnd2p2); | ||
| 211 | Dbl_setzero(opnd3p1,opnd3p2); | ||
| 212 | /* | ||
| 213 | * Four bits at a time are inspected in each loop, and a | ||
| 214 | * simple shift and add multiply algorithm is used. | ||
| 215 | */ | ||
| 216 | for (count=1;count<=DBL_P;count+=4) { | ||
| 217 | stickybit |= Dlow4p2(opnd3p2); | ||
| 218 | Dbl_rightshiftby4(opnd3p1,opnd3p2); | ||
| 219 | if (Dbit28p2(opnd1p2)) { | ||
| 220 | /* Twoword_add should be an ADDC followed by an ADD. */ | ||
| 221 | Twoword_add(opnd3p1, opnd3p2, opnd2p1<<3 | opnd2p2>>29, | ||
| 222 | opnd2p2<<3); | ||
| 223 | } | ||
| 224 | if (Dbit29p2(opnd1p2)) { | ||
| 225 | Twoword_add(opnd3p1, opnd3p2, opnd2p1<<2 | opnd2p2>>30, | ||
| 226 | opnd2p2<<2); | ||
| 227 | } | ||
| 228 | if (Dbit30p2(opnd1p2)) { | ||
| 229 | Twoword_add(opnd3p1, opnd3p2, opnd2p1<<1 | opnd2p2>>31, | ||
| 230 | opnd2p2<<1); | ||
| 231 | } | ||
| 232 | if (Dbit31p2(opnd1p2)) { | ||
| 233 | Twoword_add(opnd3p1, opnd3p2, opnd2p1, opnd2p2); | ||
| 234 | } | ||
| 235 | Dbl_rightshiftby4(opnd1p1,opnd1p2); | ||
| 236 | } | ||
| 237 | if (Dbit3p1(opnd3p1)==0) { | ||
| 238 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
| 239 | } | ||
| 240 | else { | ||
| 241 | /* result mantissa >= 2. */ | ||
| 242 | dest_exponent++; | ||
| 243 | } | ||
| 244 | /* check for denormalized result */ | ||
| 245 | while (Dbit3p1(opnd3p1)==0) { | ||
| 246 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
| 247 | dest_exponent--; | ||
| 248 | } | ||
| 249 | /* | ||
| 250 | * check for guard, sticky and inexact bits | ||
| 251 | */ | ||
| 252 | stickybit |= Dallp2(opnd3p2) << 25; | ||
| 253 | guardbit = (Dallp2(opnd3p2) << 24) >> 31; | ||
| 254 | inexact = guardbit | stickybit; | ||
| 255 | |||
| 256 | /* align result mantissa */ | ||
| 257 | Dbl_rightshiftby8(opnd3p1,opnd3p2); | ||
| 258 | |||
| 259 | /* | ||
| 260 | * round result | ||
| 261 | */ | ||
| 262 | if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) { | ||
| 263 | Dbl_clear_signexponent(opnd3p1); | ||
| 264 | switch (Rounding_mode()) { | ||
| 265 | case ROUNDPLUS: | ||
| 266 | if (Dbl_iszero_sign(resultp1)) | ||
| 267 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 268 | break; | ||
| 269 | case ROUNDMINUS: | ||
| 270 | if (Dbl_isone_sign(resultp1)) | ||
| 271 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 272 | break; | ||
| 273 | case ROUNDNEAREST: | ||
| 274 | if (guardbit) { | ||
| 275 | if (stickybit || Dbl_isone_lowmantissap2(opnd3p2)) | ||
| 276 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 277 | } | ||
| 278 | } | ||
| 279 | if (Dbl_isone_hidden(opnd3p1)) dest_exponent++; | ||
| 280 | } | ||
| 281 | Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2); | ||
| 282 | |||
| 283 | /* | ||
| 284 | * Test for overflow | ||
| 285 | */ | ||
| 286 | if (dest_exponent >= DBL_INFINITY_EXPONENT) { | ||
| 287 | /* trap if OVERFLOWTRAP enabled */ | ||
| 288 | if (Is_overflowtrap_enabled()) { | ||
| 289 | /* | ||
| 290 | * Adjust bias of result | ||
| 291 | */ | ||
| 292 | Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl); | ||
| 293 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 294 | if (inexact) | ||
| 295 | if (Is_inexacttrap_enabled()) | ||
| 296 | return (OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
| 297 | else Set_inexactflag(); | ||
| 298 | return (OVERFLOWEXCEPTION); | ||
| 299 | } | ||
| 300 | inexact = TRUE; | ||
| 301 | Set_overflowflag(); | ||
| 302 | /* set result to infinity or largest number */ | ||
| 303 | Dbl_setoverflow(resultp1,resultp2); | ||
| 304 | } | ||
| 305 | /* | ||
| 306 | * Test for underflow | ||
| 307 | */ | ||
| 308 | else if (dest_exponent <= 0) { | ||
| 309 | /* trap if UNDERFLOWTRAP enabled */ | ||
| 310 | if (Is_underflowtrap_enabled()) { | ||
| 311 | /* | ||
| 312 | * Adjust bias of result | ||
| 313 | */ | ||
| 314 | Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl); | ||
| 315 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 316 | if (inexact) | ||
| 317 | if (Is_inexacttrap_enabled()) | ||
| 318 | return (UNDERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
| 319 | else Set_inexactflag(); | ||
| 320 | return (UNDERFLOWEXCEPTION); | ||
| 321 | } | ||
| 322 | |||
| 323 | /* Determine if should set underflow flag */ | ||
| 324 | is_tiny = TRUE; | ||
| 325 | if (dest_exponent == 0 && inexact) { | ||
| 326 | switch (Rounding_mode()) { | ||
| 327 | case ROUNDPLUS: | ||
| 328 | if (Dbl_iszero_sign(resultp1)) { | ||
| 329 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 330 | if (Dbl_isone_hiddenoverflow(opnd3p1)) | ||
| 331 | is_tiny = FALSE; | ||
| 332 | Dbl_decrement(opnd3p1,opnd3p2); | ||
| 333 | } | ||
| 334 | break; | ||
| 335 | case ROUNDMINUS: | ||
| 336 | if (Dbl_isone_sign(resultp1)) { | ||
| 337 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 338 | if (Dbl_isone_hiddenoverflow(opnd3p1)) | ||
| 339 | is_tiny = FALSE; | ||
| 340 | Dbl_decrement(opnd3p1,opnd3p2); | ||
| 341 | } | ||
| 342 | break; | ||
| 343 | case ROUNDNEAREST: | ||
| 344 | if (guardbit && (stickybit || | ||
| 345 | Dbl_isone_lowmantissap2(opnd3p2))) { | ||
| 346 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 347 | if (Dbl_isone_hiddenoverflow(opnd3p1)) | ||
| 348 | is_tiny = FALSE; | ||
| 349 | Dbl_decrement(opnd3p1,opnd3p2); | ||
| 350 | } | ||
| 351 | break; | ||
| 352 | } | ||
| 353 | } | ||
| 354 | |||
| 355 | /* | ||
| 356 | * denormalize result or set to signed zero | ||
| 357 | */ | ||
| 358 | stickybit = inexact; | ||
| 359 | Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit, | ||
| 360 | stickybit,inexact); | ||
| 361 | |||
| 362 | /* return zero or smallest number */ | ||
| 363 | if (inexact) { | ||
| 364 | switch (Rounding_mode()) { | ||
| 365 | case ROUNDPLUS: | ||
| 366 | if (Dbl_iszero_sign(resultp1)) { | ||
| 367 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 368 | } | ||
| 369 | break; | ||
| 370 | case ROUNDMINUS: | ||
| 371 | if (Dbl_isone_sign(resultp1)) { | ||
| 372 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 373 | } | ||
| 374 | break; | ||
| 375 | case ROUNDNEAREST: | ||
| 376 | if (guardbit && (stickybit || | ||
| 377 | Dbl_isone_lowmantissap2(opnd3p2))) { | ||
| 378 | Dbl_increment(opnd3p1,opnd3p2); | ||
| 379 | } | ||
| 380 | break; | ||
| 381 | } | ||
| 382 | if (is_tiny) Set_underflowflag(); | ||
| 383 | } | ||
| 384 | Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2); | ||
| 385 | } | ||
| 386 | else Dbl_set_exponent(resultp1,dest_exponent); | ||
| 387 | /* check for inexact */ | ||
| 388 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 389 | if (inexact) { | ||
| 390 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 391 | else Set_inexactflag(); | ||
| 392 | } | ||
| 393 | return(NOEXCEPTION); | ||
| 394 | } | ||
diff --git a/arch/parisc/math-emu/dfrem.c b/arch/parisc/math-emu/dfrem.c new file mode 100644 index 000000000000..b98378534677 --- /dev/null +++ b/arch/parisc/math-emu/dfrem.c | |||
| @@ -0,0 +1,297 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/dfrem.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Double Precision Floating-point Remainder | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * dbl_frem(srcptr1,srcptr2,dstptr,status) | ||
| 32 | * | ||
| 33 | * Internal Interfaces: | ||
| 34 | * | ||
| 35 | * Theory: | ||
| 36 | * <<please update with a overview of the operation of this file>> | ||
| 37 | * | ||
| 38 | * END_DESC | ||
| 39 | */ | ||
| 40 | |||
| 41 | |||
| 42 | |||
| 43 | #include "float.h" | ||
| 44 | #include "dbl_float.h" | ||
| 45 | |||
| 46 | /* | ||
| 47 | * Double Precision Floating-point Remainder | ||
| 48 | */ | ||
| 49 | |||
| 50 | int | ||
| 51 | dbl_frem (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2, | ||
| 52 | dbl_floating_point * dstptr, unsigned int *status) | ||
| 53 | { | ||
| 54 | register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2; | ||
| 55 | register unsigned int resultp1, resultp2; | ||
| 56 | register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount; | ||
| 57 | register boolean roundup = FALSE; | ||
| 58 | |||
| 59 | Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2); | ||
| 60 | Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2); | ||
| 61 | /* | ||
| 62 | * check first operand for NaN's or infinity | ||
| 63 | */ | ||
| 64 | if ((opnd1_exponent = Dbl_exponent(opnd1p1)) == DBL_INFINITY_EXPONENT) { | ||
| 65 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
| 66 | if (Dbl_isnotnan(opnd2p1,opnd2p2)) { | ||
| 67 | /* invalid since first operand is infinity */ | ||
| 68 | if (Is_invalidtrap_enabled()) | ||
| 69 | return(INVALIDEXCEPTION); | ||
| 70 | Set_invalidflag(); | ||
| 71 | Dbl_makequietnan(resultp1,resultp2); | ||
| 72 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 73 | return(NOEXCEPTION); | ||
| 74 | } | ||
| 75 | } | ||
| 76 | else { | ||
| 77 | /* | ||
| 78 | * is NaN; signaling or quiet? | ||
| 79 | */ | ||
| 80 | if (Dbl_isone_signaling(opnd1p1)) { | ||
| 81 | /* trap if INVALIDTRAP enabled */ | ||
| 82 | if (Is_invalidtrap_enabled()) | ||
| 83 | return(INVALIDEXCEPTION); | ||
| 84 | /* make NaN quiet */ | ||
| 85 | Set_invalidflag(); | ||
| 86 | Dbl_set_quiet(opnd1p1); | ||
| 87 | } | ||
| 88 | /* | ||
| 89 | * is second operand a signaling NaN? | ||
| 90 | */ | ||
| 91 | else if (Dbl_is_signalingnan(opnd2p1)) { | ||
| 92 | /* trap if INVALIDTRAP enabled */ | ||
| 93 | if (Is_invalidtrap_enabled()) | ||
| 94 | return(INVALIDEXCEPTION); | ||
| 95 | /* make NaN quiet */ | ||
| 96 | Set_invalidflag(); | ||
| 97 | Dbl_set_quiet(opnd2p1); | ||
| 98 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
| 99 | return(NOEXCEPTION); | ||
| 100 | } | ||
| 101 | /* | ||
| 102 | * return quiet NaN | ||
| 103 | */ | ||
| 104 | Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); | ||
| 105 | return(NOEXCEPTION); | ||
| 106 | } | ||
| 107 | } | ||
| 108 | /* | ||
| 109 | * check second operand for NaN's or infinity | ||
| 110 | */ | ||
| 111 | if ((opnd2_exponent = Dbl_exponent(opnd2p1)) == DBL_INFINITY_EXPONENT) { | ||
| 112 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
| 113 | /* | ||
| 114 | * return first operand | ||
| 115 | */ | ||
| 116 | Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); | ||
| 117 | return(NOEXCEPTION); | ||
| 118 | } | ||
| 119 | /* | ||
| 120 | * is NaN; signaling or quiet? | ||
| 121 | */ | ||
| 122 | if (Dbl_isone_signaling(opnd2p1)) { | ||
| 123 | /* trap if INVALIDTRAP enabled */ | ||
| 124 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 125 | /* make NaN quiet */ | ||
| 126 | Set_invalidflag(); | ||
| 127 | Dbl_set_quiet(opnd2p1); | ||
| 128 | } | ||
| 129 | /* | ||
| 130 | * return quiet NaN | ||
| 131 | */ | ||
| 132 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
| 133 | return(NOEXCEPTION); | ||
| 134 | } | ||
| 135 | /* | ||
| 136 | * check second operand for zero | ||
| 137 | */ | ||
| 138 | if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { | ||
| 139 | /* invalid since second operand is zero */ | ||
| 140 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 141 | Set_invalidflag(); | ||
| 142 | Dbl_makequietnan(resultp1,resultp2); | ||
| 143 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 144 | return(NOEXCEPTION); | ||
| 145 | } | ||
| 146 | |||
| 147 | /* | ||
| 148 | * get sign of result | ||
| 149 | */ | ||
| 150 | resultp1 = opnd1p1; | ||
| 151 | |||
| 152 | /* | ||
| 153 | * check for denormalized operands | ||
| 154 | */ | ||
| 155 | if (opnd1_exponent == 0) { | ||
| 156 | /* check for zero */ | ||
| 157 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
| 158 | Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); | ||
| 159 | return(NOEXCEPTION); | ||
| 160 | } | ||
| 161 | /* normalize, then continue */ | ||
| 162 | opnd1_exponent = 1; | ||
| 163 | Dbl_normalize(opnd1p1,opnd1p2,opnd1_exponent); | ||
| 164 | } | ||
| 165 | else { | ||
| 166 | Dbl_clear_signexponent_set_hidden(opnd1p1); | ||
| 167 | } | ||
| 168 | if (opnd2_exponent == 0) { | ||
| 169 | /* normalize, then continue */ | ||
| 170 | opnd2_exponent = 1; | ||
| 171 | Dbl_normalize(opnd2p1,opnd2p2,opnd2_exponent); | ||
| 172 | } | ||
| 173 | else { | ||
| 174 | Dbl_clear_signexponent_set_hidden(opnd2p1); | ||
| 175 | } | ||
| 176 | |||
| 177 | /* find result exponent and divide step loop count */ | ||
| 178 | dest_exponent = opnd2_exponent - 1; | ||
| 179 | stepcount = opnd1_exponent - opnd2_exponent; | ||
| 180 | |||
| 181 | /* | ||
| 182 | * check for opnd1/opnd2 < 1 | ||
| 183 | */ | ||
| 184 | if (stepcount < 0) { | ||
| 185 | /* | ||
| 186 | * check for opnd1/opnd2 > 1/2 | ||
| 187 | * | ||
| 188 | * In this case n will round to 1, so | ||
| 189 | * r = opnd1 - opnd2 | ||
| 190 | */ | ||
| 191 | if (stepcount == -1 && | ||
| 192 | Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) { | ||
| 193 | /* set sign */ | ||
| 194 | Dbl_allp1(resultp1) = ~Dbl_allp1(resultp1); | ||
| 195 | /* align opnd2 with opnd1 */ | ||
| 196 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
| 197 | Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2, | ||
| 198 | opnd2p1,opnd2p2); | ||
| 199 | /* now normalize */ | ||
| 200 | while (Dbl_iszero_hidden(opnd2p1)) { | ||
| 201 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
| 202 | dest_exponent--; | ||
| 203 | } | ||
| 204 | Dbl_set_exponentmantissa(resultp1,resultp2,opnd2p1,opnd2p2); | ||
| 205 | goto testforunderflow; | ||
| 206 | } | ||
| 207 | /* | ||
| 208 | * opnd1/opnd2 <= 1/2 | ||
| 209 | * | ||
| 210 | * In this case n will round to zero, so | ||
| 211 | * r = opnd1 | ||
| 212 | */ | ||
| 213 | Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2); | ||
| 214 | dest_exponent = opnd1_exponent; | ||
| 215 | goto testforunderflow; | ||
| 216 | } | ||
| 217 | |||
| 218 | /* | ||
| 219 | * Generate result | ||
| 220 | * | ||
| 221 | * Do iterative subtract until remainder is less than operand 2. | ||
| 222 | */ | ||
| 223 | while (stepcount-- > 0 && (Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2))) { | ||
| 224 | if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) { | ||
| 225 | Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2); | ||
| 226 | } | ||
| 227 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
| 228 | } | ||
| 229 | /* | ||
| 230 | * Do last subtract, then determine which way to round if remainder | ||
| 231 | * is exactly 1/2 of opnd2 | ||
| 232 | */ | ||
| 233 | if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) { | ||
| 234 | Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2); | ||
| 235 | roundup = TRUE; | ||
| 236 | } | ||
| 237 | if (stepcount > 0 || Dbl_iszero(opnd1p1,opnd1p2)) { | ||
| 238 | /* division is exact, remainder is zero */ | ||
| 239 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
| 240 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 241 | return(NOEXCEPTION); | ||
| 242 | } | ||
| 243 | |||
| 244 | /* | ||
| 245 | * Check for cases where opnd1/opnd2 < n | ||
| 246 | * | ||
| 247 | * In this case the result's sign will be opposite that of | ||
| 248 | * opnd1. The mantissa also needs some correction. | ||
| 249 | */ | ||
| 250 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
| 251 | if (Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) { | ||
| 252 | Dbl_invert_sign(resultp1); | ||
| 253 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
| 254 | Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,opnd1p1,opnd1p2); | ||
| 255 | } | ||
| 256 | /* check for remainder being exactly 1/2 of opnd2 */ | ||
| 257 | else if (Dbl_isequal(opnd1p1,opnd1p2,opnd2p1,opnd2p2) && roundup) { | ||
| 258 | Dbl_invert_sign(resultp1); | ||
| 259 | } | ||
| 260 | |||
| 261 | /* normalize result's mantissa */ | ||
| 262 | while (Dbl_iszero_hidden(opnd1p1)) { | ||
| 263 | dest_exponent--; | ||
| 264 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
| 265 | } | ||
| 266 | Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2); | ||
| 267 | |||
| 268 | /* | ||
| 269 | * Test for underflow | ||
| 270 | */ | ||
| 271 | testforunderflow: | ||
| 272 | if (dest_exponent <= 0) { | ||
| 273 | /* trap if UNDERFLOWTRAP enabled */ | ||
| 274 | if (Is_underflowtrap_enabled()) { | ||
| 275 | /* | ||
| 276 | * Adjust bias of result | ||
| 277 | */ | ||
| 278 | Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl); | ||
| 279 | /* frem is always exact */ | ||
| 280 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 281 | return(UNDERFLOWEXCEPTION); | ||
| 282 | } | ||
| 283 | /* | ||
| 284 | * denormalize result or set to signed zero | ||
| 285 | */ | ||
| 286 | if (dest_exponent >= (1 - DBL_P)) { | ||
| 287 | Dbl_rightshift_exponentmantissa(resultp1,resultp2, | ||
| 288 | 1-dest_exponent); | ||
| 289 | } | ||
| 290 | else { | ||
| 291 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
| 292 | } | ||
| 293 | } | ||
| 294 | else Dbl_set_exponent(resultp1,dest_exponent); | ||
| 295 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 296 | return(NOEXCEPTION); | ||
| 297 | } | ||
diff --git a/arch/parisc/math-emu/dfsqrt.c b/arch/parisc/math-emu/dfsqrt.c new file mode 100644 index 000000000000..b6ed1066f1e4 --- /dev/null +++ b/arch/parisc/math-emu/dfsqrt.c | |||
| @@ -0,0 +1,195 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/dfsqrt.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Double Floating-point Square Root | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * dbl_fsqrt(srcptr,nullptr,dstptr,status) | ||
| 32 | * | ||
| 33 | * Internal Interfaces: | ||
| 34 | * | ||
| 35 | * Theory: | ||
| 36 | * <<please update with a overview of the operation of this file>> | ||
| 37 | * | ||
| 38 | * END_DESC | ||
| 39 | */ | ||
| 40 | |||
| 41 | |||
| 42 | #include "float.h" | ||
| 43 | #include "dbl_float.h" | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Double Floating-point Square Root | ||
| 47 | */ | ||
| 48 | |||
| 49 | /*ARGSUSED*/ | ||
| 50 | unsigned int | ||
| 51 | dbl_fsqrt( | ||
| 52 | dbl_floating_point *srcptr, | ||
| 53 | unsigned int *nullptr, | ||
| 54 | dbl_floating_point *dstptr, | ||
| 55 | unsigned int *status) | ||
| 56 | { | ||
| 57 | register unsigned int srcp1, srcp2, resultp1, resultp2; | ||
| 58 | register unsigned int newbitp1, newbitp2, sump1, sump2; | ||
| 59 | register int src_exponent; | ||
| 60 | register boolean guardbit = FALSE, even_exponent; | ||
| 61 | |||
| 62 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
| 63 | /* | ||
| 64 | * check source operand for NaN or infinity | ||
| 65 | */ | ||
| 66 | if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) { | ||
| 67 | /* | ||
| 68 | * is signaling NaN? | ||
| 69 | */ | ||
| 70 | if (Dbl_isone_signaling(srcp1)) { | ||
| 71 | /* trap if INVALIDTRAP enabled */ | ||
| 72 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 73 | /* make NaN quiet */ | ||
| 74 | Set_invalidflag(); | ||
| 75 | Dbl_set_quiet(srcp1); | ||
| 76 | } | ||
| 77 | /* | ||
| 78 | * Return quiet NaN or positive infinity. | ||
| 79 | * Fall thru to negative test if negative infinity. | ||
| 80 | */ | ||
| 81 | if (Dbl_iszero_sign(srcp1) || | ||
| 82 | Dbl_isnotzero_mantissa(srcp1,srcp2)) { | ||
| 83 | Dbl_copytoptr(srcp1,srcp2,dstptr); | ||
| 84 | return(NOEXCEPTION); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | /* | ||
| 89 | * check for zero source operand | ||
| 90 | */ | ||
| 91 | if (Dbl_iszero_exponentmantissa(srcp1,srcp2)) { | ||
| 92 | Dbl_copytoptr(srcp1,srcp2,dstptr); | ||
| 93 | return(NOEXCEPTION); | ||
| 94 | } | ||
| 95 | |||
| 96 | /* | ||
| 97 | * check for negative source operand | ||
| 98 | */ | ||
| 99 | if (Dbl_isone_sign(srcp1)) { | ||
| 100 | /* trap if INVALIDTRAP enabled */ | ||
| 101 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 102 | /* make NaN quiet */ | ||
| 103 | Set_invalidflag(); | ||
| 104 | Dbl_makequietnan(srcp1,srcp2); | ||
| 105 | Dbl_copytoptr(srcp1,srcp2,dstptr); | ||
| 106 | return(NOEXCEPTION); | ||
| 107 | } | ||
| 108 | |||
| 109 | /* | ||
| 110 | * Generate result | ||
| 111 | */ | ||
| 112 | if (src_exponent > 0) { | ||
| 113 | even_exponent = Dbl_hidden(srcp1); | ||
| 114 | Dbl_clear_signexponent_set_hidden(srcp1); | ||
| 115 | } | ||
| 116 | else { | ||
| 117 | /* normalize operand */ | ||
| 118 | Dbl_clear_signexponent(srcp1); | ||
| 119 | src_exponent++; | ||
| 120 | Dbl_normalize(srcp1,srcp2,src_exponent); | ||
| 121 | even_exponent = src_exponent & 1; | ||
| 122 | } | ||
| 123 | if (even_exponent) { | ||
| 124 | /* exponent is even */ | ||
| 125 | /* Add comment here. Explain why odd exponent needs correction */ | ||
| 126 | Dbl_leftshiftby1(srcp1,srcp2); | ||
| 127 | } | ||
| 128 | /* | ||
| 129 | * Add comment here. Explain following algorithm. | ||
| 130 | * | ||
| 131 | * Trust me, it works. | ||
| 132 | * | ||
| 133 | */ | ||
| 134 | Dbl_setzero(resultp1,resultp2); | ||
| 135 | Dbl_allp1(newbitp1) = 1 << (DBL_P - 32); | ||
| 136 | Dbl_setzero_mantissap2(newbitp2); | ||
| 137 | while (Dbl_isnotzero(newbitp1,newbitp2) && Dbl_isnotzero(srcp1,srcp2)) { | ||
| 138 | Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,sump1,sump2); | ||
| 139 | if(Dbl_isnotgreaterthan(sump1,sump2,srcp1,srcp2)) { | ||
| 140 | Dbl_leftshiftby1(newbitp1,newbitp2); | ||
| 141 | /* update result */ | ||
| 142 | Dbl_addition(resultp1,resultp2,newbitp1,newbitp2, | ||
| 143 | resultp1,resultp2); | ||
| 144 | Dbl_subtract(srcp1,srcp2,sump1,sump2,srcp1,srcp2); | ||
| 145 | Dbl_rightshiftby2(newbitp1,newbitp2); | ||
| 146 | } | ||
| 147 | else { | ||
| 148 | Dbl_rightshiftby1(newbitp1,newbitp2); | ||
| 149 | } | ||
| 150 | Dbl_leftshiftby1(srcp1,srcp2); | ||
| 151 | } | ||
| 152 | /* correct exponent for pre-shift */ | ||
| 153 | if (even_exponent) { | ||
| 154 | Dbl_rightshiftby1(resultp1,resultp2); | ||
| 155 | } | ||
| 156 | |||
| 157 | /* check for inexact */ | ||
| 158 | if (Dbl_isnotzero(srcp1,srcp2)) { | ||
| 159 | if (!even_exponent && Dbl_islessthan(resultp1,resultp2,srcp1,srcp2)) { | ||
| 160 | Dbl_increment(resultp1,resultp2); | ||
| 161 | } | ||
| 162 | guardbit = Dbl_lowmantissap2(resultp2); | ||
| 163 | Dbl_rightshiftby1(resultp1,resultp2); | ||
| 164 | |||
| 165 | /* now round result */ | ||
| 166 | switch (Rounding_mode()) { | ||
| 167 | case ROUNDPLUS: | ||
| 168 | Dbl_increment(resultp1,resultp2); | ||
| 169 | break; | ||
| 170 | case ROUNDNEAREST: | ||
| 171 | /* stickybit is always true, so guardbit | ||
| 172 | * is enough to determine rounding */ | ||
| 173 | if (guardbit) { | ||
| 174 | Dbl_increment(resultp1,resultp2); | ||
| 175 | } | ||
| 176 | break; | ||
| 177 | } | ||
| 178 | /* increment result exponent by 1 if mantissa overflowed */ | ||
| 179 | if (Dbl_isone_hiddenoverflow(resultp1)) src_exponent+=2; | ||
| 180 | |||
| 181 | if (Is_inexacttrap_enabled()) { | ||
| 182 | Dbl_set_exponent(resultp1, | ||
| 183 | ((src_exponent-DBL_BIAS)>>1)+DBL_BIAS); | ||
| 184 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 185 | return(INEXACTEXCEPTION); | ||
| 186 | } | ||
| 187 | else Set_inexactflag(); | ||
| 188 | } | ||
| 189 | else { | ||
| 190 | Dbl_rightshiftby1(resultp1,resultp2); | ||
| 191 | } | ||
| 192 | Dbl_set_exponent(resultp1,((src_exponent-DBL_BIAS)>>1)+DBL_BIAS); | ||
| 193 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 194 | return(NOEXCEPTION); | ||
| 195 | } | ||
diff --git a/arch/parisc/math-emu/dfsub.c b/arch/parisc/math-emu/dfsub.c new file mode 100644 index 000000000000..87ebc60d465b --- /dev/null +++ b/arch/parisc/math-emu/dfsub.c | |||
| @@ -0,0 +1,526 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/dfsub.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Double_subtract: subtract two double precision values. | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * dbl_fsub(leftptr, rightptr, dstptr, status) | ||
| 32 | * | ||
| 33 | * Internal Interfaces: | ||
| 34 | * | ||
| 35 | * Theory: | ||
| 36 | * <<please update with a overview of the operation of this file>> | ||
| 37 | * | ||
| 38 | * END_DESC | ||
| 39 | */ | ||
| 40 | |||
| 41 | |||
| 42 | #include "float.h" | ||
| 43 | #include "dbl_float.h" | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Double_subtract: subtract two double precision values. | ||
| 47 | */ | ||
| 48 | int | ||
| 49 | dbl_fsub( | ||
| 50 | dbl_floating_point *leftptr, | ||
| 51 | dbl_floating_point *rightptr, | ||
| 52 | dbl_floating_point *dstptr, | ||
| 53 | unsigned int *status) | ||
| 54 | { | ||
| 55 | register unsigned int signless_upper_left, signless_upper_right, save; | ||
| 56 | register unsigned int leftp1, leftp2, rightp1, rightp2, extent; | ||
| 57 | register unsigned int resultp1 = 0, resultp2 = 0; | ||
| 58 | |||
| 59 | register int result_exponent, right_exponent, diff_exponent; | ||
| 60 | register int sign_save, jumpsize; | ||
| 61 | register boolean inexact = FALSE, underflowtrap; | ||
| 62 | |||
| 63 | /* Create local copies of the numbers */ | ||
| 64 | Dbl_copyfromptr(leftptr,leftp1,leftp2); | ||
| 65 | Dbl_copyfromptr(rightptr,rightp1,rightp2); | ||
| 66 | |||
| 67 | /* A zero "save" helps discover equal operands (for later), * | ||
| 68 | * and is used in swapping operands (if needed). */ | ||
| 69 | Dbl_xortointp1(leftp1,rightp1,/*to*/save); | ||
| 70 | |||
| 71 | /* | ||
| 72 | * check first operand for NaN's or infinity | ||
| 73 | */ | ||
| 74 | if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT) | ||
| 75 | { | ||
| 76 | if (Dbl_iszero_mantissa(leftp1,leftp2)) | ||
| 77 | { | ||
| 78 | if (Dbl_isnotnan(rightp1,rightp2)) | ||
| 79 | { | ||
| 80 | if (Dbl_isinfinity(rightp1,rightp2) && save==0) | ||
| 81 | { | ||
| 82 | /* | ||
| 83 | * invalid since operands are same signed infinity's | ||
| 84 | */ | ||
| 85 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 86 | Set_invalidflag(); | ||
| 87 | Dbl_makequietnan(resultp1,resultp2); | ||
| 88 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 89 | return(NOEXCEPTION); | ||
| 90 | } | ||
| 91 | /* | ||
| 92 | * return infinity | ||
| 93 | */ | ||
| 94 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
| 95 | return(NOEXCEPTION); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | else | ||
| 99 | { | ||
| 100 | /* | ||
| 101 | * is NaN; signaling or quiet? | ||
| 102 | */ | ||
| 103 | if (Dbl_isone_signaling(leftp1)) | ||
| 104 | { | ||
| 105 | /* trap if INVALIDTRAP enabled */ | ||
| 106 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 107 | /* make NaN quiet */ | ||
| 108 | Set_invalidflag(); | ||
| 109 | Dbl_set_quiet(leftp1); | ||
| 110 | } | ||
| 111 | /* | ||
| 112 | * is second operand a signaling NaN? | ||
| 113 | */ | ||
| 114 | else if (Dbl_is_signalingnan(rightp1)) | ||
| 115 | { | ||
| 116 | /* trap if INVALIDTRAP enabled */ | ||
| 117 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 118 | /* make NaN quiet */ | ||
| 119 | Set_invalidflag(); | ||
| 120 | Dbl_set_quiet(rightp1); | ||
| 121 | Dbl_copytoptr(rightp1,rightp2,dstptr); | ||
| 122 | return(NOEXCEPTION); | ||
| 123 | } | ||
| 124 | /* | ||
| 125 | * return quiet NaN | ||
| 126 | */ | ||
| 127 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
| 128 | return(NOEXCEPTION); | ||
| 129 | } | ||
| 130 | } /* End left NaN or Infinity processing */ | ||
| 131 | /* | ||
| 132 | * check second operand for NaN's or infinity | ||
| 133 | */ | ||
| 134 | if (Dbl_isinfinity_exponent(rightp1)) | ||
| 135 | { | ||
| 136 | if (Dbl_iszero_mantissa(rightp1,rightp2)) | ||
| 137 | { | ||
| 138 | /* return infinity */ | ||
| 139 | Dbl_invert_sign(rightp1); | ||
| 140 | Dbl_copytoptr(rightp1,rightp2,dstptr); | ||
| 141 | return(NOEXCEPTION); | ||
| 142 | } | ||
| 143 | /* | ||
| 144 | * is NaN; signaling or quiet? | ||
| 145 | */ | ||
| 146 | if (Dbl_isone_signaling(rightp1)) | ||
| 147 | { | ||
| 148 | /* trap if INVALIDTRAP enabled */ | ||
| 149 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 150 | /* make NaN quiet */ | ||
| 151 | Set_invalidflag(); | ||
| 152 | Dbl_set_quiet(rightp1); | ||
| 153 | } | ||
| 154 | /* | ||
| 155 | * return quiet NaN | ||
| 156 | */ | ||
| 157 | Dbl_copytoptr(rightp1,rightp2,dstptr); | ||
| 158 | return(NOEXCEPTION); | ||
| 159 | } /* End right NaN or Infinity processing */ | ||
| 160 | |||
| 161 | /* Invariant: Must be dealing with finite numbers */ | ||
| 162 | |||
| 163 | /* Compare operands by removing the sign */ | ||
| 164 | Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left); | ||
| 165 | Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right); | ||
| 166 | |||
| 167 | /* sign difference selects add or sub operation. */ | ||
| 168 | if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right)) | ||
| 169 | { | ||
| 170 | /* Set the left operand to the larger one by XOR swap * | ||
| 171 | * First finish the first word using "save" */ | ||
| 172 | Dbl_xorfromintp1(save,rightp1,/*to*/rightp1); | ||
| 173 | Dbl_xorfromintp1(save,leftp1,/*to*/leftp1); | ||
| 174 | Dbl_swap_lower(leftp2,rightp2); | ||
| 175 | result_exponent = Dbl_exponent(leftp1); | ||
| 176 | Dbl_invert_sign(leftp1); | ||
| 177 | } | ||
| 178 | /* Invariant: left is not smaller than right. */ | ||
| 179 | |||
| 180 | if((right_exponent = Dbl_exponent(rightp1)) == 0) | ||
| 181 | { | ||
| 182 | /* Denormalized operands. First look for zeroes */ | ||
| 183 | if(Dbl_iszero_mantissa(rightp1,rightp2)) | ||
| 184 | { | ||
| 185 | /* right is zero */ | ||
| 186 | if(Dbl_iszero_exponentmantissa(leftp1,leftp2)) | ||
| 187 | { | ||
| 188 | /* Both operands are zeros */ | ||
| 189 | Dbl_invert_sign(rightp1); | ||
| 190 | if(Is_rounding_mode(ROUNDMINUS)) | ||
| 191 | { | ||
| 192 | Dbl_or_signs(leftp1,/*with*/rightp1); | ||
| 193 | } | ||
| 194 | else | ||
| 195 | { | ||
| 196 | Dbl_and_signs(leftp1,/*with*/rightp1); | ||
| 197 | } | ||
| 198 | } | ||
| 199 | else | ||
| 200 | { | ||
| 201 | /* Left is not a zero and must be the result. Trapped | ||
| 202 | * underflows are signaled if left is denormalized. Result | ||
| 203 | * is always exact. */ | ||
| 204 | if( (result_exponent == 0) && Is_underflowtrap_enabled() ) | ||
| 205 | { | ||
| 206 | /* need to normalize results mantissa */ | ||
| 207 | sign_save = Dbl_signextendedsign(leftp1); | ||
| 208 | Dbl_leftshiftby1(leftp1,leftp2); | ||
| 209 | Dbl_normalize(leftp1,leftp2,result_exponent); | ||
| 210 | Dbl_set_sign(leftp1,/*using*/sign_save); | ||
| 211 | Dbl_setwrapped_exponent(leftp1,result_exponent,unfl); | ||
| 212 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
| 213 | /* inexact = FALSE */ | ||
| 214 | return(UNDERFLOWEXCEPTION); | ||
| 215 | } | ||
| 216 | } | ||
| 217 | Dbl_copytoptr(leftp1,leftp2,dstptr); | ||
| 218 | return(NOEXCEPTION); | ||
| 219 | } | ||
| 220 | |||
| 221 | /* Neither are zeroes */ | ||
| 222 | Dbl_clear_sign(rightp1); /* Exponent is already cleared */ | ||
| 223 | if(result_exponent == 0 ) | ||
| 224 | { | ||
| 225 | /* Both operands are denormalized. The result must be exact | ||
| 226 | * and is simply calculated. A sum could become normalized and a | ||
| 227 | * difference could cancel to a true zero. */ | ||
| 228 | if( (/*signed*/int) save >= 0 ) | ||
| 229 | { | ||
| 230 | Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2, | ||
| 231 | /*into*/resultp1,resultp2); | ||
| 232 | if(Dbl_iszero_mantissa(resultp1,resultp2)) | ||
| 233 | { | ||
| 234 | if(Is_rounding_mode(ROUNDMINUS)) | ||
| 235 | { | ||
| 236 | Dbl_setone_sign(resultp1); | ||
| 237 | } | ||
| 238 | else | ||
| 239 | { | ||
| 240 | Dbl_setzero_sign(resultp1); | ||
| 241 | } | ||
| 242 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 243 | return(NOEXCEPTION); | ||
| 244 | } | ||
| 245 | } | ||
| 246 | else | ||
| 247 | { | ||
| 248 | Dbl_addition(leftp1,leftp2,rightp1,rightp2, | ||
| 249 | /*into*/resultp1,resultp2); | ||
| 250 | if(Dbl_isone_hidden(resultp1)) | ||
| 251 | { | ||
| 252 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 253 | return(NOEXCEPTION); | ||
| 254 | } | ||
| 255 | } | ||
| 256 | if(Is_underflowtrap_enabled()) | ||
| 257 | { | ||
| 258 | /* need to normalize result */ | ||
| 259 | sign_save = Dbl_signextendedsign(resultp1); | ||
| 260 | Dbl_leftshiftby1(resultp1,resultp2); | ||
| 261 | Dbl_normalize(resultp1,resultp2,result_exponent); | ||
| 262 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
| 263 | Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
| 264 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 265 | /* inexact = FALSE */ | ||
| 266 | return(UNDERFLOWEXCEPTION); | ||
| 267 | } | ||
| 268 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 269 | return(NOEXCEPTION); | ||
| 270 | } | ||
| 271 | right_exponent = 1; /* Set exponent to reflect different bias | ||
| 272 | * with denomalized numbers. */ | ||
| 273 | } | ||
| 274 | else | ||
| 275 | { | ||
| 276 | Dbl_clear_signexponent_set_hidden(rightp1); | ||
| 277 | } | ||
| 278 | Dbl_clear_exponent_set_hidden(leftp1); | ||
| 279 | diff_exponent = result_exponent - right_exponent; | ||
| 280 | |||
| 281 | /* | ||
| 282 | * Special case alignment of operands that would force alignment | ||
| 283 | * beyond the extent of the extension. A further optimization | ||
| 284 | * could special case this but only reduces the path length for this | ||
| 285 | * infrequent case. | ||
| 286 | */ | ||
| 287 | if(diff_exponent > DBL_THRESHOLD) | ||
| 288 | { | ||
| 289 | diff_exponent = DBL_THRESHOLD; | ||
| 290 | } | ||
| 291 | |||
| 292 | /* Align right operand by shifting to right */ | ||
| 293 | Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent, | ||
| 294 | /*and lower to*/extent); | ||
| 295 | |||
| 296 | /* Treat sum and difference of the operands separately. */ | ||
| 297 | if( (/*signed*/int) save >= 0 ) | ||
| 298 | { | ||
| 299 | /* | ||
| 300 | * Difference of the two operands. Their can be no overflow. A | ||
| 301 | * borrow can occur out of the hidden bit and force a post | ||
| 302 | * normalization phase. | ||
| 303 | */ | ||
| 304 | Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2, | ||
| 305 | /*with*/extent,/*into*/resultp1,resultp2); | ||
| 306 | if(Dbl_iszero_hidden(resultp1)) | ||
| 307 | { | ||
| 308 | /* Handle normalization */ | ||
| 309 | /* A straight foward algorithm would now shift the result | ||
| 310 | * and extension left until the hidden bit becomes one. Not | ||
| 311 | * all of the extension bits need participate in the shift. | ||
| 312 | * Only the two most significant bits (round and guard) are | ||
| 313 | * needed. If only a single shift is needed then the guard | ||
| 314 | * bit becomes a significant low order bit and the extension | ||
| 315 | * must participate in the rounding. If more than a single | ||
| 316 | * shift is needed, then all bits to the right of the guard | ||
| 317 | * bit are zeros, and the guard bit may or may not be zero. */ | ||
| 318 | sign_save = Dbl_signextendedsign(resultp1); | ||
| 319 | Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2); | ||
| 320 | |||
| 321 | /* Need to check for a zero result. The sign and exponent | ||
| 322 | * fields have already been zeroed. The more efficient test | ||
| 323 | * of the full object can be used. | ||
| 324 | */ | ||
| 325 | if(Dbl_iszero(resultp1,resultp2)) | ||
| 326 | /* Must have been "x-x" or "x+(-x)". */ | ||
| 327 | { | ||
| 328 | if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1); | ||
| 329 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 330 | return(NOEXCEPTION); | ||
| 331 | } | ||
| 332 | result_exponent--; | ||
| 333 | /* Look to see if normalization is finished. */ | ||
| 334 | if(Dbl_isone_hidden(resultp1)) | ||
| 335 | { | ||
| 336 | if(result_exponent==0) | ||
| 337 | { | ||
| 338 | /* Denormalized, exponent should be zero. Left operand * | ||
| 339 | * was normalized, so extent (guard, round) was zero */ | ||
| 340 | goto underflow; | ||
| 341 | } | ||
| 342 | else | ||
| 343 | { | ||
| 344 | /* No further normalization is needed. */ | ||
| 345 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
| 346 | Ext_leftshiftby1(extent); | ||
| 347 | goto round; | ||
| 348 | } | ||
| 349 | } | ||
| 350 | |||
| 351 | /* Check for denormalized, exponent should be zero. Left * | ||
| 352 | * operand was normalized, so extent (guard, round) was zero */ | ||
| 353 | if(!(underflowtrap = Is_underflowtrap_enabled()) && | ||
| 354 | result_exponent==0) goto underflow; | ||
| 355 | |||
| 356 | /* Shift extension to complete one bit of normalization and | ||
| 357 | * update exponent. */ | ||
| 358 | Ext_leftshiftby1(extent); | ||
| 359 | |||
| 360 | /* Discover first one bit to determine shift amount. Use a | ||
| 361 | * modified binary search. We have already shifted the result | ||
| 362 | * one position right and still not found a one so the remainder | ||
| 363 | * of the extension must be zero and simplifies rounding. */ | ||
| 364 | /* Scan bytes */ | ||
| 365 | while(Dbl_iszero_hiddenhigh7mantissa(resultp1)) | ||
| 366 | { | ||
| 367 | Dbl_leftshiftby8(resultp1,resultp2); | ||
| 368 | if((result_exponent -= 8) <= 0 && !underflowtrap) | ||
| 369 | goto underflow; | ||
| 370 | } | ||
| 371 | /* Now narrow it down to the nibble */ | ||
| 372 | if(Dbl_iszero_hiddenhigh3mantissa(resultp1)) | ||
| 373 | { | ||
| 374 | /* The lower nibble contains the normalizing one */ | ||
| 375 | Dbl_leftshiftby4(resultp1,resultp2); | ||
| 376 | if((result_exponent -= 4) <= 0 && !underflowtrap) | ||
| 377 | goto underflow; | ||
| 378 | } | ||
| 379 | /* Select case were first bit is set (already normalized) | ||
| 380 | * otherwise select the proper shift. */ | ||
| 381 | if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7) | ||
| 382 | { | ||
| 383 | /* Already normalized */ | ||
| 384 | if(result_exponent <= 0) goto underflow; | ||
| 385 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
| 386 | Dbl_set_exponent(resultp1,/*using*/result_exponent); | ||
| 387 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 388 | return(NOEXCEPTION); | ||
| 389 | } | ||
| 390 | Dbl_sethigh4bits(resultp1,/*using*/sign_save); | ||
| 391 | switch(jumpsize) | ||
| 392 | { | ||
| 393 | case 1: | ||
| 394 | { | ||
| 395 | Dbl_leftshiftby3(resultp1,resultp2); | ||
| 396 | result_exponent -= 3; | ||
| 397 | break; | ||
| 398 | } | ||
| 399 | case 2: | ||
| 400 | case 3: | ||
| 401 | { | ||
| 402 | Dbl_leftshiftby2(resultp1,resultp2); | ||
| 403 | result_exponent -= 2; | ||
| 404 | break; | ||
| 405 | } | ||
| 406 | case 4: | ||
| 407 | case 5: | ||
| 408 | case 6: | ||
| 409 | case 7: | ||
| 410 | { | ||
| 411 | Dbl_leftshiftby1(resultp1,resultp2); | ||
| 412 | result_exponent -= 1; | ||
| 413 | break; | ||
| 414 | } | ||
| 415 | } | ||
| 416 | if(result_exponent > 0) | ||
| 417 | { | ||
| 418 | Dbl_set_exponent(resultp1,/*using*/result_exponent); | ||
| 419 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 420 | return(NOEXCEPTION); /* Sign bit is already set */ | ||
| 421 | } | ||
| 422 | /* Fixup potential underflows */ | ||
| 423 | underflow: | ||
| 424 | if(Is_underflowtrap_enabled()) | ||
| 425 | { | ||
| 426 | Dbl_set_sign(resultp1,sign_save); | ||
| 427 | Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
| 428 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 429 | /* inexact = FALSE */ | ||
| 430 | return(UNDERFLOWEXCEPTION); | ||
| 431 | } | ||
| 432 | /* | ||
| 433 | * Since we cannot get an inexact denormalized result, | ||
| 434 | * we can now return. | ||
| 435 | */ | ||
| 436 | Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent); | ||
| 437 | Dbl_clear_signexponent(resultp1); | ||
| 438 | Dbl_set_sign(resultp1,sign_save); | ||
| 439 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 440 | return(NOEXCEPTION); | ||
| 441 | } /* end if(hidden...)... */ | ||
| 442 | /* Fall through and round */ | ||
| 443 | } /* end if(save >= 0)... */ | ||
| 444 | else | ||
| 445 | { | ||
| 446 | /* Subtract magnitudes */ | ||
| 447 | Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2); | ||
| 448 | if(Dbl_isone_hiddenoverflow(resultp1)) | ||
| 449 | { | ||
| 450 | /* Prenormalization required. */ | ||
| 451 | Dbl_rightshiftby1_withextent(resultp2,extent,extent); | ||
| 452 | Dbl_arithrightshiftby1(resultp1,resultp2); | ||
| 453 | result_exponent++; | ||
| 454 | } /* end if hiddenoverflow... */ | ||
| 455 | } /* end else ...subtract magnitudes... */ | ||
| 456 | |||
| 457 | /* Round the result. If the extension is all zeros,then the result is | ||
| 458 | * exact. Otherwise round in the correct direction. No underflow is | ||
| 459 | * possible. If a postnormalization is necessary, then the mantissa is | ||
| 460 | * all zeros so no shift is needed. */ | ||
| 461 | round: | ||
| 462 | if(Ext_isnotzero(extent)) | ||
| 463 | { | ||
| 464 | inexact = TRUE; | ||
| 465 | switch(Rounding_mode()) | ||
| 466 | { | ||
| 467 | case ROUNDNEAREST: /* The default. */ | ||
| 468 | if(Ext_isone_sign(extent)) | ||
| 469 | { | ||
| 470 | /* at least 1/2 ulp */ | ||
| 471 | if(Ext_isnotzero_lower(extent) || | ||
| 472 | Dbl_isone_lowmantissap2(resultp2)) | ||
| 473 | { | ||
| 474 | /* either exactly half way and odd or more than 1/2ulp */ | ||
| 475 | Dbl_increment(resultp1,resultp2); | ||
| 476 | } | ||
| 477 | } | ||
| 478 | break; | ||
| 479 | |||
| 480 | case ROUNDPLUS: | ||
| 481 | if(Dbl_iszero_sign(resultp1)) | ||
| 482 | { | ||
| 483 | /* Round up positive results */ | ||
| 484 | Dbl_increment(resultp1,resultp2); | ||
| 485 | } | ||
| 486 | break; | ||
| 487 | |||
| 488 | case ROUNDMINUS: | ||
| 489 | if(Dbl_isone_sign(resultp1)) | ||
| 490 | { | ||
| 491 | /* Round down negative results */ | ||
| 492 | Dbl_increment(resultp1,resultp2); | ||
| 493 | } | ||
| 494 | |||
| 495 | case ROUNDZERO:; | ||
| 496 | /* truncate is simple */ | ||
| 497 | } /* end switch... */ | ||
| 498 | if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++; | ||
| 499 | } | ||
| 500 | if(result_exponent == DBL_INFINITY_EXPONENT) | ||
| 501 | { | ||
| 502 | /* Overflow */ | ||
| 503 | if(Is_overflowtrap_enabled()) | ||
| 504 | { | ||
| 505 | Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl); | ||
| 506 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 507 | if (inexact) | ||
| 508 | if (Is_inexacttrap_enabled()) | ||
| 509 | return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
| 510 | else Set_inexactflag(); | ||
| 511 | return(OVERFLOWEXCEPTION); | ||
| 512 | } | ||
| 513 | else | ||
| 514 | { | ||
| 515 | inexact = TRUE; | ||
| 516 | Set_overflowflag(); | ||
| 517 | Dbl_setoverflow(resultp1,resultp2); | ||
| 518 | } | ||
| 519 | } | ||
| 520 | else Dbl_set_exponent(resultp1,result_exponent); | ||
| 521 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 522 | if(inexact) | ||
| 523 | if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 524 | else Set_inexactflag(); | ||
| 525 | return(NOEXCEPTION); | ||
| 526 | } | ||
diff --git a/arch/parisc/math-emu/driver.c b/arch/parisc/math-emu/driver.c new file mode 100644 index 000000000000..09ef4136c693 --- /dev/null +++ b/arch/parisc/math-emu/driver.c | |||
| @@ -0,0 +1,128 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * linux/arch/math-emu/driver.c.c | ||
| 23 | * | ||
| 24 | * decodes and dispatches unimplemented FPU instructions | ||
| 25 | * | ||
| 26 | * Copyright (C) 1999, 2000 Philipp Rumpf <prumpf@tux.org> | ||
| 27 | * Copyright (C) 2001 Hewlett-Packard <bame@debian.org> | ||
| 28 | */ | ||
| 29 | |||
| 30 | #include <linux/sched.h> | ||
| 31 | #include "float.h" | ||
| 32 | #include "math-emu.h" | ||
| 33 | |||
| 34 | |||
| 35 | #define fptpos 31 | ||
| 36 | #define fpr1pos 10 | ||
| 37 | #define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1)) | ||
| 38 | |||
| 39 | #define FPUDEBUG 0 | ||
| 40 | |||
| 41 | /* Format of the floating-point exception registers. */ | ||
| 42 | struct exc_reg { | ||
| 43 | unsigned int exception : 6; | ||
| 44 | unsigned int ei : 26; | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* Macros for grabbing bits of the instruction format from the 'ei' | ||
| 48 | field above. */ | ||
| 49 | /* Major opcode 0c and 0e */ | ||
| 50 | #define FP0CE_UID(i) (((i) >> 6) & 3) | ||
| 51 | #define FP0CE_CLASS(i) (((i) >> 9) & 3) | ||
| 52 | #define FP0CE_SUBOP(i) (((i) >> 13) & 7) | ||
| 53 | #define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */ | ||
| 54 | #define FP0C_FORMAT(i) (((i) >> 11) & 3) | ||
| 55 | #define FP0E_FORMAT(i) (((i) >> 11) & 1) | ||
| 56 | |||
| 57 | /* Major opcode 0c, uid 2 (performance monitoring) */ | ||
| 58 | #define FPPM_SUBOP(i) (((i) >> 9) & 0x1f) | ||
| 59 | |||
| 60 | /* Major opcode 2e (fused operations). */ | ||
| 61 | #define FP2E_SUBOP(i) (((i) >> 5) & 1) | ||
| 62 | #define FP2E_FORMAT(i) (((i) >> 11) & 1) | ||
| 63 | |||
| 64 | /* Major opcode 26 (FMPYSUB) */ | ||
| 65 | /* Major opcode 06 (FMPYADD) */ | ||
| 66 | #define FPx6_FORMAT(i) ((i) & 0x1f) | ||
| 67 | |||
| 68 | /* Flags and enable bits of the status word. */ | ||
| 69 | #define FPSW_FLAGS(w) ((w) >> 27) | ||
| 70 | #define FPSW_ENABLE(w) ((w) & 0x1f) | ||
| 71 | #define FPSW_V (1<<4) | ||
| 72 | #define FPSW_Z (1<<3) | ||
| 73 | #define FPSW_O (1<<2) | ||
| 74 | #define FPSW_U (1<<1) | ||
| 75 | #define FPSW_I (1<<0) | ||
| 76 | |||
| 77 | /* Handle a floating point exception. Return zero if the faulting | ||
| 78 | instruction can be completed successfully. */ | ||
| 79 | int | ||
| 80 | handle_fpe(struct pt_regs *regs) | ||
| 81 | { | ||
| 82 | extern void printbinary(unsigned long x, int nbits); | ||
| 83 | struct siginfo si; | ||
| 84 | unsigned int orig_sw, sw; | ||
| 85 | int signalcode; | ||
| 86 | /* need an intermediate copy of float regs because FPU emulation | ||
| 87 | * code expects an artificial last entry which contains zero | ||
| 88 | * | ||
| 89 | * also, the passed in fr registers contain one word that defines | ||
| 90 | * the fpu type. the fpu type information is constructed | ||
| 91 | * inside the emulation code | ||
| 92 | */ | ||
| 93 | __u64 frcopy[36]; | ||
| 94 | |||
| 95 | memcpy(frcopy, regs->fr, sizeof regs->fr); | ||
| 96 | frcopy[32] = 0; | ||
| 97 | |||
| 98 | memcpy(&orig_sw, frcopy, sizeof(orig_sw)); | ||
| 99 | |||
| 100 | if (FPUDEBUG) { | ||
| 101 | printk(KERN_DEBUG "FP VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI ->\n "); | ||
| 102 | printbinary(orig_sw, 32); | ||
| 103 | printk(KERN_DEBUG "\n"); | ||
| 104 | } | ||
| 105 | |||
| 106 | signalcode = decode_fpu(frcopy, 0x666); | ||
| 107 | |||
| 108 | /* Status word = FR0L. */ | ||
| 109 | memcpy(&sw, frcopy, sizeof(sw)); | ||
| 110 | if (FPUDEBUG) { | ||
| 111 | printk(KERN_DEBUG "VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI decode_fpu returns %d|0x%x\n", | ||
| 112 | signalcode >> 24, signalcode & 0xffffff); | ||
| 113 | printbinary(sw, 32); | ||
| 114 | printk(KERN_DEBUG "\n"); | ||
| 115 | } | ||
| 116 | |||
| 117 | memcpy(regs->fr, frcopy, sizeof regs->fr); | ||
| 118 | if (signalcode != 0) { | ||
| 119 | si.si_signo = signalcode >> 24; | ||
| 120 | si.si_errno = 0; | ||
| 121 | si.si_code = signalcode & 0xffffff; | ||
| 122 | si.si_addr = (void __user *) regs->iaoq[0]; | ||
| 123 | force_sig_info(si.si_signo, &si, current); | ||
| 124 | return -1; | ||
| 125 | } | ||
| 126 | |||
| 127 | return signalcode ? -1 : 0; | ||
| 128 | } | ||
diff --git a/arch/parisc/math-emu/fcnvff.c b/arch/parisc/math-emu/fcnvff.c new file mode 100644 index 000000000000..76c063f7d17c --- /dev/null +++ b/arch/parisc/math-emu/fcnvff.c | |||
| @@ -0,0 +1,309 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/fcnvff.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Single Floating-point to Double Floating-point | ||
| 29 | * Double Floating-point to Single Floating-point | ||
| 30 | * | ||
| 31 | * External Interfaces: | ||
| 32 | * dbl_to_sgl_fcnvff(srcptr,nullptr,dstptr,status) | ||
| 33 | * sgl_to_dbl_fcnvff(srcptr,nullptr,dstptr,status) | ||
| 34 | * | ||
| 35 | * Internal Interfaces: | ||
| 36 | * | ||
| 37 | * Theory: | ||
| 38 | * <<please update with a overview of the operation of this file>> | ||
| 39 | * | ||
| 40 | * END_DESC | ||
| 41 | */ | ||
| 42 | |||
| 43 | |||
| 44 | #include "float.h" | ||
| 45 | #include "sgl_float.h" | ||
| 46 | #include "dbl_float.h" | ||
| 47 | #include "cnv_float.h" | ||
| 48 | |||
| 49 | /* | ||
| 50 | * Single Floating-point to Double Floating-point | ||
| 51 | */ | ||
| 52 | /*ARGSUSED*/ | ||
| 53 | int | ||
| 54 | sgl_to_dbl_fcnvff( | ||
| 55 | sgl_floating_point *srcptr, | ||
| 56 | unsigned int *nullptr, | ||
| 57 | dbl_floating_point *dstptr, | ||
| 58 | unsigned int *status) | ||
| 59 | { | ||
| 60 | register unsigned int src, resultp1, resultp2; | ||
| 61 | register int src_exponent; | ||
| 62 | |||
| 63 | src = *srcptr; | ||
| 64 | src_exponent = Sgl_exponent(src); | ||
| 65 | Dbl_allp1(resultp1) = Sgl_all(src); /* set sign of result */ | ||
| 66 | /* | ||
| 67 | * Test for NaN or infinity | ||
| 68 | */ | ||
| 69 | if (src_exponent == SGL_INFINITY_EXPONENT) { | ||
| 70 | /* | ||
| 71 | * determine if NaN or infinity | ||
| 72 | */ | ||
| 73 | if (Sgl_iszero_mantissa(src)) { | ||
| 74 | /* | ||
| 75 | * is infinity; want to return double infinity | ||
| 76 | */ | ||
| 77 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
| 78 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 79 | return(NOEXCEPTION); | ||
| 80 | } | ||
| 81 | else { | ||
| 82 | /* | ||
| 83 | * is NaN; signaling or quiet? | ||
| 84 | */ | ||
| 85 | if (Sgl_isone_signaling(src)) { | ||
| 86 | /* trap if INVALIDTRAP enabled */ | ||
| 87 | if (Is_invalidtrap_enabled()) | ||
| 88 | return(INVALIDEXCEPTION); | ||
| 89 | /* make NaN quiet */ | ||
| 90 | else { | ||
| 91 | Set_invalidflag(); | ||
| 92 | Sgl_set_quiet(src); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | /* | ||
| 96 | * NaN is quiet, return as double NaN | ||
| 97 | */ | ||
| 98 | Dbl_setinfinity_exponent(resultp1); | ||
| 99 | Sgl_to_dbl_mantissa(src,resultp1,resultp2); | ||
| 100 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 101 | return(NOEXCEPTION); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | /* | ||
| 105 | * Test for zero or denormalized | ||
| 106 | */ | ||
| 107 | if (src_exponent == 0) { | ||
| 108 | /* | ||
| 109 | * determine if zero or denormalized | ||
| 110 | */ | ||
| 111 | if (Sgl_isnotzero_mantissa(src)) { | ||
| 112 | /* | ||
| 113 | * is denormalized; want to normalize | ||
| 114 | */ | ||
| 115 | Sgl_clear_signexponent(src); | ||
| 116 | Sgl_leftshiftby1(src); | ||
| 117 | Sgl_normalize(src,src_exponent); | ||
| 118 | Sgl_to_dbl_exponent(src_exponent,resultp1); | ||
| 119 | Sgl_to_dbl_mantissa(src,resultp1,resultp2); | ||
| 120 | } | ||
| 121 | else { | ||
| 122 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
| 123 | } | ||
| 124 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 125 | return(NOEXCEPTION); | ||
| 126 | } | ||
| 127 | /* | ||
| 128 | * No special cases, just complete the conversion | ||
| 129 | */ | ||
| 130 | Sgl_to_dbl_exponent(src_exponent, resultp1); | ||
| 131 | Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2); | ||
| 132 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 133 | return(NOEXCEPTION); | ||
| 134 | } | ||
| 135 | |||
| 136 | /* | ||
| 137 | * Double Floating-point to Single Floating-point | ||
| 138 | */ | ||
| 139 | /*ARGSUSED*/ | ||
| 140 | int | ||
| 141 | dbl_to_sgl_fcnvff( | ||
| 142 | dbl_floating_point *srcptr, | ||
| 143 | unsigned int *nullptr, | ||
| 144 | sgl_floating_point *dstptr, | ||
| 145 | unsigned int *status) | ||
| 146 | { | ||
| 147 | register unsigned int srcp1, srcp2, result; | ||
| 148 | register int src_exponent, dest_exponent, dest_mantissa; | ||
| 149 | register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; | ||
| 150 | register boolean lsb_odd = FALSE; | ||
| 151 | boolean is_tiny; | ||
| 152 | |||
| 153 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
| 154 | src_exponent = Dbl_exponent(srcp1); | ||
| 155 | Sgl_all(result) = Dbl_allp1(srcp1); /* set sign of result */ | ||
| 156 | /* | ||
| 157 | * Test for NaN or infinity | ||
| 158 | */ | ||
| 159 | if (src_exponent == DBL_INFINITY_EXPONENT) { | ||
| 160 | /* | ||
| 161 | * determine if NaN or infinity | ||
| 162 | */ | ||
| 163 | if (Dbl_iszero_mantissa(srcp1,srcp2)) { | ||
| 164 | /* | ||
| 165 | * is infinity; want to return single infinity | ||
| 166 | */ | ||
| 167 | Sgl_setinfinity_exponentmantissa(result); | ||
| 168 | *dstptr = result; | ||
| 169 | return(NOEXCEPTION); | ||
| 170 | } | ||
| 171 | /* | ||
| 172 | * is NaN; signaling or quiet? | ||
| 173 | */ | ||
| 174 | if (Dbl_isone_signaling(srcp1)) { | ||
| 175 | /* trap if INVALIDTRAP enabled */ | ||
| 176 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 177 | else { | ||
| 178 | Set_invalidflag(); | ||
| 179 | /* make NaN quiet */ | ||
| 180 | Dbl_set_quiet(srcp1); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | /* | ||
| 184 | * NaN is quiet, return as single NaN | ||
| 185 | */ | ||
| 186 | Sgl_setinfinity_exponent(result); | ||
| 187 | Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29); | ||
| 188 | if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result); | ||
| 189 | *dstptr = result; | ||
| 190 | return(NOEXCEPTION); | ||
| 191 | } | ||
| 192 | /* | ||
| 193 | * Generate result | ||
| 194 | */ | ||
| 195 | Dbl_to_sgl_exponent(src_exponent,dest_exponent); | ||
| 196 | if (dest_exponent > 0) { | ||
| 197 | Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit, | ||
| 198 | stickybit,lsb_odd); | ||
| 199 | } | ||
| 200 | else { | ||
| 201 | if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){ | ||
| 202 | Sgl_setzero_exponentmantissa(result); | ||
| 203 | *dstptr = result; | ||
| 204 | return(NOEXCEPTION); | ||
| 205 | } | ||
| 206 | if (Is_underflowtrap_enabled()) { | ||
| 207 | Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact, | ||
| 208 | guardbit,stickybit,lsb_odd); | ||
| 209 | } | ||
| 210 | else { | ||
| 211 | /* compute result, determine inexact info, | ||
| 212 | * and set Underflowflag if appropriate | ||
| 213 | */ | ||
| 214 | Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent, | ||
| 215 | dest_mantissa,inexact,guardbit,stickybit,lsb_odd, | ||
| 216 | is_tiny); | ||
| 217 | } | ||
| 218 | } | ||
| 219 | /* | ||
| 220 | * Now round result if not exact | ||
| 221 | */ | ||
| 222 | if (inexact) { | ||
| 223 | switch (Rounding_mode()) { | ||
| 224 | case ROUNDPLUS: | ||
| 225 | if (Sgl_iszero_sign(result)) dest_mantissa++; | ||
| 226 | break; | ||
| 227 | case ROUNDMINUS: | ||
| 228 | if (Sgl_isone_sign(result)) dest_mantissa++; | ||
| 229 | break; | ||
| 230 | case ROUNDNEAREST: | ||
| 231 | if (guardbit) { | ||
| 232 | if (stickybit || lsb_odd) dest_mantissa++; | ||
| 233 | } | ||
| 234 | } | ||
| 235 | } | ||
| 236 | Sgl_set_exponentmantissa(result,dest_mantissa); | ||
| 237 | |||
| 238 | /* | ||
| 239 | * check for mantissa overflow after rounding | ||
| 240 | */ | ||
| 241 | if ((dest_exponent>0 || Is_underflowtrap_enabled()) && | ||
| 242 | Sgl_isone_hidden(result)) dest_exponent++; | ||
| 243 | |||
| 244 | /* | ||
| 245 | * Test for overflow | ||
| 246 | */ | ||
| 247 | if (dest_exponent >= SGL_INFINITY_EXPONENT) { | ||
| 248 | /* trap if OVERFLOWTRAP enabled */ | ||
| 249 | if (Is_overflowtrap_enabled()) { | ||
| 250 | /* | ||
| 251 | * Check for gross overflow | ||
| 252 | */ | ||
| 253 | if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP) | ||
| 254 | return(UNIMPLEMENTEDEXCEPTION); | ||
| 255 | |||
| 256 | /* | ||
| 257 | * Adjust bias of result | ||
| 258 | */ | ||
| 259 | Sgl_setwrapped_exponent(result,dest_exponent,ovfl); | ||
| 260 | *dstptr = result; | ||
| 261 | if (inexact) | ||
| 262 | if (Is_inexacttrap_enabled()) | ||
| 263 | return(OVERFLOWEXCEPTION|INEXACTEXCEPTION); | ||
| 264 | else Set_inexactflag(); | ||
| 265 | return(OVERFLOWEXCEPTION); | ||
| 266 | } | ||
| 267 | Set_overflowflag(); | ||
| 268 | inexact = TRUE; | ||
| 269 | /* set result to infinity or largest number */ | ||
| 270 | Sgl_setoverflow(result); | ||
| 271 | } | ||
| 272 | /* | ||
| 273 | * Test for underflow | ||
| 274 | */ | ||
| 275 | else if (dest_exponent <= 0) { | ||
| 276 | /* trap if UNDERFLOWTRAP enabled */ | ||
| 277 | if (Is_underflowtrap_enabled()) { | ||
| 278 | /* | ||
| 279 | * Check for gross underflow | ||
| 280 | */ | ||
| 281 | if (dest_exponent <= -(SGL_WRAP)) | ||
| 282 | return(UNIMPLEMENTEDEXCEPTION); | ||
| 283 | /* | ||
| 284 | * Adjust bias of result | ||
| 285 | */ | ||
| 286 | Sgl_setwrapped_exponent(result,dest_exponent,unfl); | ||
| 287 | *dstptr = result; | ||
| 288 | if (inexact) | ||
| 289 | if (Is_inexacttrap_enabled()) | ||
| 290 | return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION); | ||
| 291 | else Set_inexactflag(); | ||
| 292 | return(UNDERFLOWEXCEPTION); | ||
| 293 | } | ||
| 294 | /* | ||
| 295 | * result is denormalized or signed zero | ||
| 296 | */ | ||
| 297 | if (inexact && is_tiny) Set_underflowflag(); | ||
| 298 | |||
| 299 | } | ||
| 300 | else Sgl_set_exponent(result,dest_exponent); | ||
| 301 | *dstptr = result; | ||
| 302 | /* | ||
| 303 | * Trap if inexact trap is enabled | ||
| 304 | */ | ||
| 305 | if (inexact) | ||
| 306 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 307 | else Set_inexactflag(); | ||
| 308 | return(NOEXCEPTION); | ||
| 309 | } | ||
diff --git a/arch/parisc/math-emu/fcnvfu.c b/arch/parisc/math-emu/fcnvfu.c new file mode 100644 index 000000000000..7e8565537bf5 --- /dev/null +++ b/arch/parisc/math-emu/fcnvfu.c | |||
| @@ -0,0 +1,536 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/fcnvfu.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Floating-point to Unsigned Fixed-point Converts | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * dbl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status) | ||
| 32 | * dbl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status) | ||
| 33 | * sgl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status) | ||
| 34 | * sgl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status) | ||
| 35 | * | ||
| 36 | * Internal Interfaces: | ||
| 37 | * | ||
| 38 | * Theory: | ||
| 39 | * <<please update with a overview of the operation of this file>> | ||
| 40 | * | ||
| 41 | * END_DESC | ||
| 42 | */ | ||
| 43 | |||
| 44 | |||
| 45 | #include "float.h" | ||
| 46 | #include "sgl_float.h" | ||
| 47 | #include "dbl_float.h" | ||
| 48 | #include "cnv_float.h" | ||
| 49 | |||
| 50 | /************************************************************************ | ||
| 51 | * Floating-point to Unsigned Fixed-point Converts * | ||
| 52 | ************************************************************************/ | ||
| 53 | |||
| 54 | /* | ||
| 55 | * Single Floating-point to Single Unsigned Fixed | ||
| 56 | */ | ||
| 57 | /*ARGSUSED*/ | ||
| 58 | int | ||
| 59 | sgl_to_sgl_fcnvfu( | ||
| 60 | sgl_floating_point *srcptr, | ||
| 61 | unsigned int *nullptr, | ||
| 62 | unsigned int *dstptr, | ||
| 63 | unsigned int *status) | ||
| 64 | { | ||
| 65 | register unsigned int src, result; | ||
| 66 | register int src_exponent; | ||
| 67 | register boolean inexact = FALSE; | ||
| 68 | |||
| 69 | src = *srcptr; | ||
| 70 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
| 71 | |||
| 72 | /* | ||
| 73 | * Test for overflow | ||
| 74 | */ | ||
| 75 | if (src_exponent > SGL_FX_MAX_EXP + 1) { | ||
| 76 | if (Sgl_isone_sign(src)) { | ||
| 77 | result = 0; | ||
| 78 | } else { | ||
| 79 | result = 0xffffffff; | ||
| 80 | } | ||
| 81 | if (Is_invalidtrap_enabled()) { | ||
| 82 | return(INVALIDEXCEPTION); | ||
| 83 | } | ||
| 84 | Set_invalidflag(); | ||
| 85 | *dstptr = result; | ||
| 86 | return(NOEXCEPTION); | ||
| 87 | } | ||
| 88 | /* | ||
| 89 | * Generate result | ||
| 90 | */ | ||
| 91 | if (src_exponent >= 0) { | ||
| 92 | /* | ||
| 93 | * Check sign. | ||
| 94 | * If negative, trap unimplemented. | ||
| 95 | */ | ||
| 96 | if (Sgl_isone_sign(src)) { | ||
| 97 | result = 0; | ||
| 98 | if (Is_invalidtrap_enabled()) { | ||
| 99 | return(INVALIDEXCEPTION); | ||
| 100 | } | ||
| 101 | Set_invalidflag(); | ||
| 102 | *dstptr = result; | ||
| 103 | return(NOEXCEPTION); | ||
| 104 | } | ||
| 105 | Sgl_clear_signexponent_set_hidden(src); | ||
| 106 | Suint_from_sgl_mantissa(src,src_exponent,result); | ||
| 107 | |||
| 108 | /* check for inexact */ | ||
| 109 | if (Sgl_isinexact_to_unsigned(src,src_exponent)) { | ||
| 110 | inexact = TRUE; | ||
| 111 | /* round result */ | ||
| 112 | switch (Rounding_mode()) { | ||
| 113 | case ROUNDPLUS: | ||
| 114 | result++; | ||
| 115 | break; | ||
| 116 | case ROUNDMINUS: /* never negative */ | ||
| 117 | break; | ||
| 118 | case ROUNDNEAREST: | ||
| 119 | if (Sgl_isone_roundbit(src,src_exponent) && | ||
| 120 | (Sgl_isone_stickybit(src,src_exponent) || | ||
| 121 | (result & 1))) { | ||
| 122 | result++; | ||
| 123 | } | ||
| 124 | break; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | } else { | ||
| 128 | result = 0; | ||
| 129 | |||
| 130 | /* check for inexact */ | ||
| 131 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
| 132 | inexact = TRUE; | ||
| 133 | /* round result */ | ||
| 134 | switch (Rounding_mode()) { | ||
| 135 | case ROUNDPLUS: | ||
| 136 | if (Sgl_iszero_sign(src)) { | ||
| 137 | result++; | ||
| 138 | } | ||
| 139 | break; | ||
| 140 | case ROUNDMINUS: | ||
| 141 | if (Sgl_isone_sign(src)) { | ||
| 142 | result = 0; | ||
| 143 | if (Is_invalidtrap_enabled()) { | ||
| 144 | return(INVALIDEXCEPTION); | ||
| 145 | } | ||
| 146 | Set_invalidflag(); | ||
| 147 | inexact = FALSE; | ||
| 148 | } | ||
| 149 | break; | ||
| 150 | case ROUNDNEAREST: | ||
| 151 | if (src_exponent == -1 && | ||
| 152 | Sgl_isnotzero_mantissa(src)) { | ||
| 153 | if (Sgl_isone_sign(src)) { | ||
| 154 | result = 0; | ||
| 155 | if (Is_invalidtrap_enabled()) { | ||
| 156 | return(INVALIDEXCEPTION); | ||
| 157 | } | ||
| 158 | Set_invalidflag(); | ||
| 159 | inexact = FALSE; | ||
| 160 | } | ||
| 161 | else result++; | ||
| 162 | } | ||
| 163 | break; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | } | ||
| 167 | *dstptr = result; | ||
| 168 | if (inexact) { | ||
| 169 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 170 | else Set_inexactflag(); | ||
| 171 | } | ||
| 172 | return(NOEXCEPTION); | ||
| 173 | } | ||
| 174 | |||
| 175 | /* | ||
| 176 | * Single Floating-point to Double Unsigned Fixed | ||
| 177 | */ | ||
| 178 | /*ARGSUSED*/ | ||
| 179 | int | ||
| 180 | sgl_to_dbl_fcnvfu( | ||
| 181 | sgl_floating_point *srcptr, | ||
| 182 | unsigned int *nullptr, | ||
| 183 | dbl_unsigned *dstptr, | ||
| 184 | unsigned int *status) | ||
| 185 | { | ||
| 186 | register int src_exponent; | ||
| 187 | register unsigned int src, resultp1, resultp2; | ||
| 188 | register boolean inexact = FALSE; | ||
| 189 | |||
| 190 | src = *srcptr; | ||
| 191 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
| 192 | |||
| 193 | /* | ||
| 194 | * Test for overflow | ||
| 195 | */ | ||
| 196 | if (src_exponent > DBL_FX_MAX_EXP + 1) { | ||
| 197 | if (Sgl_isone_sign(src)) { | ||
| 198 | resultp1 = resultp2 = 0; | ||
| 199 | } else { | ||
| 200 | resultp1 = resultp2 = 0xffffffff; | ||
| 201 | } | ||
| 202 | if (Is_invalidtrap_enabled()) { | ||
| 203 | return(INVALIDEXCEPTION); | ||
| 204 | } | ||
| 205 | Set_invalidflag(); | ||
| 206 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
| 207 | return(NOEXCEPTION); | ||
| 208 | } | ||
| 209 | /* | ||
| 210 | * Generate result | ||
| 211 | */ | ||
| 212 | if (src_exponent >= 0) { | ||
| 213 | /* | ||
| 214 | * Check sign. | ||
| 215 | * If negative, trap unimplemented. | ||
| 216 | */ | ||
| 217 | if (Sgl_isone_sign(src)) { | ||
| 218 | resultp1 = resultp2 = 0; | ||
| 219 | if (Is_invalidtrap_enabled()) { | ||
| 220 | return(INVALIDEXCEPTION); | ||
| 221 | } | ||
| 222 | Set_invalidflag(); | ||
| 223 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
| 224 | return(NOEXCEPTION); | ||
| 225 | } | ||
| 226 | Sgl_clear_signexponent_set_hidden(src); | ||
| 227 | Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2); | ||
| 228 | |||
| 229 | /* check for inexact */ | ||
| 230 | if (Sgl_isinexact_to_unsigned(src,src_exponent)) { | ||
| 231 | inexact = TRUE; | ||
| 232 | /* round result */ | ||
| 233 | switch (Rounding_mode()) { | ||
| 234 | case ROUNDPLUS: | ||
| 235 | Duint_increment(resultp1,resultp2); | ||
| 236 | break; | ||
| 237 | case ROUNDMINUS: /* never negative */ | ||
| 238 | break; | ||
| 239 | case ROUNDNEAREST: | ||
| 240 | if (Sgl_isone_roundbit(src,src_exponent) && | ||
| 241 | (Sgl_isone_stickybit(src,src_exponent) || | ||
| 242 | Duint_isone_lowp2(resultp2))) { | ||
| 243 | Duint_increment(resultp1,resultp2); | ||
| 244 | } | ||
| 245 | break; | ||
| 246 | } | ||
| 247 | } | ||
| 248 | } else { | ||
| 249 | Duint_setzero(resultp1,resultp2); | ||
| 250 | |||
| 251 | /* check for inexact */ | ||
| 252 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
| 253 | inexact = TRUE; | ||
| 254 | /* round result */ | ||
| 255 | switch (Rounding_mode()) { | ||
| 256 | case ROUNDPLUS: | ||
| 257 | if (Sgl_iszero_sign(src)) { | ||
| 258 | Duint_increment(resultp1,resultp2); | ||
| 259 | } | ||
| 260 | break; | ||
| 261 | case ROUNDMINUS: | ||
| 262 | if (Sgl_isone_sign(src)) { | ||
| 263 | resultp1 = resultp2 = 0; | ||
| 264 | if (Is_invalidtrap_enabled()) { | ||
| 265 | return(INVALIDEXCEPTION); | ||
| 266 | } | ||
| 267 | Set_invalidflag(); | ||
| 268 | inexact = FALSE; | ||
| 269 | } | ||
| 270 | break; | ||
| 271 | case ROUNDNEAREST: | ||
| 272 | if (src_exponent == -1 && | ||
| 273 | Sgl_isnotzero_mantissa(src)) { | ||
| 274 | if (Sgl_isone_sign(src)) { | ||
| 275 | resultp1 = 0; | ||
| 276 | resultp2 = 0; | ||
| 277 | if (Is_invalidtrap_enabled()) { | ||
| 278 | return(INVALIDEXCEPTION); | ||
| 279 | } | ||
| 280 | Set_invalidflag(); | ||
| 281 | inexact = FALSE; | ||
| 282 | } | ||
| 283 | else Duint_increment(resultp1,resultp2); | ||
| 284 | } | ||
| 285 | } | ||
| 286 | } | ||
| 287 | } | ||
| 288 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
| 289 | if (inexact) { | ||
| 290 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 291 | else Set_inexactflag(); | ||
| 292 | } | ||
| 293 | return(NOEXCEPTION); | ||
| 294 | } | ||
| 295 | |||
| 296 | /* | ||
| 297 | * Double Floating-point to Single Unsigned Fixed | ||
| 298 | */ | ||
| 299 | /*ARGSUSED*/ | ||
| 300 | int | ||
| 301 | dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr, | ||
| 302 | unsigned int *dstptr, unsigned int *status) | ||
| 303 | { | ||
| 304 | register unsigned int srcp1, srcp2, result; | ||
| 305 | register int src_exponent; | ||
| 306 | register boolean inexact = FALSE; | ||
| 307 | |||
| 308 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
| 309 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
| 310 | |||
| 311 | /* | ||
| 312 | * Test for overflow | ||
| 313 | */ | ||
| 314 | if (src_exponent > SGL_FX_MAX_EXP + 1) { | ||
| 315 | if (Dbl_isone_sign(srcp1)) { | ||
| 316 | result = 0; | ||
| 317 | } else { | ||
| 318 | result = 0xffffffff; | ||
| 319 | } | ||
| 320 | if (Is_invalidtrap_enabled()) { | ||
| 321 | return(INVALIDEXCEPTION); | ||
| 322 | } | ||
| 323 | Set_invalidflag(); | ||
| 324 | *dstptr = result; | ||
| 325 | return(NOEXCEPTION); | ||
| 326 | } | ||
| 327 | /* | ||
| 328 | * Generate result | ||
| 329 | */ | ||
| 330 | if (src_exponent >= 0) { | ||
| 331 | /* | ||
| 332 | * Check sign. | ||
| 333 | * If negative, trap unimplemented. | ||
| 334 | */ | ||
| 335 | if (Dbl_isone_sign(srcp1)) { | ||
| 336 | result = 0; | ||
| 337 | if (Is_invalidtrap_enabled()) { | ||
| 338 | return(INVALIDEXCEPTION); | ||
| 339 | } | ||
| 340 | Set_invalidflag(); | ||
| 341 | *dstptr = result; | ||
| 342 | return(NOEXCEPTION); | ||
| 343 | } | ||
| 344 | Dbl_clear_signexponent_set_hidden(srcp1); | ||
| 345 | Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result); | ||
| 346 | |||
| 347 | /* check for inexact */ | ||
| 348 | if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) { | ||
| 349 | inexact = TRUE; | ||
| 350 | /* round result */ | ||
| 351 | switch (Rounding_mode()) { | ||
| 352 | case ROUNDPLUS: | ||
| 353 | result++; | ||
| 354 | break; | ||
| 355 | case ROUNDMINUS: /* never negative */ | ||
| 356 | break; | ||
| 357 | case ROUNDNEAREST: | ||
| 358 | if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent) && | ||
| 359 | (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)|| | ||
| 360 | result&1)) | ||
| 361 | result++; | ||
| 362 | break; | ||
| 363 | } | ||
| 364 | /* check for overflow */ | ||
| 365 | if (result == 0) { | ||
| 366 | result = 0xffffffff; | ||
| 367 | if (Is_invalidtrap_enabled()) { | ||
| 368 | return(INVALIDEXCEPTION); | ||
| 369 | } | ||
| 370 | Set_invalidflag(); | ||
| 371 | *dstptr = result; | ||
| 372 | return(NOEXCEPTION); | ||
| 373 | } | ||
| 374 | } | ||
| 375 | } else { | ||
| 376 | result = 0; | ||
| 377 | |||
| 378 | /* check for inexact */ | ||
| 379 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
| 380 | inexact = TRUE; | ||
| 381 | /* round result */ | ||
| 382 | switch (Rounding_mode()) { | ||
| 383 | case ROUNDPLUS: | ||
| 384 | if (Dbl_iszero_sign(srcp1)) result++; | ||
| 385 | break; | ||
| 386 | case ROUNDMINUS: | ||
| 387 | if (Dbl_isone_sign(srcp1)) { | ||
| 388 | result = 0; | ||
| 389 | if (Is_invalidtrap_enabled()) { | ||
| 390 | return(INVALIDEXCEPTION); | ||
| 391 | } | ||
| 392 | Set_invalidflag(); | ||
| 393 | inexact = FALSE; | ||
| 394 | } | ||
| 395 | break; | ||
| 396 | case ROUNDNEAREST: | ||
| 397 | if (src_exponent == -1 && | ||
| 398 | Dbl_isnotzero_mantissa(srcp1,srcp2)) | ||
| 399 | if (Dbl_isone_sign(srcp1)) { | ||
| 400 | result = 0; | ||
| 401 | if (Is_invalidtrap_enabled()) { | ||
| 402 | return(INVALIDEXCEPTION); | ||
| 403 | } | ||
| 404 | Set_invalidflag(); | ||
| 405 | inexact = FALSE; | ||
| 406 | } | ||
| 407 | else result++; | ||
| 408 | } | ||
| 409 | } | ||
| 410 | } | ||
| 411 | *dstptr = result; | ||
| 412 | if (inexact) { | ||
| 413 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 414 | else Set_inexactflag(); | ||
| 415 | } | ||
| 416 | return(NOEXCEPTION); | ||
| 417 | } | ||
| 418 | |||
| 419 | /* | ||
| 420 | * Double Floating-point to Double Unsigned Fixed | ||
| 421 | */ | ||
| 422 | /*ARGSUSED*/ | ||
| 423 | int | ||
| 424 | dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr, | ||
| 425 | dbl_unsigned * dstptr, unsigned int *status) | ||
| 426 | { | ||
| 427 | register int src_exponent; | ||
| 428 | register unsigned int srcp1, srcp2, resultp1, resultp2; | ||
| 429 | register boolean inexact = FALSE; | ||
| 430 | |||
| 431 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
| 432 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
| 433 | |||
| 434 | /* | ||
| 435 | * Test for overflow | ||
| 436 | */ | ||
| 437 | if (src_exponent > DBL_FX_MAX_EXP + 1) { | ||
| 438 | if (Dbl_isone_sign(srcp1)) { | ||
| 439 | resultp1 = resultp2 = 0; | ||
| 440 | } else { | ||
| 441 | resultp1 = resultp2 = 0xffffffff; | ||
| 442 | } | ||
| 443 | if (Is_invalidtrap_enabled()) { | ||
| 444 | return(INVALIDEXCEPTION); | ||
| 445 | } | ||
| 446 | Set_invalidflag(); | ||
| 447 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
| 448 | return(NOEXCEPTION); | ||
| 449 | } | ||
| 450 | |||
| 451 | /* | ||
| 452 | * Generate result | ||
| 453 | */ | ||
| 454 | if (src_exponent >= 0) { | ||
| 455 | /* | ||
| 456 | * Check sign. | ||
| 457 | * If negative, trap unimplemented. | ||
| 458 | */ | ||
| 459 | if (Dbl_isone_sign(srcp1)) { | ||
| 460 | resultp1 = resultp2 = 0; | ||
| 461 | if (Is_invalidtrap_enabled()) { | ||
| 462 | return(INVALIDEXCEPTION); | ||
| 463 | } | ||
| 464 | Set_invalidflag(); | ||
| 465 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
| 466 | return(NOEXCEPTION); | ||
| 467 | } | ||
| 468 | Dbl_clear_signexponent_set_hidden(srcp1); | ||
| 469 | Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1, | ||
| 470 | resultp2); | ||
| 471 | |||
| 472 | /* check for inexact */ | ||
| 473 | if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) { | ||
| 474 | inexact = TRUE; | ||
| 475 | /* round result */ | ||
| 476 | switch (Rounding_mode()) { | ||
| 477 | case ROUNDPLUS: | ||
| 478 | Duint_increment(resultp1,resultp2); | ||
| 479 | break; | ||
| 480 | case ROUNDMINUS: /* never negative */ | ||
| 481 | break; | ||
| 482 | case ROUNDNEAREST: | ||
| 483 | if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) | ||
| 484 | if(Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || | ||
| 485 | Duint_isone_lowp2(resultp2)) | ||
| 486 | Duint_increment(resultp1,resultp2); | ||
| 487 | } | ||
| 488 | } | ||
| 489 | } else { | ||
| 490 | Duint_setzero(resultp1,resultp2); | ||
| 491 | |||
| 492 | /* check for inexact */ | ||
| 493 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
| 494 | inexact = TRUE; | ||
| 495 | /* round result */ | ||
| 496 | switch (Rounding_mode()) { | ||
| 497 | case ROUNDPLUS: | ||
| 498 | if (Dbl_iszero_sign(srcp1)) { | ||
| 499 | Duint_increment(resultp1,resultp2); | ||
| 500 | } | ||
| 501 | break; | ||
| 502 | case ROUNDMINUS: | ||
| 503 | if (Dbl_isone_sign(srcp1)) { | ||
| 504 | resultp1 = resultp2 = 0; | ||
| 505 | if (Is_invalidtrap_enabled()) { | ||
| 506 | return(INVALIDEXCEPTION); | ||
| 507 | } | ||
| 508 | Set_invalidflag(); | ||
| 509 | inexact = FALSE; | ||
| 510 | } | ||
| 511 | break; | ||
| 512 | case ROUNDNEAREST: | ||
| 513 | if (src_exponent == -1 && | ||
| 514 | Dbl_isnotzero_mantissa(srcp1,srcp2)) | ||
| 515 | if (Dbl_iszero_sign(srcp1)) { | ||
| 516 | Duint_increment(resultp1,resultp2); | ||
| 517 | } else { | ||
| 518 | resultp1 = 0; | ||
| 519 | resultp2 = 0; | ||
| 520 | if (Is_invalidtrap_enabled()) { | ||
| 521 | return(INVALIDEXCEPTION); | ||
| 522 | } | ||
| 523 | Set_invalidflag(); | ||
| 524 | inexact = FALSE; | ||
| 525 | } | ||
| 526 | } | ||
| 527 | } | ||
| 528 | } | ||
| 529 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
| 530 | if (inexact) { | ||
| 531 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 532 | else Set_inexactflag(); | ||
| 533 | } | ||
| 534 | return(NOEXCEPTION); | ||
| 535 | } | ||
| 536 | |||
diff --git a/arch/parisc/math-emu/fcnvfut.c b/arch/parisc/math-emu/fcnvfut.c new file mode 100644 index 000000000000..4176a44ed750 --- /dev/null +++ b/arch/parisc/math-emu/fcnvfut.c | |||
| @@ -0,0 +1,332 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/fcnvfut.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Floating-point to Unsigned Fixed-point Converts with Truncation | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * dbl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status) | ||
| 32 | * dbl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status) | ||
| 33 | * sgl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status) | ||
| 34 | * sgl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status) | ||
| 35 | * | ||
| 36 | * Internal Interfaces: | ||
| 37 | * | ||
| 38 | * Theory: | ||
| 39 | * <<please update with a overview of the operation of this file>> | ||
| 40 | * | ||
| 41 | * END_DESC | ||
| 42 | */ | ||
| 43 | |||
| 44 | |||
| 45 | #include "float.h" | ||
| 46 | #include "sgl_float.h" | ||
| 47 | #include "dbl_float.h" | ||
| 48 | #include "cnv_float.h" | ||
| 49 | |||
| 50 | /************************************************************************ | ||
| 51 | * Floating-point to Unsigned Fixed-point Converts with Truncation * | ||
| 52 | ************************************************************************/ | ||
| 53 | |||
| 54 | /* | ||
| 55 | * Convert single floating-point to single fixed-point format | ||
| 56 | * with truncated result | ||
| 57 | */ | ||
| 58 | /*ARGSUSED*/ | ||
| 59 | int | ||
| 60 | sgl_to_sgl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr, | ||
| 61 | unsigned int *dstptr, unsigned int *status) | ||
| 62 | { | ||
| 63 | register unsigned int src, result; | ||
| 64 | register int src_exponent; | ||
| 65 | |||
| 66 | src = *srcptr; | ||
| 67 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
| 68 | |||
| 69 | /* | ||
| 70 | * Test for overflow | ||
| 71 | */ | ||
| 72 | if (src_exponent > SGL_FX_MAX_EXP + 1) { | ||
| 73 | if (Sgl_isone_sign(src)) { | ||
| 74 | result = 0; | ||
| 75 | } else { | ||
| 76 | result = 0xffffffff; | ||
| 77 | } | ||
| 78 | if (Is_invalidtrap_enabled()) { | ||
| 79 | return(INVALIDEXCEPTION); | ||
| 80 | } | ||
| 81 | Set_invalidflag(); | ||
| 82 | *dstptr = result; | ||
| 83 | return(NOEXCEPTION); | ||
| 84 | } | ||
| 85 | /* | ||
| 86 | * Generate result | ||
| 87 | */ | ||
| 88 | if (src_exponent >= 0) { | ||
| 89 | /* | ||
| 90 | * Check sign. | ||
| 91 | * If negative, trap unimplemented. | ||
| 92 | */ | ||
| 93 | if (Sgl_isone_sign(src)) { | ||
| 94 | result = 0; | ||
| 95 | if (Is_invalidtrap_enabled()) { | ||
| 96 | return(INVALIDEXCEPTION); | ||
| 97 | } | ||
| 98 | Set_invalidflag(); | ||
| 99 | *dstptr = result; | ||
| 100 | return(NOEXCEPTION); | ||
| 101 | } | ||
| 102 | Sgl_clear_signexponent_set_hidden(src); | ||
| 103 | Suint_from_sgl_mantissa(src,src_exponent,result); | ||
| 104 | *dstptr = result; | ||
| 105 | |||
| 106 | /* check for inexact */ | ||
| 107 | if (Sgl_isinexact_to_unsigned(src,src_exponent)) { | ||
| 108 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 109 | else Set_inexactflag(); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | else { | ||
| 113 | *dstptr = 0; | ||
| 114 | |||
| 115 | /* check for inexact */ | ||
| 116 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
| 117 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 118 | else Set_inexactflag(); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | return(NOEXCEPTION); | ||
| 122 | } | ||
| 123 | |||
| 124 | /* | ||
| 125 | * Single Floating-point to Double Unsigned Fixed | ||
| 126 | */ | ||
| 127 | /*ARGSUSED*/ | ||
| 128 | int | ||
| 129 | sgl_to_dbl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr, | ||
| 130 | dbl_unsigned * dstptr, unsigned int *status) | ||
| 131 | { | ||
| 132 | register int src_exponent; | ||
| 133 | register unsigned int src, resultp1, resultp2; | ||
| 134 | |||
| 135 | src = *srcptr; | ||
| 136 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
| 137 | |||
| 138 | /* | ||
| 139 | * Test for overflow | ||
| 140 | */ | ||
| 141 | if (src_exponent > DBL_FX_MAX_EXP + 1) { | ||
| 142 | if (Sgl_isone_sign(src)) { | ||
| 143 | resultp1 = resultp2 = 0; | ||
| 144 | } else { | ||
| 145 | resultp1 = resultp2 = 0xffffffff; | ||
| 146 | } | ||
| 147 | if (Is_invalidtrap_enabled()) { | ||
| 148 | return(INVALIDEXCEPTION); | ||
| 149 | } | ||
| 150 | Set_invalidflag(); | ||
| 151 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
| 152 | return(NOEXCEPTION); | ||
| 153 | } | ||
| 154 | /* | ||
| 155 | * Generate result | ||
| 156 | */ | ||
| 157 | if (src_exponent >= 0) { | ||
| 158 | /* | ||
| 159 | * Check sign. | ||
| 160 | * If negative, trap unimplemented. | ||
| 161 | */ | ||
| 162 | if (Sgl_isone_sign(src)) { | ||
| 163 | resultp1 = resultp2 = 0; | ||
| 164 | if (Is_invalidtrap_enabled()) { | ||
| 165 | return(INVALIDEXCEPTION); | ||
| 166 | } | ||
| 167 | Set_invalidflag(); | ||
| 168 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
| 169 | return(NOEXCEPTION); | ||
| 170 | } | ||
| 171 | Sgl_clear_signexponent_set_hidden(src); | ||
| 172 | Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2); | ||
| 173 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
| 174 | |||
| 175 | /* check for inexact */ | ||
| 176 | if (Sgl_isinexact_to_unsigned(src,src_exponent)) { | ||
| 177 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 178 | else Set_inexactflag(); | ||
| 179 | } | ||
| 180 | } | ||
| 181 | else { | ||
| 182 | Duint_setzero(resultp1,resultp2); | ||
| 183 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
| 184 | |||
| 185 | /* check for inexact */ | ||
| 186 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
| 187 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 188 | else Set_inexactflag(); | ||
| 189 | } | ||
| 190 | } | ||
| 191 | return(NOEXCEPTION); | ||
| 192 | } | ||
| 193 | |||
| 194 | /* | ||
| 195 | * Double Floating-point to Single Unsigned Fixed | ||
| 196 | */ | ||
| 197 | /*ARGSUSED*/ | ||
| 198 | int | ||
| 199 | dbl_to_sgl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr, | ||
| 200 | unsigned int *dstptr, unsigned int *status) | ||
| 201 | { | ||
| 202 | register unsigned int srcp1, srcp2, result; | ||
| 203 | register int src_exponent; | ||
| 204 | |||
| 205 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
| 206 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
| 207 | |||
| 208 | /* | ||
| 209 | * Test for overflow | ||
| 210 | */ | ||
| 211 | if (src_exponent > SGL_FX_MAX_EXP + 1) { | ||
| 212 | if (Dbl_isone_sign(srcp1)) { | ||
| 213 | result = 0; | ||
| 214 | } else { | ||
| 215 | result = 0xffffffff; | ||
| 216 | } | ||
| 217 | if (Is_invalidtrap_enabled()) { | ||
| 218 | return(INVALIDEXCEPTION); | ||
| 219 | } | ||
| 220 | Set_invalidflag(); | ||
| 221 | *dstptr = result; | ||
| 222 | return(NOEXCEPTION); | ||
| 223 | } | ||
| 224 | /* | ||
| 225 | * Generate result | ||
| 226 | */ | ||
| 227 | if (src_exponent >= 0) { | ||
| 228 | /* | ||
| 229 | * Check sign. | ||
| 230 | * If negative, trap unimplemented. | ||
| 231 | */ | ||
| 232 | if (Dbl_isone_sign(srcp1)) { | ||
| 233 | result = 0; | ||
| 234 | if (Is_invalidtrap_enabled()) { | ||
| 235 | return(INVALIDEXCEPTION); | ||
| 236 | } | ||
| 237 | Set_invalidflag(); | ||
| 238 | *dstptr = result; | ||
| 239 | return(NOEXCEPTION); | ||
| 240 | } | ||
| 241 | Dbl_clear_signexponent_set_hidden(srcp1); | ||
| 242 | Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result); | ||
| 243 | *dstptr = result; | ||
| 244 | |||
| 245 | /* check for inexact */ | ||
| 246 | if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) { | ||
| 247 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 248 | else Set_inexactflag(); | ||
| 249 | } | ||
| 250 | } | ||
| 251 | else { | ||
| 252 | *dstptr = 0; | ||
| 253 | |||
| 254 | /* check for inexact */ | ||
| 255 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
| 256 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 257 | else Set_inexactflag(); | ||
| 258 | } | ||
| 259 | } | ||
| 260 | return(NOEXCEPTION); | ||
| 261 | } | ||
| 262 | |||
| 263 | /* | ||
| 264 | * Double Floating-point to Double Unsigned Fixed | ||
| 265 | */ | ||
| 266 | /*ARGSUSED*/ | ||
| 267 | int | ||
| 268 | dbl_to_dbl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr, | ||
| 269 | dbl_unsigned * dstptr, unsigned int *status) | ||
| 270 | { | ||
| 271 | register int src_exponent; | ||
| 272 | register unsigned int srcp1, srcp2, resultp1, resultp2; | ||
| 273 | |||
| 274 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
| 275 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
| 276 | |||
| 277 | /* | ||
| 278 | * Test for overflow | ||
| 279 | */ | ||
| 280 | if (src_exponent > DBL_FX_MAX_EXP + 1) { | ||
| 281 | if (Dbl_isone_sign(srcp1)) { | ||
| 282 | resultp1 = resultp2 = 0; | ||
| 283 | } else { | ||
| 284 | resultp1 = resultp2 = 0xffffffff; | ||
| 285 | } | ||
| 286 | if (Is_invalidtrap_enabled()) { | ||
| 287 | return(INVALIDEXCEPTION); | ||
| 288 | } | ||
| 289 | Set_invalidflag(); | ||
| 290 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
| 291 | return(NOEXCEPTION); | ||
| 292 | } | ||
| 293 | /* | ||
| 294 | * Generate result | ||
| 295 | */ | ||
| 296 | if (src_exponent >= 0) { | ||
| 297 | /* | ||
| 298 | * Check sign. | ||
| 299 | * If negative, trap unimplemented. | ||
| 300 | */ | ||
| 301 | if (Dbl_isone_sign(srcp1)) { | ||
| 302 | resultp1 = resultp2 = 0; | ||
| 303 | if (Is_invalidtrap_enabled()) { | ||
| 304 | return(INVALIDEXCEPTION); | ||
| 305 | } | ||
| 306 | Set_invalidflag(); | ||
| 307 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
| 308 | return(NOEXCEPTION); | ||
| 309 | } | ||
| 310 | Dbl_clear_signexponent_set_hidden(srcp1); | ||
| 311 | Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent, | ||
| 312 | resultp1,resultp2); | ||
| 313 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
| 314 | |||
| 315 | /* check for inexact */ | ||
| 316 | if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) { | ||
| 317 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 318 | else Set_inexactflag(); | ||
| 319 | } | ||
| 320 | } | ||
| 321 | else { | ||
| 322 | Duint_setzero(resultp1,resultp2); | ||
| 323 | Duint_copytoptr(resultp1,resultp2,dstptr); | ||
| 324 | |||
| 325 | /* check for inexact */ | ||
| 326 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
| 327 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 328 | else Set_inexactflag(); | ||
| 329 | } | ||
| 330 | } | ||
| 331 | return(NOEXCEPTION); | ||
| 332 | } | ||
diff --git a/arch/parisc/math-emu/fcnvfx.c b/arch/parisc/math-emu/fcnvfx.c new file mode 100644 index 000000000000..d6475bddb507 --- /dev/null +++ b/arch/parisc/math-emu/fcnvfx.c | |||
| @@ -0,0 +1,501 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/fcnvfx.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Single Floating-point to Single Fixed-point | ||
| 29 | * Single Floating-point to Double Fixed-point | ||
| 30 | * Double Floating-point to Single Fixed-point | ||
| 31 | * Double Floating-point to Double Fixed-point | ||
| 32 | * | ||
| 33 | * External Interfaces: | ||
| 34 | * dbl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status) | ||
| 35 | * dbl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status) | ||
| 36 | * sgl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status) | ||
| 37 | * sgl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status) | ||
| 38 | * | ||
| 39 | * Internal Interfaces: | ||
| 40 | * | ||
| 41 | * Theory: | ||
| 42 | * <<please update with a overview of the operation of this file>> | ||
| 43 | * | ||
| 44 | * END_DESC | ||
| 45 | */ | ||
| 46 | |||
| 47 | |||
| 48 | #include "float.h" | ||
| 49 | #include "sgl_float.h" | ||
| 50 | #include "dbl_float.h" | ||
| 51 | #include "cnv_float.h" | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Single Floating-point to Single Fixed-point | ||
| 55 | */ | ||
| 56 | /*ARGSUSED*/ | ||
| 57 | int | ||
| 58 | sgl_to_sgl_fcnvfx( | ||
| 59 | sgl_floating_point *srcptr, | ||
| 60 | sgl_floating_point *nullptr, | ||
| 61 | int *dstptr, | ||
| 62 | sgl_floating_point *status) | ||
| 63 | { | ||
| 64 | register unsigned int src, temp; | ||
| 65 | register int src_exponent, result; | ||
| 66 | register boolean inexact = FALSE; | ||
| 67 | |||
| 68 | src = *srcptr; | ||
| 69 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
| 70 | |||
| 71 | /* | ||
| 72 | * Test for overflow | ||
| 73 | */ | ||
| 74 | if (src_exponent > SGL_FX_MAX_EXP) { | ||
| 75 | /* check for MININT */ | ||
| 76 | if ((src_exponent > SGL_FX_MAX_EXP + 1) || | ||
| 77 | Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { | ||
| 78 | if (Sgl_iszero_sign(src)) result = 0x7fffffff; | ||
| 79 | else result = 0x80000000; | ||
| 80 | |||
| 81 | if (Is_invalidtrap_enabled()) { | ||
| 82 | return(INVALIDEXCEPTION); | ||
| 83 | } | ||
| 84 | Set_invalidflag(); | ||
| 85 | *dstptr = result; | ||
| 86 | return(NOEXCEPTION); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | /* | ||
| 90 | * Generate result | ||
| 91 | */ | ||
| 92 | if (src_exponent >= 0) { | ||
| 93 | temp = src; | ||
| 94 | Sgl_clear_signexponent_set_hidden(temp); | ||
| 95 | Int_from_sgl_mantissa(temp,src_exponent); | ||
| 96 | if (Sgl_isone_sign(src)) result = -Sgl_all(temp); | ||
| 97 | else result = Sgl_all(temp); | ||
| 98 | |||
| 99 | /* check for inexact */ | ||
| 100 | if (Sgl_isinexact_to_fix(src,src_exponent)) { | ||
| 101 | inexact = TRUE; | ||
| 102 | /* round result */ | ||
| 103 | switch (Rounding_mode()) { | ||
| 104 | case ROUNDPLUS: | ||
| 105 | if (Sgl_iszero_sign(src)) result++; | ||
| 106 | break; | ||
| 107 | case ROUNDMINUS: | ||
| 108 | if (Sgl_isone_sign(src)) result--; | ||
| 109 | break; | ||
| 110 | case ROUNDNEAREST: | ||
| 111 | if (Sgl_isone_roundbit(src,src_exponent)) { | ||
| 112 | if (Sgl_isone_stickybit(src,src_exponent) | ||
| 113 | || (Sgl_isone_lowmantissa(temp))) | ||
| 114 | if (Sgl_iszero_sign(src)) result++; | ||
| 115 | else result--; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | } | ||
| 119 | } | ||
| 120 | else { | ||
| 121 | result = 0; | ||
| 122 | |||
| 123 | /* check for inexact */ | ||
| 124 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
| 125 | inexact = TRUE; | ||
| 126 | /* round result */ | ||
| 127 | switch (Rounding_mode()) { | ||
| 128 | case ROUNDPLUS: | ||
| 129 | if (Sgl_iszero_sign(src)) result++; | ||
| 130 | break; | ||
| 131 | case ROUNDMINUS: | ||
| 132 | if (Sgl_isone_sign(src)) result--; | ||
| 133 | break; | ||
| 134 | case ROUNDNEAREST: | ||
| 135 | if (src_exponent == -1) | ||
| 136 | if (Sgl_isnotzero_mantissa(src)) | ||
| 137 | if (Sgl_iszero_sign(src)) result++; | ||
| 138 | else result--; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | } | ||
| 142 | *dstptr = result; | ||
| 143 | if (inexact) { | ||
| 144 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 145 | else Set_inexactflag(); | ||
| 146 | } | ||
| 147 | return(NOEXCEPTION); | ||
| 148 | } | ||
| 149 | |||
| 150 | /* | ||
| 151 | * Single Floating-point to Double Fixed-point | ||
| 152 | */ | ||
| 153 | /*ARGSUSED*/ | ||
| 154 | int | ||
| 155 | sgl_to_dbl_fcnvfx( | ||
| 156 | sgl_floating_point *srcptr, | ||
| 157 | unsigned int *nullptr, | ||
| 158 | dbl_integer *dstptr, | ||
| 159 | unsigned int *status) | ||
| 160 | { | ||
| 161 | register int src_exponent, resultp1; | ||
| 162 | register unsigned int src, temp, resultp2; | ||
| 163 | register boolean inexact = FALSE; | ||
| 164 | |||
| 165 | src = *srcptr; | ||
| 166 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
| 167 | |||
| 168 | /* | ||
| 169 | * Test for overflow | ||
| 170 | */ | ||
| 171 | if (src_exponent > DBL_FX_MAX_EXP) { | ||
| 172 | /* check for MININT */ | ||
| 173 | if ((src_exponent > DBL_FX_MAX_EXP + 1) || | ||
| 174 | Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { | ||
| 175 | if (Sgl_iszero_sign(src)) { | ||
| 176 | resultp1 = 0x7fffffff; | ||
| 177 | resultp2 = 0xffffffff; | ||
| 178 | } | ||
| 179 | else { | ||
| 180 | resultp1 = 0x80000000; | ||
| 181 | resultp2 = 0; | ||
| 182 | } | ||
| 183 | if (Is_invalidtrap_enabled()) { | ||
| 184 | return(INVALIDEXCEPTION); | ||
| 185 | } | ||
| 186 | Set_invalidflag(); | ||
| 187 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
| 188 | return(NOEXCEPTION); | ||
| 189 | } | ||
| 190 | Dint_set_minint(resultp1,resultp2); | ||
| 191 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
| 192 | return(NOEXCEPTION); | ||
| 193 | } | ||
| 194 | /* | ||
| 195 | * Generate result | ||
| 196 | */ | ||
| 197 | if (src_exponent >= 0) { | ||
| 198 | temp = src; | ||
| 199 | Sgl_clear_signexponent_set_hidden(temp); | ||
| 200 | Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2); | ||
| 201 | if (Sgl_isone_sign(src)) { | ||
| 202 | Dint_setone_sign(resultp1,resultp2); | ||
| 203 | } | ||
| 204 | |||
| 205 | /* check for inexact */ | ||
| 206 | if (Sgl_isinexact_to_fix(src,src_exponent)) { | ||
| 207 | inexact = TRUE; | ||
| 208 | /* round result */ | ||
| 209 | switch (Rounding_mode()) { | ||
| 210 | case ROUNDPLUS: | ||
| 211 | if (Sgl_iszero_sign(src)) { | ||
| 212 | Dint_increment(resultp1,resultp2); | ||
| 213 | } | ||
| 214 | break; | ||
| 215 | case ROUNDMINUS: | ||
| 216 | if (Sgl_isone_sign(src)) { | ||
| 217 | Dint_decrement(resultp1,resultp2); | ||
| 218 | } | ||
| 219 | break; | ||
| 220 | case ROUNDNEAREST: | ||
| 221 | if (Sgl_isone_roundbit(src,src_exponent)) | ||
| 222 | if (Sgl_isone_stickybit(src,src_exponent) || | ||
| 223 | (Dint_isone_lowp2(resultp2))) | ||
| 224 | if (Sgl_iszero_sign(src)) { | ||
| 225 | Dint_increment(resultp1,resultp2); | ||
| 226 | } | ||
| 227 | else { | ||
| 228 | Dint_decrement(resultp1,resultp2); | ||
| 229 | } | ||
| 230 | } | ||
| 231 | } | ||
| 232 | } | ||
| 233 | else { | ||
| 234 | Dint_setzero(resultp1,resultp2); | ||
| 235 | |||
| 236 | /* check for inexact */ | ||
| 237 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
| 238 | inexact = TRUE; | ||
| 239 | /* round result */ | ||
| 240 | switch (Rounding_mode()) { | ||
| 241 | case ROUNDPLUS: | ||
| 242 | if (Sgl_iszero_sign(src)) { | ||
| 243 | Dint_increment(resultp1,resultp2); | ||
| 244 | } | ||
| 245 | break; | ||
| 246 | case ROUNDMINUS: | ||
| 247 | if (Sgl_isone_sign(src)) { | ||
| 248 | Dint_decrement(resultp1,resultp2); | ||
| 249 | } | ||
| 250 | break; | ||
| 251 | case ROUNDNEAREST: | ||
| 252 | if (src_exponent == -1) | ||
| 253 | if (Sgl_isnotzero_mantissa(src)) | ||
| 254 | if (Sgl_iszero_sign(src)) { | ||
| 255 | Dint_increment(resultp1,resultp2); | ||
| 256 | } | ||
| 257 | else { | ||
| 258 | Dint_decrement(resultp1,resultp2); | ||
| 259 | } | ||
| 260 | } | ||
| 261 | } | ||
| 262 | } | ||
| 263 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
| 264 | if (inexact) { | ||
| 265 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 266 | else Set_inexactflag(); | ||
| 267 | } | ||
| 268 | return(NOEXCEPTION); | ||
| 269 | } | ||
| 270 | |||
| 271 | /* | ||
| 272 | * Double Floating-point to Single Fixed-point | ||
| 273 | */ | ||
| 274 | /*ARGSUSED*/ | ||
| 275 | int | ||
| 276 | dbl_to_sgl_fcnvfx( | ||
| 277 | dbl_floating_point *srcptr, | ||
| 278 | unsigned int *nullptr, | ||
| 279 | int *dstptr, | ||
| 280 | unsigned int *status) | ||
| 281 | { | ||
| 282 | register unsigned int srcp1,srcp2, tempp1,tempp2; | ||
| 283 | register int src_exponent, result; | ||
| 284 | register boolean inexact = FALSE; | ||
| 285 | |||
| 286 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
| 287 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
| 288 | |||
| 289 | /* | ||
| 290 | * Test for overflow | ||
| 291 | */ | ||
| 292 | if (src_exponent > SGL_FX_MAX_EXP) { | ||
| 293 | /* check for MININT */ | ||
| 294 | if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) { | ||
| 295 | if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff; | ||
| 296 | else result = 0x80000000; | ||
| 297 | |||
| 298 | if (Is_invalidtrap_enabled()) { | ||
| 299 | return(INVALIDEXCEPTION); | ||
| 300 | } | ||
| 301 | Set_invalidflag(); | ||
| 302 | *dstptr = result; | ||
| 303 | return(NOEXCEPTION); | ||
| 304 | } | ||
| 305 | } | ||
| 306 | /* | ||
| 307 | * Generate result | ||
| 308 | */ | ||
| 309 | if (src_exponent >= 0) { | ||
| 310 | tempp1 = srcp1; | ||
| 311 | tempp2 = srcp2; | ||
| 312 | Dbl_clear_signexponent_set_hidden(tempp1); | ||
| 313 | Int_from_dbl_mantissa(tempp1,tempp2,src_exponent); | ||
| 314 | if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP)) | ||
| 315 | result = -Dbl_allp1(tempp1); | ||
| 316 | else result = Dbl_allp1(tempp1); | ||
| 317 | |||
| 318 | /* check for inexact */ | ||
| 319 | if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { | ||
| 320 | inexact = TRUE; | ||
| 321 | /* round result */ | ||
| 322 | switch (Rounding_mode()) { | ||
| 323 | case ROUNDPLUS: | ||
| 324 | if (Dbl_iszero_sign(srcp1)) result++; | ||
| 325 | break; | ||
| 326 | case ROUNDMINUS: | ||
| 327 | if (Dbl_isone_sign(srcp1)) result--; | ||
| 328 | break; | ||
| 329 | case ROUNDNEAREST: | ||
| 330 | if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) | ||
| 331 | if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || | ||
| 332 | (Dbl_isone_lowmantissap1(tempp1))) | ||
| 333 | if (Dbl_iszero_sign(srcp1)) result++; | ||
| 334 | else result--; | ||
| 335 | } | ||
| 336 | /* check for overflow */ | ||
| 337 | if ((Dbl_iszero_sign(srcp1) && result < 0) || | ||
| 338 | (Dbl_isone_sign(srcp1) && result > 0)) { | ||
| 339 | |||
| 340 | if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff; | ||
| 341 | else result = 0x80000000; | ||
| 342 | |||
| 343 | if (Is_invalidtrap_enabled()) { | ||
| 344 | return(INVALIDEXCEPTION); | ||
| 345 | } | ||
| 346 | Set_invalidflag(); | ||
| 347 | *dstptr = result; | ||
| 348 | return(NOEXCEPTION); | ||
| 349 | } | ||
| 350 | } | ||
| 351 | } | ||
| 352 | else { | ||
| 353 | result = 0; | ||
| 354 | |||
| 355 | /* check for inexact */ | ||
| 356 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
| 357 | inexact = TRUE; | ||
| 358 | /* round result */ | ||
| 359 | switch (Rounding_mode()) { | ||
| 360 | case ROUNDPLUS: | ||
| 361 | if (Dbl_iszero_sign(srcp1)) result++; | ||
| 362 | break; | ||
| 363 | case ROUNDMINUS: | ||
| 364 | if (Dbl_isone_sign(srcp1)) result--; | ||
| 365 | break; | ||
| 366 | case ROUNDNEAREST: | ||
| 367 | if (src_exponent == -1) | ||
| 368 | if (Dbl_isnotzero_mantissa(srcp1,srcp2)) | ||
| 369 | if (Dbl_iszero_sign(srcp1)) result++; | ||
| 370 | else result--; | ||
| 371 | } | ||
| 372 | } | ||
| 373 | } | ||
| 374 | *dstptr = result; | ||
| 375 | if (inexact) { | ||
| 376 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 377 | else Set_inexactflag(); | ||
| 378 | } | ||
| 379 | return(NOEXCEPTION); | ||
| 380 | } | ||
| 381 | |||
| 382 | /* | ||
| 383 | * Double Floating-point to Double Fixed-point | ||
| 384 | */ | ||
| 385 | /*ARGSUSED*/ | ||
| 386 | int | ||
| 387 | dbl_to_dbl_fcnvfx( | ||
| 388 | dbl_floating_point *srcptr, | ||
| 389 | unsigned int *nullptr, | ||
| 390 | dbl_integer *dstptr, | ||
| 391 | unsigned int *status) | ||
| 392 | { | ||
| 393 | register int src_exponent, resultp1; | ||
| 394 | register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2; | ||
| 395 | register boolean inexact = FALSE; | ||
| 396 | |||
| 397 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
| 398 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
| 399 | |||
| 400 | /* | ||
| 401 | * Test for overflow | ||
| 402 | */ | ||
| 403 | if (src_exponent > DBL_FX_MAX_EXP) { | ||
| 404 | /* check for MININT */ | ||
| 405 | if ((src_exponent > DBL_FX_MAX_EXP + 1) || | ||
| 406 | Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) { | ||
| 407 | if (Dbl_iszero_sign(srcp1)) { | ||
| 408 | resultp1 = 0x7fffffff; | ||
| 409 | resultp2 = 0xffffffff; | ||
| 410 | } | ||
| 411 | else { | ||
| 412 | resultp1 = 0x80000000; | ||
| 413 | resultp2 = 0; | ||
| 414 | } | ||
| 415 | if (Is_invalidtrap_enabled()) { | ||
| 416 | return(INVALIDEXCEPTION); | ||
| 417 | } | ||
| 418 | Set_invalidflag(); | ||
| 419 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
| 420 | return(NOEXCEPTION); | ||
| 421 | } | ||
| 422 | } | ||
| 423 | |||
| 424 | /* | ||
| 425 | * Generate result | ||
| 426 | */ | ||
| 427 | if (src_exponent >= 0) { | ||
| 428 | tempp1 = srcp1; | ||
| 429 | tempp2 = srcp2; | ||
| 430 | Dbl_clear_signexponent_set_hidden(tempp1); | ||
| 431 | Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1, | ||
| 432 | resultp2); | ||
| 433 | if (Dbl_isone_sign(srcp1)) { | ||
| 434 | Dint_setone_sign(resultp1,resultp2); | ||
| 435 | } | ||
| 436 | |||
| 437 | /* check for inexact */ | ||
| 438 | if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { | ||
| 439 | inexact = TRUE; | ||
| 440 | /* round result */ | ||
| 441 | switch (Rounding_mode()) { | ||
| 442 | case ROUNDPLUS: | ||
| 443 | if (Dbl_iszero_sign(srcp1)) { | ||
| 444 | Dint_increment(resultp1,resultp2); | ||
| 445 | } | ||
| 446 | break; | ||
| 447 | case ROUNDMINUS: | ||
| 448 | if (Dbl_isone_sign(srcp1)) { | ||
| 449 | Dint_decrement(resultp1,resultp2); | ||
| 450 | } | ||
| 451 | break; | ||
| 452 | case ROUNDNEAREST: | ||
| 453 | if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) | ||
| 454 | if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || | ||
| 455 | (Dint_isone_lowp2(resultp2))) | ||
| 456 | if (Dbl_iszero_sign(srcp1)) { | ||
| 457 | Dint_increment(resultp1,resultp2); | ||
| 458 | } | ||
| 459 | else { | ||
| 460 | Dint_decrement(resultp1,resultp2); | ||
| 461 | } | ||
| 462 | } | ||
| 463 | } | ||
| 464 | } | ||
| 465 | else { | ||
| 466 | Dint_setzero(resultp1,resultp2); | ||
| 467 | |||
| 468 | /* check for inexact */ | ||
| 469 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
| 470 | inexact = TRUE; | ||
| 471 | /* round result */ | ||
| 472 | switch (Rounding_mode()) { | ||
| 473 | case ROUNDPLUS: | ||
| 474 | if (Dbl_iszero_sign(srcp1)) { | ||
| 475 | Dint_increment(resultp1,resultp2); | ||
| 476 | } | ||
| 477 | break; | ||
| 478 | case ROUNDMINUS: | ||
| 479 | if (Dbl_isone_sign(srcp1)) { | ||
| 480 | Dint_decrement(resultp1,resultp2); | ||
| 481 | } | ||
| 482 | break; | ||
| 483 | case ROUNDNEAREST: | ||
| 484 | if (src_exponent == -1) | ||
| 485 | if (Dbl_isnotzero_mantissa(srcp1,srcp2)) | ||
| 486 | if (Dbl_iszero_sign(srcp1)) { | ||
| 487 | Dint_increment(resultp1,resultp2); | ||
| 488 | } | ||
| 489 | else { | ||
| 490 | Dint_decrement(resultp1,resultp2); | ||
| 491 | } | ||
| 492 | } | ||
| 493 | } | ||
| 494 | } | ||
| 495 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
| 496 | if (inexact) { | ||
| 497 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 498 | else Set_inexactflag(); | ||
| 499 | } | ||
| 500 | return(NOEXCEPTION); | ||
| 501 | } | ||
diff --git a/arch/parisc/math-emu/fcnvfxt.c b/arch/parisc/math-emu/fcnvfxt.c new file mode 100644 index 000000000000..8b9010c4690e --- /dev/null +++ b/arch/parisc/math-emu/fcnvfxt.c | |||
| @@ -0,0 +1,328 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/fcnvfxt.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Single Floating-point to Single Fixed-point /w truncated result | ||
| 29 | * Single Floating-point to Double Fixed-point /w truncated result | ||
| 30 | * Double Floating-point to Single Fixed-point /w truncated result | ||
| 31 | * Double Floating-point to Double Fixed-point /w truncated result | ||
| 32 | * | ||
| 33 | * External Interfaces: | ||
| 34 | * dbl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status) | ||
| 35 | * dbl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status) | ||
| 36 | * sgl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status) | ||
| 37 | * sgl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status) | ||
| 38 | * | ||
| 39 | * Internal Interfaces: | ||
| 40 | * | ||
| 41 | * Theory: | ||
| 42 | * <<please update with a overview of the operation of this file>> | ||
| 43 | * | ||
| 44 | * END_DESC | ||
| 45 | */ | ||
| 46 | |||
| 47 | |||
| 48 | #include "float.h" | ||
| 49 | #include "sgl_float.h" | ||
| 50 | #include "dbl_float.h" | ||
| 51 | #include "cnv_float.h" | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Convert single floating-point to single fixed-point format | ||
| 55 | * with truncated result | ||
| 56 | */ | ||
| 57 | /*ARGSUSED*/ | ||
| 58 | int | ||
| 59 | sgl_to_sgl_fcnvfxt( | ||
| 60 | sgl_floating_point *srcptr, | ||
| 61 | unsigned int *nullptr, | ||
| 62 | int *dstptr, | ||
| 63 | unsigned int *status) | ||
| 64 | { | ||
| 65 | register unsigned int src, temp; | ||
| 66 | register int src_exponent, result; | ||
| 67 | |||
| 68 | src = *srcptr; | ||
| 69 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
| 70 | |||
| 71 | /* | ||
| 72 | * Test for overflow | ||
| 73 | */ | ||
| 74 | if (src_exponent > SGL_FX_MAX_EXP) { | ||
| 75 | /* check for MININT */ | ||
| 76 | if ((src_exponent > SGL_FX_MAX_EXP + 1) || | ||
| 77 | Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { | ||
| 78 | if (Sgl_iszero_sign(src)) result = 0x7fffffff; | ||
| 79 | else result = 0x80000000; | ||
| 80 | |||
| 81 | if (Is_invalidtrap_enabled()) { | ||
| 82 | return(INVALIDEXCEPTION); | ||
| 83 | } | ||
| 84 | Set_invalidflag(); | ||
| 85 | *dstptr = result; | ||
| 86 | return(NOEXCEPTION); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | /* | ||
| 90 | * Generate result | ||
| 91 | */ | ||
| 92 | if (src_exponent >= 0) { | ||
| 93 | temp = src; | ||
| 94 | Sgl_clear_signexponent_set_hidden(temp); | ||
| 95 | Int_from_sgl_mantissa(temp,src_exponent); | ||
| 96 | if (Sgl_isone_sign(src)) result = -Sgl_all(temp); | ||
| 97 | else result = Sgl_all(temp); | ||
| 98 | *dstptr = result; | ||
| 99 | |||
| 100 | /* check for inexact */ | ||
| 101 | if (Sgl_isinexact_to_fix(src,src_exponent)) { | ||
| 102 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 103 | else Set_inexactflag(); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | else { | ||
| 107 | *dstptr = 0; | ||
| 108 | |||
| 109 | /* check for inexact */ | ||
| 110 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
| 111 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 112 | else Set_inexactflag(); | ||
| 113 | } | ||
| 114 | } | ||
| 115 | return(NOEXCEPTION); | ||
| 116 | } | ||
| 117 | |||
| 118 | /* | ||
| 119 | * Single Floating-point to Double Fixed-point | ||
| 120 | */ | ||
| 121 | /*ARGSUSED*/ | ||
| 122 | int | ||
| 123 | sgl_to_dbl_fcnvfxt( | ||
| 124 | sgl_floating_point *srcptr, | ||
| 125 | unsigned int *nullptr, | ||
| 126 | dbl_integer *dstptr, | ||
| 127 | unsigned int *status) | ||
| 128 | { | ||
| 129 | register int src_exponent, resultp1; | ||
| 130 | register unsigned int src, temp, resultp2; | ||
| 131 | |||
| 132 | src = *srcptr; | ||
| 133 | src_exponent = Sgl_exponent(src) - SGL_BIAS; | ||
| 134 | |||
| 135 | /* | ||
| 136 | * Test for overflow | ||
| 137 | */ | ||
| 138 | if (src_exponent > DBL_FX_MAX_EXP) { | ||
| 139 | /* check for MININT */ | ||
| 140 | if ((src_exponent > DBL_FX_MAX_EXP + 1) || | ||
| 141 | Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) { | ||
| 142 | if (Sgl_iszero_sign(src)) { | ||
| 143 | resultp1 = 0x7fffffff; | ||
| 144 | resultp2 = 0xffffffff; | ||
| 145 | } | ||
| 146 | else { | ||
| 147 | resultp1 = 0x80000000; | ||
| 148 | resultp2 = 0; | ||
| 149 | } | ||
| 150 | if (Is_invalidtrap_enabled()) { | ||
| 151 | return(INVALIDEXCEPTION); | ||
| 152 | } | ||
| 153 | Set_invalidflag(); | ||
| 154 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
| 155 | return(NOEXCEPTION); | ||
| 156 | } | ||
| 157 | Dint_set_minint(resultp1,resultp2); | ||
| 158 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
| 159 | return(NOEXCEPTION); | ||
| 160 | } | ||
| 161 | /* | ||
| 162 | * Generate result | ||
| 163 | */ | ||
| 164 | if (src_exponent >= 0) { | ||
| 165 | temp = src; | ||
| 166 | Sgl_clear_signexponent_set_hidden(temp); | ||
| 167 | Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2); | ||
| 168 | if (Sgl_isone_sign(src)) { | ||
| 169 | Dint_setone_sign(resultp1,resultp2); | ||
| 170 | } | ||
| 171 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
| 172 | |||
| 173 | /* check for inexact */ | ||
| 174 | if (Sgl_isinexact_to_fix(src,src_exponent)) { | ||
| 175 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 176 | else Set_inexactflag(); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | else { | ||
| 180 | Dint_setzero(resultp1,resultp2); | ||
| 181 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
| 182 | |||
| 183 | /* check for inexact */ | ||
| 184 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
| 185 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 186 | else Set_inexactflag(); | ||
| 187 | } | ||
| 188 | } | ||
| 189 | return(NOEXCEPTION); | ||
| 190 | } | ||
| 191 | |||
| 192 | /* | ||
| 193 | * Double Floating-point to Single Fixed-point | ||
| 194 | */ | ||
| 195 | /*ARGSUSED*/ | ||
| 196 | int | ||
| 197 | dbl_to_sgl_fcnvfxt( | ||
| 198 | dbl_floating_point *srcptr, | ||
| 199 | unsigned int *nullptr, | ||
| 200 | int *dstptr, | ||
| 201 | unsigned int *status) | ||
| 202 | { | ||
| 203 | register unsigned int srcp1, srcp2, tempp1, tempp2; | ||
| 204 | register int src_exponent, result; | ||
| 205 | |||
| 206 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
| 207 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
| 208 | |||
| 209 | /* | ||
| 210 | * Test for overflow | ||
| 211 | */ | ||
| 212 | if (src_exponent > SGL_FX_MAX_EXP) { | ||
| 213 | /* check for MININT */ | ||
| 214 | if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) { | ||
| 215 | if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff; | ||
| 216 | else result = 0x80000000; | ||
| 217 | |||
| 218 | if (Is_invalidtrap_enabled()) { | ||
| 219 | return(INVALIDEXCEPTION); | ||
| 220 | } | ||
| 221 | Set_invalidflag(); | ||
| 222 | *dstptr = result; | ||
| 223 | return(NOEXCEPTION); | ||
| 224 | } | ||
| 225 | } | ||
| 226 | /* | ||
| 227 | * Generate result | ||
| 228 | */ | ||
| 229 | if (src_exponent >= 0) { | ||
| 230 | tempp1 = srcp1; | ||
| 231 | tempp2 = srcp2; | ||
| 232 | Dbl_clear_signexponent_set_hidden(tempp1); | ||
| 233 | Int_from_dbl_mantissa(tempp1,tempp2,src_exponent); | ||
| 234 | if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP)) | ||
| 235 | result = -Dbl_allp1(tempp1); | ||
| 236 | else result = Dbl_allp1(tempp1); | ||
| 237 | *dstptr = result; | ||
| 238 | |||
| 239 | /* check for inexact */ | ||
| 240 | if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { | ||
| 241 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 242 | else Set_inexactflag(); | ||
| 243 | } | ||
| 244 | } | ||
| 245 | else { | ||
| 246 | *dstptr = 0; | ||
| 247 | |||
| 248 | /* check for inexact */ | ||
| 249 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
| 250 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 251 | else Set_inexactflag(); | ||
| 252 | } | ||
| 253 | } | ||
| 254 | return(NOEXCEPTION); | ||
| 255 | } | ||
| 256 | |||
| 257 | /* | ||
| 258 | * Double Floating-point to Double Fixed-point | ||
| 259 | */ | ||
| 260 | /*ARGSUSED*/ | ||
| 261 | int | ||
| 262 | dbl_to_dbl_fcnvfxt( | ||
| 263 | dbl_floating_point *srcptr, | ||
| 264 | unsigned int *nullptr, | ||
| 265 | dbl_integer *dstptr, | ||
| 266 | unsigned int *status) | ||
| 267 | { | ||
| 268 | register int src_exponent, resultp1; | ||
| 269 | register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2; | ||
| 270 | |||
| 271 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
| 272 | src_exponent = Dbl_exponent(srcp1) - DBL_BIAS; | ||
| 273 | |||
| 274 | /* | ||
| 275 | * Test for overflow | ||
| 276 | */ | ||
| 277 | if (src_exponent > DBL_FX_MAX_EXP) { | ||
| 278 | /* check for MININT */ | ||
| 279 | if ((src_exponent > DBL_FX_MAX_EXP + 1) || | ||
| 280 | Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) { | ||
| 281 | if (Dbl_iszero_sign(srcp1)) { | ||
| 282 | resultp1 = 0x7fffffff; | ||
| 283 | resultp2 = 0xffffffff; | ||
| 284 | } | ||
| 285 | else { | ||
| 286 | resultp1 = 0x80000000; | ||
| 287 | resultp2 = 0; | ||
| 288 | } | ||
| 289 | if (Is_invalidtrap_enabled()) { | ||
| 290 | return(INVALIDEXCEPTION); | ||
| 291 | } | ||
| 292 | Set_invalidflag(); | ||
| 293 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
| 294 | return(NOEXCEPTION); | ||
| 295 | } | ||
| 296 | } | ||
| 297 | /* | ||
| 298 | * Generate result | ||
| 299 | */ | ||
| 300 | if (src_exponent >= 0) { | ||
| 301 | tempp1 = srcp1; | ||
| 302 | tempp2 = srcp2; | ||
| 303 | Dbl_clear_signexponent_set_hidden(tempp1); | ||
| 304 | Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent, | ||
| 305 | resultp1,resultp2); | ||
| 306 | if (Dbl_isone_sign(srcp1)) { | ||
| 307 | Dint_setone_sign(resultp1,resultp2); | ||
| 308 | } | ||
| 309 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
| 310 | |||
| 311 | /* check for inexact */ | ||
| 312 | if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { | ||
| 313 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 314 | else Set_inexactflag(); | ||
| 315 | } | ||
| 316 | } | ||
| 317 | else { | ||
| 318 | Dint_setzero(resultp1,resultp2); | ||
| 319 | Dint_copytoptr(resultp1,resultp2,dstptr); | ||
| 320 | |||
| 321 | /* check for inexact */ | ||
| 322 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
| 323 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 324 | else Set_inexactflag(); | ||
| 325 | } | ||
| 326 | } | ||
| 327 | return(NOEXCEPTION); | ||
| 328 | } | ||
diff --git a/arch/parisc/math-emu/fcnvuf.c b/arch/parisc/math-emu/fcnvuf.c new file mode 100644 index 000000000000..5e68189fee22 --- /dev/null +++ b/arch/parisc/math-emu/fcnvuf.c | |||
| @@ -0,0 +1,318 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/fcnvuf.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Fixed point to Floating-point Converts | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * dbl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status) | ||
| 32 | * dbl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status) | ||
| 33 | * sgl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status) | ||
| 34 | * sgl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status) | ||
| 35 | * | ||
| 36 | * Internal Interfaces: | ||
| 37 | * | ||
| 38 | * Theory: | ||
| 39 | * <<please update with a overview of the operation of this file>> | ||
| 40 | * | ||
| 41 | * END_DESC | ||
| 42 | */ | ||
| 43 | |||
| 44 | |||
| 45 | #include "float.h" | ||
| 46 | #include "sgl_float.h" | ||
| 47 | #include "dbl_float.h" | ||
| 48 | #include "cnv_float.h" | ||
| 49 | |||
| 50 | /************************************************************************ | ||
| 51 | * Fixed point to Floating-point Converts * | ||
| 52 | ************************************************************************/ | ||
| 53 | |||
| 54 | /* | ||
| 55 | * Convert Single Unsigned Fixed to Single Floating-point format | ||
| 56 | */ | ||
| 57 | |||
| 58 | int | ||
| 59 | sgl_to_sgl_fcnvuf( | ||
| 60 | unsigned int *srcptr, | ||
| 61 | unsigned int *nullptr, | ||
| 62 | sgl_floating_point *dstptr, | ||
| 63 | unsigned int *status) | ||
| 64 | { | ||
| 65 | register unsigned int src, result = 0; | ||
| 66 | register int dst_exponent; | ||
| 67 | |||
| 68 | src = *srcptr; | ||
| 69 | |||
| 70 | /* Check for zero */ | ||
| 71 | if (src == 0) { | ||
| 72 | Sgl_setzero(result); | ||
| 73 | *dstptr = result; | ||
| 74 | return(NOEXCEPTION); | ||
| 75 | } | ||
| 76 | /* | ||
| 77 | * Generate exponent and normalized mantissa | ||
| 78 | */ | ||
| 79 | dst_exponent = 16; /* initialize for normalization */ | ||
| 80 | /* | ||
| 81 | * Check word for most significant bit set. Returns | ||
| 82 | * a value in dst_exponent indicating the bit position, | ||
| 83 | * between -1 and 30. | ||
| 84 | */ | ||
| 85 | Find_ms_one_bit(src,dst_exponent); | ||
| 86 | /* left justify source, with msb at bit position 0 */ | ||
| 87 | src <<= dst_exponent+1; | ||
| 88 | Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH); | ||
| 89 | Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent); | ||
| 90 | |||
| 91 | /* check for inexact */ | ||
| 92 | if (Suint_isinexact_to_sgl(src)) { | ||
| 93 | switch (Rounding_mode()) { | ||
| 94 | case ROUNDPLUS: | ||
| 95 | Sgl_increment(result); | ||
| 96 | break; | ||
| 97 | case ROUNDMINUS: /* never negative */ | ||
| 98 | break; | ||
| 99 | case ROUNDNEAREST: | ||
| 100 | Sgl_roundnearest_from_suint(src,result); | ||
| 101 | break; | ||
| 102 | } | ||
| 103 | if (Is_inexacttrap_enabled()) { | ||
| 104 | *dstptr = result; | ||
| 105 | return(INEXACTEXCEPTION); | ||
| 106 | } | ||
| 107 | else Set_inexactflag(); | ||
| 108 | } | ||
| 109 | *dstptr = result; | ||
| 110 | return(NOEXCEPTION); | ||
| 111 | } | ||
| 112 | |||
| 113 | /* | ||
| 114 | * Single Unsigned Fixed to Double Floating-point | ||
| 115 | */ | ||
| 116 | |||
| 117 | int | ||
| 118 | sgl_to_dbl_fcnvuf( | ||
| 119 | unsigned int *srcptr, | ||
| 120 | unsigned int *nullptr, | ||
| 121 | dbl_floating_point *dstptr, | ||
| 122 | unsigned int *status) | ||
| 123 | { | ||
| 124 | register int dst_exponent; | ||
| 125 | register unsigned int src, resultp1 = 0, resultp2 = 0; | ||
| 126 | |||
| 127 | src = *srcptr; | ||
| 128 | |||
| 129 | /* Check for zero */ | ||
| 130 | if (src == 0) { | ||
| 131 | Dbl_setzero(resultp1,resultp2); | ||
| 132 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 133 | return(NOEXCEPTION); | ||
| 134 | } | ||
| 135 | /* | ||
| 136 | * Generate exponent and normalized mantissa | ||
| 137 | */ | ||
| 138 | dst_exponent = 16; /* initialize for normalization */ | ||
| 139 | /* | ||
| 140 | * Check word for most significant bit set. Returns | ||
| 141 | * a value in dst_exponent indicating the bit position, | ||
| 142 | * between -1 and 30. | ||
| 143 | */ | ||
| 144 | Find_ms_one_bit(src,dst_exponent); | ||
| 145 | /* left justify source, with msb at bit position 0 */ | ||
| 146 | src <<= dst_exponent+1; | ||
| 147 | Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH); | ||
| 148 | Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH)); | ||
| 149 | Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent); | ||
| 150 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 151 | return(NOEXCEPTION); | ||
| 152 | } | ||
| 153 | |||
| 154 | /* | ||
| 155 | * Double Unsigned Fixed to Single Floating-point | ||
| 156 | */ | ||
| 157 | |||
| 158 | int | ||
| 159 | dbl_to_sgl_fcnvuf( | ||
| 160 | dbl_unsigned *srcptr, | ||
| 161 | unsigned int *nullptr, | ||
| 162 | sgl_floating_point *dstptr, | ||
| 163 | unsigned int *status) | ||
| 164 | { | ||
| 165 | int dst_exponent; | ||
| 166 | unsigned int srcp1, srcp2, result = 0; | ||
| 167 | |||
| 168 | Duint_copyfromptr(srcptr,srcp1,srcp2); | ||
| 169 | |||
| 170 | /* Check for zero */ | ||
| 171 | if (srcp1 == 0 && srcp2 == 0) { | ||
| 172 | Sgl_setzero(result); | ||
| 173 | *dstptr = result; | ||
| 174 | return(NOEXCEPTION); | ||
| 175 | } | ||
| 176 | /* | ||
| 177 | * Generate exponent and normalized mantissa | ||
| 178 | */ | ||
| 179 | dst_exponent = 16; /* initialize for normalization */ | ||
| 180 | if (srcp1 == 0) { | ||
| 181 | /* | ||
| 182 | * Check word for most significant bit set. Returns | ||
| 183 | * a value in dst_exponent indicating the bit position, | ||
| 184 | * between -1 and 30. | ||
| 185 | */ | ||
| 186 | Find_ms_one_bit(srcp2,dst_exponent); | ||
| 187 | /* left justify source, with msb at bit position 0 */ | ||
| 188 | srcp1 = srcp2 << dst_exponent+1; | ||
| 189 | srcp2 = 0; | ||
| 190 | /* | ||
| 191 | * since msb set is in second word, need to | ||
| 192 | * adjust bit position count | ||
| 193 | */ | ||
| 194 | dst_exponent += 32; | ||
| 195 | } | ||
| 196 | else { | ||
| 197 | /* | ||
| 198 | * Check word for most significant bit set. Returns | ||
| 199 | * a value in dst_exponent indicating the bit position, | ||
| 200 | * between -1 and 30. | ||
| 201 | * | ||
| 202 | */ | ||
| 203 | Find_ms_one_bit(srcp1,dst_exponent); | ||
| 204 | /* left justify source, with msb at bit position 0 */ | ||
| 205 | if (dst_exponent >= 0) { | ||
| 206 | Variable_shift_double(srcp1,srcp2,(31-dst_exponent), | ||
| 207 | srcp1); | ||
| 208 | srcp2 <<= dst_exponent+1; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH); | ||
| 212 | Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent); | ||
| 213 | |||
| 214 | /* check for inexact */ | ||
| 215 | if (Duint_isinexact_to_sgl(srcp1,srcp2)) { | ||
| 216 | switch (Rounding_mode()) { | ||
| 217 | case ROUNDPLUS: | ||
| 218 | Sgl_increment(result); | ||
| 219 | break; | ||
| 220 | case ROUNDMINUS: /* never negative */ | ||
| 221 | break; | ||
| 222 | case ROUNDNEAREST: | ||
| 223 | Sgl_roundnearest_from_duint(srcp1,srcp2,result); | ||
| 224 | break; | ||
| 225 | } | ||
| 226 | if (Is_inexacttrap_enabled()) { | ||
| 227 | *dstptr = result; | ||
| 228 | return(INEXACTEXCEPTION); | ||
| 229 | } | ||
| 230 | else Set_inexactflag(); | ||
| 231 | } | ||
| 232 | *dstptr = result; | ||
| 233 | return(NOEXCEPTION); | ||
| 234 | } | ||
| 235 | |||
| 236 | /* | ||
| 237 | * Double Unsigned Fixed to Double Floating-point | ||
| 238 | */ | ||
| 239 | |||
| 240 | int | ||
| 241 | dbl_to_dbl_fcnvuf( | ||
| 242 | dbl_unsigned *srcptr, | ||
| 243 | unsigned int *nullptr, | ||
| 244 | dbl_floating_point *dstptr, | ||
| 245 | unsigned int *status) | ||
| 246 | { | ||
| 247 | register int dst_exponent; | ||
| 248 | register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0; | ||
| 249 | |||
| 250 | Duint_copyfromptr(srcptr,srcp1,srcp2); | ||
| 251 | |||
| 252 | /* Check for zero */ | ||
| 253 | if (srcp1 == 0 && srcp2 ==0) { | ||
| 254 | Dbl_setzero(resultp1,resultp2); | ||
| 255 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 256 | return(NOEXCEPTION); | ||
| 257 | } | ||
| 258 | /* | ||
| 259 | * Generate exponent and normalized mantissa | ||
| 260 | */ | ||
| 261 | dst_exponent = 16; /* initialize for normalization */ | ||
| 262 | if (srcp1 == 0) { | ||
| 263 | /* | ||
| 264 | * Check word for most significant bit set. Returns | ||
| 265 | * a value in dst_exponent indicating the bit position, | ||
| 266 | * between -1 and 30. | ||
| 267 | */ | ||
| 268 | Find_ms_one_bit(srcp2,dst_exponent); | ||
| 269 | /* left justify source, with msb at bit position 0 */ | ||
| 270 | srcp1 = srcp2 << dst_exponent+1; | ||
| 271 | srcp2 = 0; | ||
| 272 | /* | ||
| 273 | * since msb set is in second word, need to | ||
| 274 | * adjust bit position count | ||
| 275 | */ | ||
| 276 | dst_exponent += 32; | ||
| 277 | } | ||
| 278 | else { | ||
| 279 | /* | ||
| 280 | * Check word for most significant bit set. Returns | ||
| 281 | * a value in dst_exponent indicating the bit position, | ||
| 282 | * between -1 and 30. | ||
| 283 | */ | ||
| 284 | Find_ms_one_bit(srcp1,dst_exponent); | ||
| 285 | /* left justify source, with msb at bit position 0 */ | ||
| 286 | if (dst_exponent >= 0) { | ||
| 287 | Variable_shift_double(srcp1,srcp2,(31-dst_exponent), | ||
| 288 | srcp1); | ||
| 289 | srcp2 <<= dst_exponent+1; | ||
| 290 | } | ||
| 291 | } | ||
| 292 | Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH); | ||
| 293 | Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2); | ||
| 294 | Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent); | ||
| 295 | |||
| 296 | /* check for inexact */ | ||
| 297 | if (Duint_isinexact_to_dbl(srcp2)) { | ||
| 298 | switch (Rounding_mode()) { | ||
| 299 | case ROUNDPLUS: | ||
| 300 | Dbl_increment(resultp1,resultp2); | ||
| 301 | break; | ||
| 302 | case ROUNDMINUS: /* never negative */ | ||
| 303 | break; | ||
| 304 | case ROUNDNEAREST: | ||
| 305 | Dbl_roundnearest_from_duint(srcp2,resultp1, | ||
| 306 | resultp2); | ||
| 307 | break; | ||
| 308 | } | ||
| 309 | if (Is_inexacttrap_enabled()) { | ||
| 310 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 311 | return(INEXACTEXCEPTION); | ||
| 312 | } | ||
| 313 | else Set_inexactflag(); | ||
| 314 | } | ||
| 315 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 316 | return(NOEXCEPTION); | ||
| 317 | } | ||
| 318 | |||
diff --git a/arch/parisc/math-emu/fcnvxf.c b/arch/parisc/math-emu/fcnvxf.c new file mode 100644 index 000000000000..05c7fadb3729 --- /dev/null +++ b/arch/parisc/math-emu/fcnvxf.c | |||
| @@ -0,0 +1,386 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/fcnvxf.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Single Fixed-point to Single Floating-point | ||
| 29 | * Single Fixed-point to Double Floating-point | ||
| 30 | * Double Fixed-point to Single Floating-point | ||
| 31 | * Double Fixed-point to Double Floating-point | ||
| 32 | * | ||
| 33 | * External Interfaces: | ||
| 34 | * dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status) | ||
| 35 | * dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status) | ||
| 36 | * sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status) | ||
| 37 | * sgl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status) | ||
| 38 | * | ||
| 39 | * Internal Interfaces: | ||
| 40 | * | ||
| 41 | * Theory: | ||
| 42 | * <<please update with a overview of the operation of this file>> | ||
| 43 | * | ||
| 44 | * END_DESC | ||
| 45 | */ | ||
| 46 | |||
| 47 | |||
| 48 | #include "float.h" | ||
| 49 | #include "sgl_float.h" | ||
| 50 | #include "dbl_float.h" | ||
| 51 | #include "cnv_float.h" | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Convert single fixed-point to single floating-point format | ||
| 55 | */ | ||
| 56 | |||
| 57 | int | ||
| 58 | sgl_to_sgl_fcnvxf( | ||
| 59 | int *srcptr, | ||
| 60 | unsigned int *nullptr, | ||
| 61 | sgl_floating_point *dstptr, | ||
| 62 | unsigned int *status) | ||
| 63 | { | ||
| 64 | register int src, dst_exponent; | ||
| 65 | register unsigned int result = 0; | ||
| 66 | |||
| 67 | src = *srcptr; | ||
| 68 | /* | ||
| 69 | * set sign bit of result and get magnitude of source | ||
| 70 | */ | ||
| 71 | if (src < 0) { | ||
| 72 | Sgl_setone_sign(result); | ||
| 73 | Int_negate(src); | ||
| 74 | } | ||
| 75 | else { | ||
| 76 | Sgl_setzero_sign(result); | ||
| 77 | /* Check for zero */ | ||
| 78 | if (src == 0) { | ||
| 79 | Sgl_setzero(result); | ||
| 80 | *dstptr = result; | ||
| 81 | return(NOEXCEPTION); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | /* | ||
| 85 | * Generate exponent and normalized mantissa | ||
| 86 | */ | ||
| 87 | dst_exponent = 16; /* initialize for normalization */ | ||
| 88 | /* | ||
| 89 | * Check word for most significant bit set. Returns | ||
| 90 | * a value in dst_exponent indicating the bit position, | ||
| 91 | * between -1 and 30. | ||
| 92 | */ | ||
| 93 | Find_ms_one_bit(src,dst_exponent); | ||
| 94 | /* left justify source, with msb at bit position 1 */ | ||
| 95 | if (dst_exponent >= 0) src <<= dst_exponent; | ||
| 96 | else src = 1 << 30; | ||
| 97 | Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1)); | ||
| 98 | Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent); | ||
| 99 | |||
| 100 | /* check for inexact */ | ||
| 101 | if (Int_isinexact_to_sgl(src)) { | ||
| 102 | switch (Rounding_mode()) { | ||
| 103 | case ROUNDPLUS: | ||
| 104 | if (Sgl_iszero_sign(result)) | ||
| 105 | Sgl_increment(result); | ||
| 106 | break; | ||
| 107 | case ROUNDMINUS: | ||
| 108 | if (Sgl_isone_sign(result)) | ||
| 109 | Sgl_increment(result); | ||
| 110 | break; | ||
| 111 | case ROUNDNEAREST: | ||
| 112 | Sgl_roundnearest_from_int(src,result); | ||
| 113 | } | ||
| 114 | if (Is_inexacttrap_enabled()) { | ||
| 115 | *dstptr = result; | ||
| 116 | return(INEXACTEXCEPTION); | ||
| 117 | } | ||
| 118 | else Set_inexactflag(); | ||
| 119 | } | ||
| 120 | *dstptr = result; | ||
| 121 | return(NOEXCEPTION); | ||
| 122 | } | ||
| 123 | |||
| 124 | /* | ||
| 125 | * Single Fixed-point to Double Floating-point | ||
| 126 | */ | ||
| 127 | |||
| 128 | int | ||
| 129 | sgl_to_dbl_fcnvxf( | ||
| 130 | int *srcptr, | ||
| 131 | unsigned int *nullptr, | ||
| 132 | dbl_floating_point *dstptr, | ||
| 133 | unsigned int *status) | ||
| 134 | { | ||
| 135 | register int src, dst_exponent; | ||
| 136 | register unsigned int resultp1 = 0, resultp2 = 0; | ||
| 137 | |||
| 138 | src = *srcptr; | ||
| 139 | /* | ||
| 140 | * set sign bit of result and get magnitude of source | ||
| 141 | */ | ||
| 142 | if (src < 0) { | ||
| 143 | Dbl_setone_sign(resultp1); | ||
| 144 | Int_negate(src); | ||
| 145 | } | ||
| 146 | else { | ||
| 147 | Dbl_setzero_sign(resultp1); | ||
| 148 | /* Check for zero */ | ||
| 149 | if (src == 0) { | ||
| 150 | Dbl_setzero(resultp1,resultp2); | ||
| 151 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 152 | return(NOEXCEPTION); | ||
| 153 | } | ||
| 154 | } | ||
| 155 | /* | ||
| 156 | * Generate exponent and normalized mantissa | ||
| 157 | */ | ||
| 158 | dst_exponent = 16; /* initialize for normalization */ | ||
| 159 | /* | ||
| 160 | * Check word for most significant bit set. Returns | ||
| 161 | * a value in dst_exponent indicating the bit position, | ||
| 162 | * between -1 and 30. | ||
| 163 | */ | ||
| 164 | Find_ms_one_bit(src,dst_exponent); | ||
| 165 | /* left justify source, with msb at bit position 1 */ | ||
| 166 | if (dst_exponent >= 0) src <<= dst_exponent; | ||
| 167 | else src = 1 << 30; | ||
| 168 | Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1); | ||
| 169 | Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH)); | ||
| 170 | Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent); | ||
| 171 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 172 | return(NOEXCEPTION); | ||
| 173 | } | ||
| 174 | |||
| 175 | /* | ||
| 176 | * Double Fixed-point to Single Floating-point | ||
| 177 | */ | ||
| 178 | |||
| 179 | int | ||
| 180 | dbl_to_sgl_fcnvxf( | ||
| 181 | dbl_integer *srcptr, | ||
| 182 | unsigned int *nullptr, | ||
| 183 | sgl_floating_point *dstptr, | ||
| 184 | unsigned int *status) | ||
| 185 | { | ||
| 186 | int dst_exponent, srcp1; | ||
| 187 | unsigned int result = 0, srcp2; | ||
| 188 | |||
| 189 | Dint_copyfromptr(srcptr,srcp1,srcp2); | ||
| 190 | /* | ||
| 191 | * set sign bit of result and get magnitude of source | ||
| 192 | */ | ||
| 193 | if (srcp1 < 0) { | ||
| 194 | Sgl_setone_sign(result); | ||
| 195 | Dint_negate(srcp1,srcp2); | ||
| 196 | } | ||
| 197 | else { | ||
| 198 | Sgl_setzero_sign(result); | ||
| 199 | /* Check for zero */ | ||
| 200 | if (srcp1 == 0 && srcp2 == 0) { | ||
| 201 | Sgl_setzero(result); | ||
| 202 | *dstptr = result; | ||
| 203 | return(NOEXCEPTION); | ||
| 204 | } | ||
| 205 | } | ||
| 206 | /* | ||
| 207 | * Generate exponent and normalized mantissa | ||
| 208 | */ | ||
| 209 | dst_exponent = 16; /* initialize for normalization */ | ||
| 210 | if (srcp1 == 0) { | ||
| 211 | /* | ||
| 212 | * Check word for most significant bit set. Returns | ||
| 213 | * a value in dst_exponent indicating the bit position, | ||
| 214 | * between -1 and 30. | ||
| 215 | */ | ||
| 216 | Find_ms_one_bit(srcp2,dst_exponent); | ||
| 217 | /* left justify source, with msb at bit position 1 */ | ||
| 218 | if (dst_exponent >= 0) { | ||
| 219 | srcp1 = srcp2 << dst_exponent; | ||
| 220 | srcp2 = 0; | ||
| 221 | } | ||
| 222 | else { | ||
| 223 | srcp1 = srcp2 >> 1; | ||
| 224 | srcp2 <<= 31; | ||
| 225 | } | ||
| 226 | /* | ||
| 227 | * since msb set is in second word, need to | ||
| 228 | * adjust bit position count | ||
| 229 | */ | ||
| 230 | dst_exponent += 32; | ||
| 231 | } | ||
| 232 | else { | ||
| 233 | /* | ||
| 234 | * Check word for most significant bit set. Returns | ||
| 235 | * a value in dst_exponent indicating the bit position, | ||
| 236 | * between -1 and 30. | ||
| 237 | * | ||
| 238 | */ | ||
| 239 | Find_ms_one_bit(srcp1,dst_exponent); | ||
| 240 | /* left justify source, with msb at bit position 1 */ | ||
| 241 | if (dst_exponent > 0) { | ||
| 242 | Variable_shift_double(srcp1,srcp2,(32-dst_exponent), | ||
| 243 | srcp1); | ||
| 244 | srcp2 <<= dst_exponent; | ||
| 245 | } | ||
| 246 | /* | ||
| 247 | * If dst_exponent = 0, we don't need to shift anything. | ||
| 248 | * If dst_exponent = -1, src = - 2**63 so we won't need to | ||
| 249 | * shift srcp2. | ||
| 250 | */ | ||
| 251 | else srcp1 >>= -(dst_exponent); | ||
| 252 | } | ||
| 253 | Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1); | ||
| 254 | Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent); | ||
| 255 | |||
| 256 | /* check for inexact */ | ||
| 257 | if (Dint_isinexact_to_sgl(srcp1,srcp2)) { | ||
| 258 | switch (Rounding_mode()) { | ||
| 259 | case ROUNDPLUS: | ||
| 260 | if (Sgl_iszero_sign(result)) | ||
| 261 | Sgl_increment(result); | ||
| 262 | break; | ||
| 263 | case ROUNDMINUS: | ||
| 264 | if (Sgl_isone_sign(result)) | ||
| 265 | Sgl_increment(result); | ||
| 266 | break; | ||
| 267 | case ROUNDNEAREST: | ||
| 268 | Sgl_roundnearest_from_dint(srcp1,srcp2,result); | ||
| 269 | } | ||
| 270 | if (Is_inexacttrap_enabled()) { | ||
| 271 | *dstptr = result; | ||
| 272 | return(INEXACTEXCEPTION); | ||
| 273 | } | ||
| 274 | else Set_inexactflag(); | ||
| 275 | } | ||
| 276 | *dstptr = result; | ||
| 277 | return(NOEXCEPTION); | ||
| 278 | } | ||
| 279 | |||
| 280 | /* | ||
| 281 | * Double Fixed-point to Double Floating-point | ||
| 282 | */ | ||
| 283 | |||
| 284 | int | ||
| 285 | dbl_to_dbl_fcnvxf( | ||
| 286 | dbl_integer *srcptr, | ||
| 287 | unsigned int *nullptr, | ||
| 288 | dbl_floating_point *dstptr, | ||
| 289 | unsigned int *status) | ||
| 290 | { | ||
| 291 | register int srcp1, dst_exponent; | ||
| 292 | register unsigned int srcp2, resultp1 = 0, resultp2 = 0; | ||
| 293 | |||
| 294 | Dint_copyfromptr(srcptr,srcp1,srcp2); | ||
| 295 | /* | ||
| 296 | * set sign bit of result and get magnitude of source | ||
| 297 | */ | ||
| 298 | if (srcp1 < 0) { | ||
| 299 | Dbl_setone_sign(resultp1); | ||
| 300 | Dint_negate(srcp1,srcp2); | ||
| 301 | } | ||
| 302 | else { | ||
| 303 | Dbl_setzero_sign(resultp1); | ||
| 304 | /* Check for zero */ | ||
| 305 | if (srcp1 == 0 && srcp2 ==0) { | ||
| 306 | Dbl_setzero(resultp1,resultp2); | ||
| 307 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 308 | return(NOEXCEPTION); | ||
| 309 | } | ||
| 310 | } | ||
| 311 | /* | ||
| 312 | * Generate exponent and normalized mantissa | ||
| 313 | */ | ||
| 314 | dst_exponent = 16; /* initialize for normalization */ | ||
| 315 | if (srcp1 == 0) { | ||
| 316 | /* | ||
| 317 | * Check word for most significant bit set. Returns | ||
| 318 | * a value in dst_exponent indicating the bit position, | ||
| 319 | * between -1 and 30. | ||
| 320 | */ | ||
| 321 | Find_ms_one_bit(srcp2,dst_exponent); | ||
| 322 | /* left justify source, with msb at bit position 1 */ | ||
| 323 | if (dst_exponent >= 0) { | ||
| 324 | srcp1 = srcp2 << dst_exponent; | ||
| 325 | srcp2 = 0; | ||
| 326 | } | ||
| 327 | else { | ||
| 328 | srcp1 = srcp2 >> 1; | ||
| 329 | srcp2 <<= 31; | ||
| 330 | } | ||
| 331 | /* | ||
| 332 | * since msb set is in second word, need to | ||
| 333 | * adjust bit position count | ||
| 334 | */ | ||
| 335 | dst_exponent += 32; | ||
| 336 | } | ||
| 337 | else { | ||
| 338 | /* | ||
| 339 | * Check word for most significant bit set. Returns | ||
| 340 | * a value in dst_exponent indicating the bit position, | ||
| 341 | * between -1 and 30. | ||
| 342 | */ | ||
| 343 | Find_ms_one_bit(srcp1,dst_exponent); | ||
| 344 | /* left justify source, with msb at bit position 1 */ | ||
| 345 | if (dst_exponent > 0) { | ||
| 346 | Variable_shift_double(srcp1,srcp2,(32-dst_exponent), | ||
| 347 | srcp1); | ||
| 348 | srcp2 <<= dst_exponent; | ||
| 349 | } | ||
| 350 | /* | ||
| 351 | * If dst_exponent = 0, we don't need to shift anything. | ||
| 352 | * If dst_exponent = -1, src = - 2**63 so we won't need to | ||
| 353 | * shift srcp2. | ||
| 354 | */ | ||
| 355 | else srcp1 >>= -(dst_exponent); | ||
| 356 | } | ||
| 357 | Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1)); | ||
| 358 | Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2); | ||
| 359 | Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent); | ||
| 360 | |||
| 361 | /* check for inexact */ | ||
| 362 | if (Dint_isinexact_to_dbl(srcp2)) { | ||
| 363 | switch (Rounding_mode()) { | ||
| 364 | case ROUNDPLUS: | ||
| 365 | if (Dbl_iszero_sign(resultp1)) { | ||
| 366 | Dbl_increment(resultp1,resultp2); | ||
| 367 | } | ||
| 368 | break; | ||
| 369 | case ROUNDMINUS: | ||
| 370 | if (Dbl_isone_sign(resultp1)) { | ||
| 371 | Dbl_increment(resultp1,resultp2); | ||
| 372 | } | ||
| 373 | break; | ||
| 374 | case ROUNDNEAREST: | ||
| 375 | Dbl_roundnearest_from_dint(srcp2,resultp1, | ||
| 376 | resultp2); | ||
| 377 | } | ||
| 378 | if (Is_inexacttrap_enabled()) { | ||
| 379 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 380 | return(INEXACTEXCEPTION); | ||
| 381 | } | ||
| 382 | else Set_inexactflag(); | ||
| 383 | } | ||
| 384 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 385 | return(NOEXCEPTION); | ||
| 386 | } | ||
diff --git a/arch/parisc/math-emu/float.h b/arch/parisc/math-emu/float.h new file mode 100644 index 000000000000..ce76f6dfa25b --- /dev/null +++ b/arch/parisc/math-emu/float.h | |||
| @@ -0,0 +1,582 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/float.h $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * <<please update with a synopis of the functionality provided by this file>> | ||
| 29 | * | ||
| 30 | * BE header: no | ||
| 31 | * | ||
| 32 | * Shipped: yes | ||
| 33 | * /usr/conf/pa/spmath/float.h | ||
| 34 | * | ||
| 35 | * END_DESC | ||
| 36 | */ | ||
| 37 | |||
| 38 | #ifdef __NO_PA_HDRS | ||
| 39 | PA header file -- do not include this header file for non-PA builds. | ||
| 40 | #endif | ||
| 41 | |||
| 42 | #include "fpbits.h" | ||
| 43 | #include "hppa.h" | ||
| 44 | /* | ||
| 45 | * Want to pick up the FPU capability flags, not the PDC structures. | ||
| 46 | * 'LOCORE' isn't really true in this case, but we don't want the C structures | ||
| 47 | * so it suits our purposes | ||
| 48 | */ | ||
| 49 | #define LOCORE | ||
| 50 | #include "fpu.h" | ||
| 51 | |||
| 52 | /* | ||
| 53 | * Declare the basic structures for the 3 different | ||
| 54 | * floating-point precisions. | ||
| 55 | * | ||
| 56 | * Single number | ||
| 57 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 58 | * |s| exp | mantissa | | ||
| 59 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 60 | */ | ||
| 61 | #define Sall(object) (object) | ||
| 62 | #define Ssign(object) Bitfield_extract( 0, 1,object) | ||
| 63 | #define Ssignedsign(object) Bitfield_signed_extract( 0, 1,object) | ||
| 64 | #define Sexponent(object) Bitfield_extract( 1, 8,object) | ||
| 65 | #define Smantissa(object) Bitfield_mask( 9, 23,object) | ||
| 66 | #define Ssignaling(object) Bitfield_extract( 9, 1,object) | ||
| 67 | #define Ssignalingnan(object) Bitfield_extract( 1, 9,object) | ||
| 68 | #define Shigh2mantissa(object) Bitfield_extract( 9, 2,object) | ||
| 69 | #define Sexponentmantissa(object) Bitfield_mask( 1, 31,object) | ||
| 70 | #define Ssignexponent(object) Bitfield_extract( 0, 9,object) | ||
| 71 | #define Shidden(object) Bitfield_extract( 8, 1,object) | ||
| 72 | #define Shiddenoverflow(object) Bitfield_extract( 7, 1,object) | ||
| 73 | #define Shiddenhigh7mantissa(object) Bitfield_extract( 8, 8,object) | ||
| 74 | #define Shiddenhigh3mantissa(object) Bitfield_extract( 8, 4,object) | ||
| 75 | #define Slow(object) Bitfield_mask( 31, 1,object) | ||
| 76 | #define Slow4(object) Bitfield_mask( 28, 4,object) | ||
| 77 | #define Slow31(object) Bitfield_mask( 1, 31,object) | ||
| 78 | #define Shigh31(object) Bitfield_extract( 0, 31,object) | ||
| 79 | #define Ssignedhigh31(object) Bitfield_signed_extract( 0, 31,object) | ||
| 80 | #define Shigh4(object) Bitfield_extract( 0, 4,object) | ||
| 81 | #define Sbit24(object) Bitfield_extract( 24, 1,object) | ||
| 82 | #define Sbit28(object) Bitfield_extract( 28, 1,object) | ||
| 83 | #define Sbit29(object) Bitfield_extract( 29, 1,object) | ||
| 84 | #define Sbit30(object) Bitfield_extract( 30, 1,object) | ||
| 85 | #define Sbit31(object) Bitfield_mask( 31, 1,object) | ||
| 86 | |||
| 87 | #define Deposit_ssign(object,value) Bitfield_deposit(value,0,1,object) | ||
| 88 | #define Deposit_sexponent(object,value) Bitfield_deposit(value,1,8,object) | ||
| 89 | #define Deposit_smantissa(object,value) Bitfield_deposit(value,9,23,object) | ||
| 90 | #define Deposit_shigh2mantissa(object,value) Bitfield_deposit(value,9,2,object) | ||
| 91 | #define Deposit_sexponentmantissa(object,value) \ | ||
| 92 | Bitfield_deposit(value,1,31,object) | ||
| 93 | #define Deposit_ssignexponent(object,value) Bitfield_deposit(value,0,9,object) | ||
| 94 | #define Deposit_slow(object,value) Bitfield_deposit(value,31,1,object) | ||
| 95 | #define Deposit_shigh4(object,value) Bitfield_deposit(value,0,4,object) | ||
| 96 | |||
| 97 | #define Is_ssign(object) Bitfield_mask( 0, 1,object) | ||
| 98 | #define Is_ssignaling(object) Bitfield_mask( 9, 1,object) | ||
| 99 | #define Is_shidden(object) Bitfield_mask( 8, 1,object) | ||
| 100 | #define Is_shiddenoverflow(object) Bitfield_mask( 7, 1,object) | ||
| 101 | #define Is_slow(object) Bitfield_mask( 31, 1,object) | ||
| 102 | #define Is_sbit24(object) Bitfield_mask( 24, 1,object) | ||
| 103 | #define Is_sbit28(object) Bitfield_mask( 28, 1,object) | ||
| 104 | #define Is_sbit29(object) Bitfield_mask( 29, 1,object) | ||
| 105 | #define Is_sbit30(object) Bitfield_mask( 30, 1,object) | ||
| 106 | #define Is_sbit31(object) Bitfield_mask( 31, 1,object) | ||
| 107 | |||
| 108 | /* | ||
| 109 | * Double number. | ||
| 110 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 111 | * |s| exponent | mantissa part 1 | | ||
| 112 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 113 | * | ||
| 114 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 115 | * | mantissa part 2 | | ||
| 116 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 117 | */ | ||
| 118 | #define Dallp1(object) (object) | ||
| 119 | #define Dsign(object) Bitfield_extract( 0, 1,object) | ||
| 120 | #define Dsignedsign(object) Bitfield_signed_extract( 0, 1,object) | ||
| 121 | #define Dexponent(object) Bitfield_extract( 1, 11,object) | ||
| 122 | #define Dmantissap1(object) Bitfield_mask( 12, 20,object) | ||
| 123 | #define Dsignaling(object) Bitfield_extract( 12, 1,object) | ||
| 124 | #define Dsignalingnan(object) Bitfield_extract( 1, 12,object) | ||
| 125 | #define Dhigh2mantissa(object) Bitfield_extract( 12, 2,object) | ||
| 126 | #define Dexponentmantissap1(object) Bitfield_mask( 1, 31,object) | ||
| 127 | #define Dsignexponent(object) Bitfield_extract( 0, 12,object) | ||
| 128 | #define Dhidden(object) Bitfield_extract( 11, 1,object) | ||
| 129 | #define Dhiddenoverflow(object) Bitfield_extract( 10, 1,object) | ||
| 130 | #define Dhiddenhigh7mantissa(object) Bitfield_extract( 11, 8,object) | ||
| 131 | #define Dhiddenhigh3mantissa(object) Bitfield_extract( 11, 4,object) | ||
| 132 | #define Dlowp1(object) Bitfield_mask( 31, 1,object) | ||
| 133 | #define Dlow31p1(object) Bitfield_mask( 1, 31,object) | ||
| 134 | #define Dhighp1(object) Bitfield_extract( 0, 1,object) | ||
| 135 | #define Dhigh4p1(object) Bitfield_extract( 0, 4,object) | ||
| 136 | #define Dhigh31p1(object) Bitfield_extract( 0, 31,object) | ||
| 137 | #define Dsignedhigh31p1(object) Bitfield_signed_extract( 0, 31,object) | ||
| 138 | #define Dbit3p1(object) Bitfield_extract( 3, 1,object) | ||
| 139 | |||
| 140 | #define Deposit_dsign(object,value) Bitfield_deposit(value,0,1,object) | ||
| 141 | #define Deposit_dexponent(object,value) Bitfield_deposit(value,1,11,object) | ||
| 142 | #define Deposit_dmantissap1(object,value) Bitfield_deposit(value,12,20,object) | ||
| 143 | #define Deposit_dhigh2mantissa(object,value) Bitfield_deposit(value,12,2,object) | ||
| 144 | #define Deposit_dexponentmantissap1(object,value) \ | ||
| 145 | Bitfield_deposit(value,1,31,object) | ||
| 146 | #define Deposit_dsignexponent(object,value) Bitfield_deposit(value,0,12,object) | ||
| 147 | #define Deposit_dlowp1(object,value) Bitfield_deposit(value,31,1,object) | ||
| 148 | #define Deposit_dhigh4p1(object,value) Bitfield_deposit(value,0,4,object) | ||
| 149 | |||
| 150 | #define Is_dsign(object) Bitfield_mask( 0, 1,object) | ||
| 151 | #define Is_dsignaling(object) Bitfield_mask( 12, 1,object) | ||
| 152 | #define Is_dhidden(object) Bitfield_mask( 11, 1,object) | ||
| 153 | #define Is_dhiddenoverflow(object) Bitfield_mask( 10, 1,object) | ||
| 154 | #define Is_dlowp1(object) Bitfield_mask( 31, 1,object) | ||
| 155 | #define Is_dhighp1(object) Bitfield_mask( 0, 1,object) | ||
| 156 | #define Is_dbit3p1(object) Bitfield_mask( 3, 1,object) | ||
| 157 | |||
| 158 | #define Dallp2(object) (object) | ||
| 159 | #define Dmantissap2(object) (object) | ||
| 160 | #define Dlowp2(object) Bitfield_mask( 31, 1,object) | ||
| 161 | #define Dlow4p2(object) Bitfield_mask( 28, 4,object) | ||
| 162 | #define Dlow31p2(object) Bitfield_mask( 1, 31,object) | ||
| 163 | #define Dhighp2(object) Bitfield_extract( 0, 1,object) | ||
| 164 | #define Dhigh31p2(object) Bitfield_extract( 0, 31,object) | ||
| 165 | #define Dbit2p2(object) Bitfield_extract( 2, 1,object) | ||
| 166 | #define Dbit3p2(object) Bitfield_extract( 3, 1,object) | ||
| 167 | #define Dbit21p2(object) Bitfield_extract( 21, 1,object) | ||
| 168 | #define Dbit28p2(object) Bitfield_extract( 28, 1,object) | ||
| 169 | #define Dbit29p2(object) Bitfield_extract( 29, 1,object) | ||
| 170 | #define Dbit30p2(object) Bitfield_extract( 30, 1,object) | ||
| 171 | #define Dbit31p2(object) Bitfield_mask( 31, 1,object) | ||
| 172 | |||
| 173 | #define Deposit_dlowp2(object,value) Bitfield_deposit(value,31,1,object) | ||
| 174 | |||
| 175 | #define Is_dlowp2(object) Bitfield_mask( 31, 1,object) | ||
| 176 | #define Is_dhighp2(object) Bitfield_mask( 0, 1,object) | ||
| 177 | #define Is_dbit2p2(object) Bitfield_mask( 2, 1,object) | ||
| 178 | #define Is_dbit3p2(object) Bitfield_mask( 3, 1,object) | ||
| 179 | #define Is_dbit21p2(object) Bitfield_mask( 21, 1,object) | ||
| 180 | #define Is_dbit28p2(object) Bitfield_mask( 28, 1,object) | ||
| 181 | #define Is_dbit29p2(object) Bitfield_mask( 29, 1,object) | ||
| 182 | #define Is_dbit30p2(object) Bitfield_mask( 30, 1,object) | ||
| 183 | #define Is_dbit31p2(object) Bitfield_mask( 31, 1,object) | ||
| 184 | |||
| 185 | /* | ||
| 186 | * Quad number. | ||
| 187 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 188 | * |s| exponent | mantissa part 1 | | ||
| 189 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 190 | * | ||
| 191 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 192 | * | mantissa part 2 | | ||
| 193 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 194 | * | ||
| 195 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 196 | * | mantissa part 3 | | ||
| 197 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 198 | * | ||
| 199 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 200 | * | mantissa part 4 | | ||
| 201 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 202 | */ | ||
| 203 | typedef struct | ||
| 204 | { | ||
| 205 | union | ||
| 206 | { | ||
| 207 | struct { unsigned qallp1; } u_qallp1; | ||
| 208 | /* Not needed for now... | ||
| 209 | Bitfield_extract( 0, 1,u_qsign,qsign) | ||
| 210 | Bitfield_signed_extract( 0, 1,u_qsignedsign,qsignedsign) | ||
| 211 | Bitfield_extract( 1, 15,u_qexponent,qexponent) | ||
| 212 | Bitfield_extract(16, 16,u_qmantissap1,qmantissap1) | ||
| 213 | Bitfield_extract(16, 1,u_qsignaling,qsignaling) | ||
| 214 | Bitfield_extract(1, 16,u_qsignalingnan,qsignalingnan) | ||
| 215 | Bitfield_extract(16, 2,u_qhigh2mantissa,qhigh2mantissa) | ||
| 216 | Bitfield_extract( 1, 31,u_qexponentmantissap1,qexponentmantissap1) | ||
| 217 | Bitfield_extract( 0, 16,u_qsignexponent,qsignexponent) | ||
| 218 | Bitfield_extract(15, 1,u_qhidden,qhidden) | ||
| 219 | Bitfield_extract(14, 1,u_qhiddenoverflow,qhiddenoverflow) | ||
| 220 | Bitfield_extract(15, 8,u_qhiddenhigh7mantissa,qhiddenhigh7mantissa) | ||
| 221 | Bitfield_extract(15, 4,u_qhiddenhigh3mantissa,qhiddenhigh3mantissa) | ||
| 222 | Bitfield_extract(31, 1,u_qlowp1,qlowp1) | ||
| 223 | Bitfield_extract( 1, 31,u_qlow31p1,qlow31p1) | ||
| 224 | Bitfield_extract( 0, 1,u_qhighp1,qhighp1) | ||
| 225 | Bitfield_extract( 0, 4,u_qhigh4p1,qhigh4p1) | ||
| 226 | Bitfield_extract( 0, 31,u_qhigh31p1,qhigh31p1) | ||
| 227 | */ | ||
| 228 | } quad_u1; | ||
| 229 | union | ||
| 230 | { | ||
| 231 | struct { unsigned qallp2; } u_qallp2; | ||
| 232 | /* Not needed for now... | ||
| 233 | Bitfield_extract(31, 1,u_qlowp2,qlowp2) | ||
| 234 | Bitfield_extract( 1, 31,u_qlow31p2,qlow31p2) | ||
| 235 | Bitfield_extract( 0, 1,u_qhighp2,qhighp2) | ||
| 236 | Bitfield_extract( 0, 31,u_qhigh31p2,qhigh31p2) | ||
| 237 | */ | ||
| 238 | } quad_u2; | ||
| 239 | union | ||
| 240 | { | ||
| 241 | struct { unsigned qallp3; } u_qallp3; | ||
| 242 | /* Not needed for now... | ||
| 243 | Bitfield_extract(31, 1,u_qlowp3,qlowp3) | ||
| 244 | Bitfield_extract( 1, 31,u_qlow31p3,qlow31p3) | ||
| 245 | Bitfield_extract( 0, 1,u_qhighp3,qhighp3) | ||
| 246 | Bitfield_extract( 0, 31,u_qhigh31p3,qhigh31p3) | ||
| 247 | */ | ||
| 248 | } quad_u3; | ||
| 249 | union | ||
| 250 | { | ||
| 251 | struct { unsigned qallp4; } u_qallp4; | ||
| 252 | /* Not need for now... | ||
| 253 | Bitfield_extract(31, 1,u_qlowp4,qlowp4) | ||
| 254 | Bitfield_extract( 1, 31,u_qlow31p4,qlow31p4) | ||
| 255 | Bitfield_extract( 0, 1,u_qhighp4,qhighp4) | ||
| 256 | Bitfield_extract( 0, 31,u_qhigh31p4,qhigh31p4) | ||
| 257 | */ | ||
| 258 | } quad_u4; | ||
| 259 | } quad_floating_point; | ||
| 260 | |||
| 261 | /* Extension - An additional structure to hold the guard, round and | ||
| 262 | * sticky bits during computations. | ||
| 263 | */ | ||
| 264 | #define Extall(object) (object) | ||
| 265 | #define Extsign(object) Bitfield_extract( 0, 1,object) | ||
| 266 | #define Exthigh31(object) Bitfield_extract( 0, 31,object) | ||
| 267 | #define Extlow31(object) Bitfield_extract( 1, 31,object) | ||
| 268 | #define Extlow(object) Bitfield_extract( 31, 1,object) | ||
| 269 | |||
| 270 | /* | ||
| 271 | * Single extended - The upper word is just like single precision, | ||
| 272 | * but one additional word of mantissa is needed. | ||
| 273 | */ | ||
| 274 | #define Sextallp1(object) (object) | ||
| 275 | #define Sextallp2(object) (object) | ||
| 276 | #define Sextlowp1(object) Bitfield_extract( 31, 1,object) | ||
| 277 | #define Sexthighp2(object) Bitfield_extract( 0, 1,object) | ||
| 278 | #define Sextlow31p2(object) Bitfield_extract( 1, 31,object) | ||
| 279 | #define Sexthiddenoverflow(object) Bitfield_extract( 4, 1,object) | ||
| 280 | #define Is_sexthiddenoverflow(object) Bitfield_mask( 4, 1,object) | ||
| 281 | |||
| 282 | /* | ||
| 283 | * Double extended - The upper two words are just like double precision, | ||
| 284 | * but two additional words of mantissa are needed. | ||
| 285 | */ | ||
| 286 | #define Dextallp1(object) (object) | ||
| 287 | #define Dextallp2(object) (object) | ||
| 288 | #define Dextallp3(object) (object) | ||
| 289 | #define Dextallp4(object) (object) | ||
| 290 | #define Dextlowp2(object) Bitfield_extract( 31, 1,object) | ||
| 291 | #define Dexthighp3(object) Bitfield_extract( 0, 1,object) | ||
| 292 | #define Dextlow31p3(object) Bitfield_extract( 1, 31,object) | ||
| 293 | #define Dexthiddenoverflow(object) Bitfield_extract( 10, 1,object) | ||
| 294 | #define Is_dexthiddenoverflow(object) Bitfield_mask( 10, 1,object) | ||
| 295 | #define Deposit_dextlowp4(object,value) Bitfield_deposit(value,31,1,object) | ||
| 296 | |||
| 297 | /* | ||
| 298 | * Declare the basic structures for the 3 different | ||
| 299 | * fixed-point precisions. | ||
| 300 | * | ||
| 301 | * Single number | ||
| 302 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 303 | * |s| integer | | ||
| 304 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 305 | */ | ||
| 306 | typedef int sgl_integer; | ||
| 307 | |||
| 308 | /* | ||
| 309 | * Double number. | ||
| 310 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 311 | * |s| high integer | | ||
| 312 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 313 | * | ||
| 314 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 315 | * | low integer | | ||
| 316 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 317 | */ | ||
| 318 | struct dint { | ||
| 319 | int wd0; | ||
| 320 | unsigned int wd1; | ||
| 321 | }; | ||
| 322 | |||
| 323 | struct dblwd { | ||
| 324 | unsigned int wd0; | ||
| 325 | unsigned int wd1; | ||
| 326 | }; | ||
| 327 | |||
| 328 | /* | ||
| 329 | * Quad number. | ||
| 330 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 331 | * |s| integer part1 | | ||
| 332 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 333 | * | ||
| 334 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 335 | * | integer part 2 | | ||
| 336 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 337 | * | ||
| 338 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 339 | * | integer part 3 | | ||
| 340 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 341 | * | ||
| 342 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 343 | * | integer part 4 | | ||
| 344 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 345 | */ | ||
| 346 | |||
| 347 | struct quadwd { | ||
| 348 | int wd0; | ||
| 349 | unsigned int wd1; | ||
| 350 | unsigned int wd2; | ||
| 351 | unsigned int wd3; | ||
| 352 | }; | ||
| 353 | |||
| 354 | typedef struct quadwd quad_integer; | ||
| 355 | |||
| 356 | |||
| 357 | /* useful typedefs */ | ||
| 358 | typedef unsigned int sgl_floating_point; | ||
| 359 | typedef struct dblwd dbl_floating_point; | ||
| 360 | typedef struct dint dbl_integer; | ||
| 361 | typedef struct dblwd dbl_unsigned; | ||
| 362 | |||
| 363 | /* | ||
| 364 | * Define the different precisions' parameters. | ||
| 365 | */ | ||
| 366 | #define SGL_BITLENGTH 32 | ||
| 367 | #define SGL_EMAX 127 | ||
| 368 | #define SGL_EMIN (-126) | ||
| 369 | #define SGL_BIAS 127 | ||
| 370 | #define SGL_WRAP 192 | ||
| 371 | #define SGL_INFINITY_EXPONENT (SGL_EMAX+SGL_BIAS+1) | ||
| 372 | #define SGL_THRESHOLD 32 | ||
| 373 | #define SGL_EXP_LENGTH 8 | ||
| 374 | #define SGL_P 24 | ||
| 375 | |||
| 376 | #define DBL_BITLENGTH 64 | ||
| 377 | #define DBL_EMAX 1023 | ||
| 378 | #define DBL_EMIN (-1022) | ||
| 379 | #define DBL_BIAS 1023 | ||
| 380 | #define DBL_WRAP 1536 | ||
| 381 | #define DBL_INFINITY_EXPONENT (DBL_EMAX+DBL_BIAS+1) | ||
| 382 | #define DBL_THRESHOLD 64 | ||
| 383 | #define DBL_EXP_LENGTH 11 | ||
| 384 | #define DBL_P 53 | ||
| 385 | |||
| 386 | #define QUAD_BITLENGTH 128 | ||
| 387 | #define QUAD_EMAX 16383 | ||
| 388 | #define QUAD_EMIN (-16382) | ||
| 389 | #define QUAD_BIAS 16383 | ||
| 390 | #define QUAD_WRAP 24576 | ||
| 391 | #define QUAD_INFINITY_EXPONENT (QUAD_EMAX+QUAD_BIAS+1) | ||
| 392 | #define QUAD_P 113 | ||
| 393 | |||
| 394 | /* Boolean Values etc. */ | ||
| 395 | #define FALSE 0 | ||
| 396 | #define TRUE (!FALSE) | ||
| 397 | #define NOT ! | ||
| 398 | #define XOR ^ | ||
| 399 | |||
| 400 | /* other constants */ | ||
| 401 | #undef NULL | ||
| 402 | #define NULL 0 | ||
| 403 | #define NIL 0 | ||
| 404 | #define SGL 0 | ||
| 405 | #define DBL 1 | ||
| 406 | #define BADFMT 2 | ||
| 407 | #define QUAD 3 | ||
| 408 | |||
| 409 | |||
| 410 | /* Types */ | ||
| 411 | typedef int boolean; | ||
| 412 | typedef int FORMAT; | ||
| 413 | typedef int VOID; | ||
| 414 | |||
| 415 | |||
| 416 | /* Declare status register equivalent to FPUs architecture. | ||
| 417 | * | ||
| 418 | * 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1 | ||
| 419 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 420 | * |V|Z|O|U|I|C| rsv | model | version |RM |rsv|T|r|V|Z|O|U|I| | ||
| 421 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 422 | */ | ||
| 423 | #define Cbit(object) Bitfield_extract( 5, 1,object) | ||
| 424 | #define Tbit(object) Bitfield_extract( 25, 1,object) | ||
| 425 | #define Roundingmode(object) Bitfield_extract( 21, 2,object) | ||
| 426 | #define Invalidtrap(object) Bitfield_extract( 27, 1,object) | ||
| 427 | #define Divisionbyzerotrap(object) Bitfield_extract( 28, 1,object) | ||
| 428 | #define Overflowtrap(object) Bitfield_extract( 29, 1,object) | ||
| 429 | #define Underflowtrap(object) Bitfield_extract( 30, 1,object) | ||
| 430 | #define Inexacttrap(object) Bitfield_extract( 31, 1,object) | ||
| 431 | #define Invalidflag(object) Bitfield_extract( 0, 1,object) | ||
| 432 | #define Divisionbyzeroflag(object) Bitfield_extract( 1, 1,object) | ||
| 433 | #define Overflowflag(object) Bitfield_extract( 2, 1,object) | ||
| 434 | #define Underflowflag(object) Bitfield_extract( 3, 1,object) | ||
| 435 | #define Inexactflag(object) Bitfield_extract( 4, 1,object) | ||
| 436 | #define Allflags(object) Bitfield_extract( 0, 5,object) | ||
| 437 | |||
| 438 | /* Definitions relevant to the status register */ | ||
| 439 | |||
| 440 | /* Rounding Modes */ | ||
| 441 | #define ROUNDNEAREST 0 | ||
| 442 | #define ROUNDZERO 1 | ||
| 443 | #define ROUNDPLUS 2 | ||
| 444 | #define ROUNDMINUS 3 | ||
| 445 | |||
| 446 | /* Exceptions */ | ||
| 447 | #define NOEXCEPTION 0x0 | ||
| 448 | #define INVALIDEXCEPTION 0x20 | ||
| 449 | #define DIVISIONBYZEROEXCEPTION 0x10 | ||
| 450 | #define OVERFLOWEXCEPTION 0x08 | ||
| 451 | #define UNDERFLOWEXCEPTION 0x04 | ||
| 452 | #define INEXACTEXCEPTION 0x02 | ||
| 453 | #define UNIMPLEMENTEDEXCEPTION 0x01 | ||
| 454 | |||
| 455 | /* New exceptions for the 2E Opcode */ | ||
| 456 | #define OPC_2E_INVALIDEXCEPTION 0x30 | ||
| 457 | #define OPC_2E_OVERFLOWEXCEPTION 0x18 | ||
| 458 | #define OPC_2E_UNDERFLOWEXCEPTION 0x0c | ||
| 459 | #define OPC_2E_INEXACTEXCEPTION 0x12 | ||
| 460 | |||
| 461 | /* Declare exception registers equivalent to FPUs architecture | ||
| 462 | * | ||
| 463 | * 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1 | ||
| 464 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 465 | * |excepttype | r1 | r2/ext | operation |parm |n| t/cond | | ||
| 466 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 467 | */ | ||
| 468 | #define Allexception(object) (object) | ||
| 469 | #define Exceptiontype(object) Bitfield_extract( 0, 6,object) | ||
| 470 | #define Instructionfield(object) Bitfield_mask( 6,26,object) | ||
| 471 | #define Parmfield(object) Bitfield_extract( 23, 3,object) | ||
| 472 | #define Rabit(object) Bitfield_extract( 24, 1,object) | ||
| 473 | #define Ibit(object) Bitfield_extract( 25, 1,object) | ||
| 474 | |||
| 475 | #define Set_exceptiontype(object,value) Bitfield_deposit(value, 0, 6,object) | ||
| 476 | #define Set_parmfield(object,value) Bitfield_deposit(value, 23, 3,object) | ||
| 477 | #define Set_exceptiontype_and_instr_field(exception,instruction,object) \ | ||
| 478 | object = exception << 26 | instruction | ||
| 479 | |||
| 480 | /* Declare the condition field | ||
| 481 | * | ||
| 482 | * 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1 | ||
| 483 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 484 | * | |G|L|E|U|X| | ||
| 485 | * +-------+-------+-------+-------+-------+-------+-------+-------+ | ||
| 486 | */ | ||
| 487 | #define Allexception(object) (object) | ||
| 488 | #define Greaterthanbit(object) Bitfield_extract( 27, 1,object) | ||
| 489 | #define Lessthanbit(object) Bitfield_extract( 28, 1,object) | ||
| 490 | #define Equalbit(object) Bitfield_extract( 29, 1,object) | ||
| 491 | #define Unorderedbit(object) Bitfield_extract( 30, 1,object) | ||
| 492 | #define Exceptionbit(object) Bitfield_extract( 31, 1,object) | ||
| 493 | |||
| 494 | /* An alias name for the status register */ | ||
| 495 | #define Fpustatus_register (*status) | ||
| 496 | |||
| 497 | /************************************************** | ||
| 498 | * Status register referencing and manipulation. * | ||
| 499 | **************************************************/ | ||
| 500 | |||
| 501 | /* Rounding mode */ | ||
| 502 | #define Rounding_mode() Roundingmode(Fpustatus_register) | ||
| 503 | #define Is_rounding_mode(rmode) \ | ||
| 504 | (Roundingmode(Fpustatus_register) == rmode) | ||
| 505 | #define Set_rounding_mode(value) \ | ||
| 506 | Bitfield_deposit(value,21,2,Fpustatus_register) | ||
| 507 | |||
| 508 | /* Boolean testing of the trap enable bits */ | ||
| 509 | #define Is_invalidtrap_enabled() Invalidtrap(Fpustatus_register) | ||
| 510 | #define Is_divisionbyzerotrap_enabled() Divisionbyzerotrap(Fpustatus_register) | ||
| 511 | #define Is_overflowtrap_enabled() Overflowtrap(Fpustatus_register) | ||
| 512 | #define Is_underflowtrap_enabled() Underflowtrap(Fpustatus_register) | ||
| 513 | #define Is_inexacttrap_enabled() Inexacttrap(Fpustatus_register) | ||
| 514 | |||
| 515 | /* Set the indicated flags in the status register */ | ||
| 516 | #define Set_invalidflag() Bitfield_deposit(1,0,1,Fpustatus_register) | ||
| 517 | #define Set_divisionbyzeroflag() Bitfield_deposit(1,1,1,Fpustatus_register) | ||
| 518 | #define Set_overflowflag() Bitfield_deposit(1,2,1,Fpustatus_register) | ||
| 519 | #define Set_underflowflag() Bitfield_deposit(1,3,1,Fpustatus_register) | ||
| 520 | #define Set_inexactflag() Bitfield_deposit(1,4,1,Fpustatus_register) | ||
| 521 | |||
| 522 | #define Clear_all_flags() Bitfield_deposit(0,0,5,Fpustatus_register) | ||
| 523 | |||
| 524 | /* Manipulate the trap and condition code bits (tbit and cbit) */ | ||
| 525 | #define Set_tbit() Bitfield_deposit(1,25,1,Fpustatus_register) | ||
| 526 | #define Clear_tbit() Bitfield_deposit(0,25,1,Fpustatus_register) | ||
| 527 | #define Is_tbit_set() Tbit(Fpustatus_register) | ||
| 528 | #define Is_cbit_set() Cbit(Fpustatus_register) | ||
| 529 | |||
| 530 | #define Set_status_cbit(value) \ | ||
| 531 | Bitfield_deposit(value,5,1,Fpustatus_register) | ||
| 532 | |||
| 533 | /******************************* | ||
| 534 | * Condition field referencing * | ||
| 535 | *******************************/ | ||
| 536 | #define Unordered(cond) Unorderedbit(cond) | ||
| 537 | #define Equal(cond) Equalbit(cond) | ||
| 538 | #define Lessthan(cond) Lessthanbit(cond) | ||
| 539 | #define Greaterthan(cond) Greaterthanbit(cond) | ||
| 540 | #define Exception(cond) Exceptionbit(cond) | ||
| 541 | |||
| 542 | |||
| 543 | /* Defines for the extension */ | ||
| 544 | #define Ext_isone_sign(extent) (Extsign(extent)) | ||
| 545 | #define Ext_isnotzero(extent) \ | ||
| 546 | (Extall(extent)) | ||
| 547 | #define Ext_isnotzero_lower(extent) \ | ||
| 548 | (Extlow31(extent)) | ||
| 549 | #define Ext_leftshiftby1(extent) \ | ||
| 550 | Extall(extent) <<= 1 | ||
| 551 | #define Ext_negate(extent) \ | ||
| 552 | (int )Extall(extent) = 0 - (int )Extall(extent) | ||
| 553 | #define Ext_setone_low(extent) Bitfield_deposit(1,31,1,extent) | ||
| 554 | #define Ext_setzero(extent) Extall(extent) = 0 | ||
| 555 | |||
| 556 | typedef int operation; | ||
| 557 | |||
| 558 | /* error messages */ | ||
| 559 | |||
| 560 | #define NONE 0 | ||
| 561 | #define UNDEFFPINST 1 | ||
| 562 | |||
| 563 | /* Function definitions: opcode, opclass */ | ||
| 564 | #define FTEST (1<<2) | 0 | ||
| 565 | #define FCPY (2<<2) | 0 | ||
| 566 | #define FABS (3<<2) | 0 | ||
| 567 | #define FSQRT (4<<2) | 0 | ||
| 568 | #define FRND (5<<2) | 0 | ||
| 569 | |||
| 570 | #define FCNVFF (0<<2) | 1 | ||
| 571 | #define FCNVXF (1<<2) | 1 | ||
| 572 | #define FCNVFX (2<<2) | 1 | ||
| 573 | #define FCNVFXT (3<<2) | 1 | ||
| 574 | |||
| 575 | #define FCMP (0<<2) | 2 | ||
| 576 | |||
| 577 | #define FADD (0<<2) | 3 | ||
| 578 | #define FSUB (1<<2) | 3 | ||
| 579 | #define FMPY (2<<2) | 3 | ||
| 580 | #define FDIV (3<<2) | 3 | ||
| 581 | #define FREM (4<<2) | 3 | ||
| 582 | |||
diff --git a/arch/parisc/math-emu/fmpyfadd.c b/arch/parisc/math-emu/fmpyfadd.c new file mode 100644 index 000000000000..5dd7f93a89be --- /dev/null +++ b/arch/parisc/math-emu/fmpyfadd.c | |||
| @@ -0,0 +1,2655 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/fmpyfadd.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Double Floating-point Multiply Fused Add | ||
| 29 | * Double Floating-point Multiply Negate Fused Add | ||
| 30 | * Single Floating-point Multiply Fused Add | ||
| 31 | * Single Floating-point Multiply Negate Fused Add | ||
| 32 | * | ||
| 33 | * External Interfaces: | ||
| 34 | * dbl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr) | ||
| 35 | * dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) | ||
| 36 | * sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr) | ||
| 37 | * sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) | ||
| 38 | * | ||
| 39 | * Internal Interfaces: | ||
| 40 | * | ||
| 41 | * Theory: | ||
| 42 | * <<please update with a overview of the operation of this file>> | ||
| 43 | * | ||
| 44 | * END_DESC | ||
| 45 | */ | ||
| 46 | |||
| 47 | |||
| 48 | #include "float.h" | ||
| 49 | #include "sgl_float.h" | ||
| 50 | #include "dbl_float.h" | ||
| 51 | |||
| 52 | |||
| 53 | /* | ||
| 54 | * Double Floating-point Multiply Fused Add | ||
| 55 | */ | ||
| 56 | |||
| 57 | int | ||
| 58 | dbl_fmpyfadd( | ||
| 59 | dbl_floating_point *src1ptr, | ||
| 60 | dbl_floating_point *src2ptr, | ||
| 61 | dbl_floating_point *src3ptr, | ||
| 62 | unsigned int *status, | ||
| 63 | dbl_floating_point *dstptr) | ||
| 64 | { | ||
| 65 | unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2; | ||
| 66 | register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4; | ||
| 67 | unsigned int rightp1, rightp2, rightp3, rightp4; | ||
| 68 | unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0; | ||
| 69 | register int mpy_exponent, add_exponent, count; | ||
| 70 | boolean inexact = FALSE, is_tiny = FALSE; | ||
| 71 | |||
| 72 | unsigned int signlessleft1, signlessright1, save; | ||
| 73 | register int result_exponent, diff_exponent; | ||
| 74 | int sign_save, jumpsize; | ||
| 75 | |||
| 76 | Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2); | ||
| 77 | Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2); | ||
| 78 | Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2); | ||
| 79 | |||
| 80 | /* | ||
| 81 | * set sign bit of result of multiply | ||
| 82 | */ | ||
| 83 | if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) | ||
| 84 | Dbl_setnegativezerop1(resultp1); | ||
| 85 | else Dbl_setzerop1(resultp1); | ||
| 86 | |||
| 87 | /* | ||
| 88 | * Generate multiply exponent | ||
| 89 | */ | ||
| 90 | mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS; | ||
| 91 | |||
| 92 | /* | ||
| 93 | * check first operand for NaN's or infinity | ||
| 94 | */ | ||
| 95 | if (Dbl_isinfinity_exponent(opnd1p1)) { | ||
| 96 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
| 97 | if (Dbl_isnotnan(opnd2p1,opnd2p2) && | ||
| 98 | Dbl_isnotnan(opnd3p1,opnd3p2)) { | ||
| 99 | if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { | ||
| 100 | /* | ||
| 101 | * invalid since operands are infinity | ||
| 102 | * and zero | ||
| 103 | */ | ||
| 104 | if (Is_invalidtrap_enabled()) | ||
| 105 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 106 | Set_invalidflag(); | ||
| 107 | Dbl_makequietnan(resultp1,resultp2); | ||
| 108 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 109 | return(NOEXCEPTION); | ||
| 110 | } | ||
| 111 | /* | ||
| 112 | * Check third operand for infinity with a | ||
| 113 | * sign opposite of the multiply result | ||
| 114 | */ | ||
| 115 | if (Dbl_isinfinity(opnd3p1,opnd3p2) && | ||
| 116 | (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { | ||
| 117 | /* | ||
| 118 | * invalid since attempting a magnitude | ||
| 119 | * subtraction of infinities | ||
| 120 | */ | ||
| 121 | if (Is_invalidtrap_enabled()) | ||
| 122 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 123 | Set_invalidflag(); | ||
| 124 | Dbl_makequietnan(resultp1,resultp2); | ||
| 125 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 126 | return(NOEXCEPTION); | ||
| 127 | } | ||
| 128 | |||
| 129 | /* | ||
| 130 | * return infinity | ||
| 131 | */ | ||
| 132 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
| 133 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 134 | return(NOEXCEPTION); | ||
| 135 | } | ||
| 136 | } | ||
| 137 | else { | ||
| 138 | /* | ||
| 139 | * is NaN; signaling or quiet? | ||
| 140 | */ | ||
| 141 | if (Dbl_isone_signaling(opnd1p1)) { | ||
| 142 | /* trap if INVALIDTRAP enabled */ | ||
| 143 | if (Is_invalidtrap_enabled()) | ||
| 144 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 145 | /* make NaN quiet */ | ||
| 146 | Set_invalidflag(); | ||
| 147 | Dbl_set_quiet(opnd1p1); | ||
| 148 | } | ||
| 149 | /* | ||
| 150 | * is second operand a signaling NaN? | ||
| 151 | */ | ||
| 152 | else if (Dbl_is_signalingnan(opnd2p1)) { | ||
| 153 | /* trap if INVALIDTRAP enabled */ | ||
| 154 | if (Is_invalidtrap_enabled()) | ||
| 155 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 156 | /* make NaN quiet */ | ||
| 157 | Set_invalidflag(); | ||
| 158 | Dbl_set_quiet(opnd2p1); | ||
| 159 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
| 160 | return(NOEXCEPTION); | ||
| 161 | } | ||
| 162 | /* | ||
| 163 | * is third operand a signaling NaN? | ||
| 164 | */ | ||
| 165 | else if (Dbl_is_signalingnan(opnd3p1)) { | ||
| 166 | /* trap if INVALIDTRAP enabled */ | ||
| 167 | if (Is_invalidtrap_enabled()) | ||
| 168 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 169 | /* make NaN quiet */ | ||
| 170 | Set_invalidflag(); | ||
| 171 | Dbl_set_quiet(opnd3p1); | ||
| 172 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 173 | return(NOEXCEPTION); | ||
| 174 | } | ||
| 175 | /* | ||
| 176 | * return quiet NaN | ||
| 177 | */ | ||
| 178 | Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); | ||
| 179 | return(NOEXCEPTION); | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | /* | ||
| 184 | * check second operand for NaN's or infinity | ||
| 185 | */ | ||
| 186 | if (Dbl_isinfinity_exponent(opnd2p1)) { | ||
| 187 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
| 188 | if (Dbl_isnotnan(opnd3p1,opnd3p2)) { | ||
| 189 | if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { | ||
| 190 | /* | ||
| 191 | * invalid since multiply operands are | ||
| 192 | * zero & infinity | ||
| 193 | */ | ||
| 194 | if (Is_invalidtrap_enabled()) | ||
| 195 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 196 | Set_invalidflag(); | ||
| 197 | Dbl_makequietnan(opnd2p1,opnd2p2); | ||
| 198 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
| 199 | return(NOEXCEPTION); | ||
| 200 | } | ||
| 201 | |||
| 202 | /* | ||
| 203 | * Check third operand for infinity with a | ||
| 204 | * sign opposite of the multiply result | ||
| 205 | */ | ||
| 206 | if (Dbl_isinfinity(opnd3p1,opnd3p2) && | ||
| 207 | (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { | ||
| 208 | /* | ||
| 209 | * invalid since attempting a magnitude | ||
| 210 | * subtraction of infinities | ||
| 211 | */ | ||
| 212 | if (Is_invalidtrap_enabled()) | ||
| 213 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 214 | Set_invalidflag(); | ||
| 215 | Dbl_makequietnan(resultp1,resultp2); | ||
| 216 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 217 | return(NOEXCEPTION); | ||
| 218 | } | ||
| 219 | |||
| 220 | /* | ||
| 221 | * return infinity | ||
| 222 | */ | ||
| 223 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
| 224 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 225 | return(NOEXCEPTION); | ||
| 226 | } | ||
| 227 | } | ||
| 228 | else { | ||
| 229 | /* | ||
| 230 | * is NaN; signaling or quiet? | ||
| 231 | */ | ||
| 232 | if (Dbl_isone_signaling(opnd2p1)) { | ||
| 233 | /* trap if INVALIDTRAP enabled */ | ||
| 234 | if (Is_invalidtrap_enabled()) | ||
| 235 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 236 | /* make NaN quiet */ | ||
| 237 | Set_invalidflag(); | ||
| 238 | Dbl_set_quiet(opnd2p1); | ||
| 239 | } | ||
| 240 | /* | ||
| 241 | * is third operand a signaling NaN? | ||
| 242 | */ | ||
| 243 | else if (Dbl_is_signalingnan(opnd3p1)) { | ||
| 244 | /* trap if INVALIDTRAP enabled */ | ||
| 245 | if (Is_invalidtrap_enabled()) | ||
| 246 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 247 | /* make NaN quiet */ | ||
| 248 | Set_invalidflag(); | ||
| 249 | Dbl_set_quiet(opnd3p1); | ||
| 250 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 251 | return(NOEXCEPTION); | ||
| 252 | } | ||
| 253 | /* | ||
| 254 | * return quiet NaN | ||
| 255 | */ | ||
| 256 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
| 257 | return(NOEXCEPTION); | ||
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 261 | /* | ||
| 262 | * check third operand for NaN's or infinity | ||
| 263 | */ | ||
| 264 | if (Dbl_isinfinity_exponent(opnd3p1)) { | ||
| 265 | if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { | ||
| 266 | /* return infinity */ | ||
| 267 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 268 | return(NOEXCEPTION); | ||
| 269 | } else { | ||
| 270 | /* | ||
| 271 | * is NaN; signaling or quiet? | ||
| 272 | */ | ||
| 273 | if (Dbl_isone_signaling(opnd3p1)) { | ||
| 274 | /* trap if INVALIDTRAP enabled */ | ||
| 275 | if (Is_invalidtrap_enabled()) | ||
| 276 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 277 | /* make NaN quiet */ | ||
| 278 | Set_invalidflag(); | ||
| 279 | Dbl_set_quiet(opnd3p1); | ||
| 280 | } | ||
| 281 | /* | ||
| 282 | * return quiet NaN | ||
| 283 | */ | ||
| 284 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 285 | return(NOEXCEPTION); | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | /* | ||
| 290 | * Generate multiply mantissa | ||
| 291 | */ | ||
| 292 | if (Dbl_isnotzero_exponent(opnd1p1)) { | ||
| 293 | /* set hidden bit */ | ||
| 294 | Dbl_clear_signexponent_set_hidden(opnd1p1); | ||
| 295 | } | ||
| 296 | else { | ||
| 297 | /* check for zero */ | ||
| 298 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
| 299 | /* | ||
| 300 | * Perform the add opnd3 with zero here. | ||
| 301 | */ | ||
| 302 | if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { | ||
| 303 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
| 304 | Dbl_or_signs(opnd3p1,resultp1); | ||
| 305 | } else { | ||
| 306 | Dbl_and_signs(opnd3p1,resultp1); | ||
| 307 | } | ||
| 308 | } | ||
| 309 | /* | ||
| 310 | * Now let's check for trapped underflow case. | ||
| 311 | */ | ||
| 312 | else if (Dbl_iszero_exponent(opnd3p1) && | ||
| 313 | Is_underflowtrap_enabled()) { | ||
| 314 | /* need to normalize results mantissa */ | ||
| 315 | sign_save = Dbl_signextendedsign(opnd3p1); | ||
| 316 | result_exponent = 0; | ||
| 317 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
| 318 | Dbl_normalize(opnd3p1,opnd3p2,result_exponent); | ||
| 319 | Dbl_set_sign(opnd3p1,/*using*/sign_save); | ||
| 320 | Dbl_setwrapped_exponent(opnd3p1,result_exponent, | ||
| 321 | unfl); | ||
| 322 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 323 | /* inexact = FALSE */ | ||
| 324 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
| 325 | } | ||
| 326 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 327 | return(NOEXCEPTION); | ||
| 328 | } | ||
| 329 | /* is denormalized, adjust exponent */ | ||
| 330 | Dbl_clear_signexponent(opnd1p1); | ||
| 331 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
| 332 | Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent); | ||
| 333 | } | ||
| 334 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
| 335 | if (Dbl_isnotzero_exponent(opnd2p1)) { | ||
| 336 | Dbl_clear_signexponent_set_hidden(opnd2p1); | ||
| 337 | } | ||
| 338 | else { | ||
| 339 | /* check for zero */ | ||
| 340 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
| 341 | /* | ||
| 342 | * Perform the add opnd3 with zero here. | ||
| 343 | */ | ||
| 344 | if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { | ||
| 345 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
| 346 | Dbl_or_signs(opnd3p1,resultp1); | ||
| 347 | } else { | ||
| 348 | Dbl_and_signs(opnd3p1,resultp1); | ||
| 349 | } | ||
| 350 | } | ||
| 351 | /* | ||
| 352 | * Now let's check for trapped underflow case. | ||
| 353 | */ | ||
| 354 | else if (Dbl_iszero_exponent(opnd3p1) && | ||
| 355 | Is_underflowtrap_enabled()) { | ||
| 356 | /* need to normalize results mantissa */ | ||
| 357 | sign_save = Dbl_signextendedsign(opnd3p1); | ||
| 358 | result_exponent = 0; | ||
| 359 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
| 360 | Dbl_normalize(opnd3p1,opnd3p2,result_exponent); | ||
| 361 | Dbl_set_sign(opnd3p1,/*using*/sign_save); | ||
| 362 | Dbl_setwrapped_exponent(opnd3p1,result_exponent, | ||
| 363 | unfl); | ||
| 364 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 365 | /* inexact = FALSE */ | ||
| 366 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
| 367 | } | ||
| 368 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 369 | return(NOEXCEPTION); | ||
| 370 | } | ||
| 371 | /* is denormalized; want to normalize */ | ||
| 372 | Dbl_clear_signexponent(opnd2p1); | ||
| 373 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
| 374 | Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent); | ||
| 375 | } | ||
| 376 | |||
| 377 | /* Multiply the first two source mantissas together */ | ||
| 378 | |||
| 379 | /* | ||
| 380 | * The intermediate result will be kept in tmpres, | ||
| 381 | * which needs enough room for 106 bits of mantissa, | ||
| 382 | * so lets call it a Double extended. | ||
| 383 | */ | ||
| 384 | Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4); | ||
| 385 | |||
| 386 | /* | ||
| 387 | * Four bits at a time are inspected in each loop, and a | ||
| 388 | * simple shift and add multiply algorithm is used. | ||
| 389 | */ | ||
| 390 | for (count = DBL_P-1; count >= 0; count -= 4) { | ||
| 391 | Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4); | ||
| 392 | if (Dbit28p2(opnd1p2)) { | ||
| 393 | /* Fourword_add should be an ADD followed by 3 ADDC's */ | ||
| 394 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
| 395 | opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0); | ||
| 396 | } | ||
| 397 | if (Dbit29p2(opnd1p2)) { | ||
| 398 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
| 399 | opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0); | ||
| 400 | } | ||
| 401 | if (Dbit30p2(opnd1p2)) { | ||
| 402 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
| 403 | opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0); | ||
| 404 | } | ||
| 405 | if (Dbit31p2(opnd1p2)) { | ||
| 406 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
| 407 | opnd2p1, opnd2p2, 0, 0); | ||
| 408 | } | ||
| 409 | Dbl_rightshiftby4(opnd1p1,opnd1p2); | ||
| 410 | } | ||
| 411 | if (Is_dexthiddenoverflow(tmpresp1)) { | ||
| 412 | /* result mantissa >= 2 (mantissa overflow) */ | ||
| 413 | mpy_exponent++; | ||
| 414 | Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4); | ||
| 415 | } | ||
| 416 | |||
| 417 | /* | ||
| 418 | * Restore the sign of the mpy result which was saved in resultp1. | ||
| 419 | * The exponent will continue to be kept in mpy_exponent. | ||
| 420 | */ | ||
| 421 | Dblext_set_sign(tmpresp1,Dbl_sign(resultp1)); | ||
| 422 | |||
| 423 | /* | ||
| 424 | * No rounding is required, since the result of the multiply | ||
| 425 | * is exact in the extended format. | ||
| 426 | */ | ||
| 427 | |||
| 428 | /* | ||
| 429 | * Now we are ready to perform the add portion of the operation. | ||
| 430 | * | ||
| 431 | * The exponents need to be kept as integers for now, since the | ||
| 432 | * multiply result might not fit into the exponent field. We | ||
| 433 | * can't overflow or underflow because of this yet, since the | ||
| 434 | * add could bring the final result back into range. | ||
| 435 | */ | ||
| 436 | add_exponent = Dbl_exponent(opnd3p1); | ||
| 437 | |||
| 438 | /* | ||
| 439 | * Check for denormalized or zero add operand. | ||
| 440 | */ | ||
| 441 | if (add_exponent == 0) { | ||
| 442 | /* check for zero */ | ||
| 443 | if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { | ||
| 444 | /* right is zero */ | ||
| 445 | /* Left can't be zero and must be result. | ||
| 446 | * | ||
| 447 | * The final result is now in tmpres and mpy_exponent, | ||
| 448 | * and needs to be rounded and squeezed back into | ||
| 449 | * double precision format from double extended. | ||
| 450 | */ | ||
| 451 | result_exponent = mpy_exponent; | ||
| 452 | Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4, | ||
| 453 | resultp1,resultp2,resultp3,resultp4); | ||
| 454 | sign_save = Dbl_signextendedsign(resultp1);/*save sign*/ | ||
| 455 | goto round; | ||
| 456 | } | ||
| 457 | |||
| 458 | /* | ||
| 459 | * Neither are zeroes. | ||
| 460 | * Adjust exponent and normalize add operand. | ||
| 461 | */ | ||
| 462 | sign_save = Dbl_signextendedsign(opnd3p1); /* save sign */ | ||
| 463 | Dbl_clear_signexponent(opnd3p1); | ||
| 464 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
| 465 | Dbl_normalize(opnd3p1,opnd3p2,add_exponent); | ||
| 466 | Dbl_set_sign(opnd3p1,sign_save); /* restore sign */ | ||
| 467 | } else { | ||
| 468 | Dbl_clear_exponent_set_hidden(opnd3p1); | ||
| 469 | } | ||
| 470 | /* | ||
| 471 | * Copy opnd3 to the double extended variable called right. | ||
| 472 | */ | ||
| 473 | Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4); | ||
| 474 | |||
| 475 | /* | ||
| 476 | * A zero "save" helps discover equal operands (for later), | ||
| 477 | * and is used in swapping operands (if needed). | ||
| 478 | */ | ||
| 479 | Dblext_xortointp1(tmpresp1,rightp1,/*to*/save); | ||
| 480 | |||
| 481 | /* | ||
| 482 | * Compare magnitude of operands. | ||
| 483 | */ | ||
| 484 | Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1); | ||
| 485 | Dblext_copytoint_exponentmantissap1(rightp1,signlessright1); | ||
| 486 | if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && | ||
| 487 | Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){ | ||
| 488 | /* | ||
| 489 | * Set the left operand to the larger one by XOR swap. | ||
| 490 | * First finish the first word "save". | ||
| 491 | */ | ||
| 492 | Dblext_xorfromintp1(save,rightp1,/*to*/rightp1); | ||
| 493 | Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); | ||
| 494 | Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4, | ||
| 495 | rightp2,rightp3,rightp4); | ||
| 496 | /* also setup exponents used in rest of routine */ | ||
| 497 | diff_exponent = add_exponent - mpy_exponent; | ||
| 498 | result_exponent = add_exponent; | ||
| 499 | } else { | ||
| 500 | /* also setup exponents used in rest of routine */ | ||
| 501 | diff_exponent = mpy_exponent - add_exponent; | ||
| 502 | result_exponent = mpy_exponent; | ||
| 503 | } | ||
| 504 | /* Invariant: left is not smaller than right. */ | ||
| 505 | |||
| 506 | /* | ||
| 507 | * Special case alignment of operands that would force alignment | ||
| 508 | * beyond the extent of the extension. A further optimization | ||
| 509 | * could special case this but only reduces the path length for | ||
| 510 | * this infrequent case. | ||
| 511 | */ | ||
| 512 | if (diff_exponent > DBLEXT_THRESHOLD) { | ||
| 513 | diff_exponent = DBLEXT_THRESHOLD; | ||
| 514 | } | ||
| 515 | |||
| 516 | /* Align right operand by shifting it to the right */ | ||
| 517 | Dblext_clear_sign(rightp1); | ||
| 518 | Dblext_right_align(rightp1,rightp2,rightp3,rightp4, | ||
| 519 | /*shifted by*/diff_exponent); | ||
| 520 | |||
| 521 | /* Treat sum and difference of the operands separately. */ | ||
| 522 | if ((int)save < 0) { | ||
| 523 | /* | ||
| 524 | * Difference of the two operands. Overflow can occur if the | ||
| 525 | * multiply overflowed. A borrow can occur out of the hidden | ||
| 526 | * bit and force a post normalization phase. | ||
| 527 | */ | ||
| 528 | Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4, | ||
| 529 | rightp1,rightp2,rightp3,rightp4, | ||
| 530 | resultp1,resultp2,resultp3,resultp4); | ||
| 531 | sign_save = Dbl_signextendedsign(resultp1); | ||
| 532 | if (Dbl_iszero_hidden(resultp1)) { | ||
| 533 | /* Handle normalization */ | ||
| 534 | /* A straight foward algorithm would now shift the | ||
| 535 | * result and extension left until the hidden bit | ||
| 536 | * becomes one. Not all of the extension bits need | ||
| 537 | * participate in the shift. Only the two most | ||
| 538 | * significant bits (round and guard) are needed. | ||
| 539 | * If only a single shift is needed then the guard | ||
| 540 | * bit becomes a significant low order bit and the | ||
| 541 | * extension must participate in the rounding. | ||
| 542 | * If more than a single shift is needed, then all | ||
| 543 | * bits to the right of the guard bit are zeros, | ||
| 544 | * and the guard bit may or may not be zero. */ | ||
| 545 | Dblext_leftshiftby1(resultp1,resultp2,resultp3, | ||
| 546 | resultp4); | ||
| 547 | |||
| 548 | /* Need to check for a zero result. The sign and | ||
| 549 | * exponent fields have already been zeroed. The more | ||
| 550 | * efficient test of the full object can be used. | ||
| 551 | */ | ||
| 552 | if(Dblext_iszero(resultp1,resultp2,resultp3,resultp4)){ | ||
| 553 | /* Must have been "x-x" or "x+(-x)". */ | ||
| 554 | if (Is_rounding_mode(ROUNDMINUS)) | ||
| 555 | Dbl_setone_sign(resultp1); | ||
| 556 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 557 | return(NOEXCEPTION); | ||
| 558 | } | ||
| 559 | result_exponent--; | ||
| 560 | |||
| 561 | /* Look to see if normalization is finished. */ | ||
| 562 | if (Dbl_isone_hidden(resultp1)) { | ||
| 563 | /* No further normalization is needed */ | ||
| 564 | goto round; | ||
| 565 | } | ||
| 566 | |||
| 567 | /* Discover first one bit to determine shift amount. | ||
| 568 | * Use a modified binary search. We have already | ||
| 569 | * shifted the result one position right and still | ||
| 570 | * not found a one so the remainder of the extension | ||
| 571 | * must be zero and simplifies rounding. */ | ||
| 572 | /* Scan bytes */ | ||
| 573 | while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) { | ||
| 574 | Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4); | ||
| 575 | result_exponent -= 8; | ||
| 576 | } | ||
| 577 | /* Now narrow it down to the nibble */ | ||
| 578 | if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) { | ||
| 579 | /* The lower nibble contains the | ||
| 580 | * normalizing one */ | ||
| 581 | Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4); | ||
| 582 | result_exponent -= 4; | ||
| 583 | } | ||
| 584 | /* Select case where first bit is set (already | ||
| 585 | * normalized) otherwise select the proper shift. */ | ||
| 586 | jumpsize = Dbl_hiddenhigh3mantissa(resultp1); | ||
| 587 | if (jumpsize <= 7) switch(jumpsize) { | ||
| 588 | case 1: | ||
| 589 | Dblext_leftshiftby3(resultp1,resultp2,resultp3, | ||
| 590 | resultp4); | ||
| 591 | result_exponent -= 3; | ||
| 592 | break; | ||
| 593 | case 2: | ||
| 594 | case 3: | ||
| 595 | Dblext_leftshiftby2(resultp1,resultp2,resultp3, | ||
| 596 | resultp4); | ||
| 597 | result_exponent -= 2; | ||
| 598 | break; | ||
| 599 | case 4: | ||
| 600 | case 5: | ||
| 601 | case 6: | ||
| 602 | case 7: | ||
| 603 | Dblext_leftshiftby1(resultp1,resultp2,resultp3, | ||
| 604 | resultp4); | ||
| 605 | result_exponent -= 1; | ||
| 606 | break; | ||
| 607 | } | ||
| 608 | } /* end if (hidden...)... */ | ||
| 609 | /* Fall through and round */ | ||
| 610 | } /* end if (save < 0)... */ | ||
| 611 | else { | ||
| 612 | /* Add magnitudes */ | ||
| 613 | Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4, | ||
| 614 | rightp1,rightp2,rightp3,rightp4, | ||
| 615 | /*to*/resultp1,resultp2,resultp3,resultp4); | ||
| 616 | sign_save = Dbl_signextendedsign(resultp1); | ||
| 617 | if (Dbl_isone_hiddenoverflow(resultp1)) { | ||
| 618 | /* Prenormalization required. */ | ||
| 619 | Dblext_arithrightshiftby1(resultp1,resultp2,resultp3, | ||
| 620 | resultp4); | ||
| 621 | result_exponent++; | ||
| 622 | } /* end if hiddenoverflow... */ | ||
| 623 | } /* end else ...add magnitudes... */ | ||
| 624 | |||
| 625 | /* Round the result. If the extension and lower two words are | ||
| 626 | * all zeros, then the result is exact. Otherwise round in the | ||
| 627 | * correct direction. Underflow is possible. If a postnormalization | ||
| 628 | * is necessary, then the mantissa is all zeros so no shift is needed. | ||
| 629 | */ | ||
| 630 | round: | ||
| 631 | if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { | ||
| 632 | Dblext_denormalize(resultp1,resultp2,resultp3,resultp4, | ||
| 633 | result_exponent,is_tiny); | ||
| 634 | } | ||
| 635 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
| 636 | if (Dblext_isnotzero_mantissap3(resultp3) || | ||
| 637 | Dblext_isnotzero_mantissap4(resultp4)) { | ||
| 638 | inexact = TRUE; | ||
| 639 | switch(Rounding_mode()) { | ||
| 640 | case ROUNDNEAREST: /* The default. */ | ||
| 641 | if (Dblext_isone_highp3(resultp3)) { | ||
| 642 | /* at least 1/2 ulp */ | ||
| 643 | if (Dblext_isnotzero_low31p3(resultp3) || | ||
| 644 | Dblext_isnotzero_mantissap4(resultp4) || | ||
| 645 | Dblext_isone_lowp2(resultp2)) { | ||
| 646 | /* either exactly half way and odd or | ||
| 647 | * more than 1/2ulp */ | ||
| 648 | Dbl_increment(resultp1,resultp2); | ||
| 649 | } | ||
| 650 | } | ||
| 651 | break; | ||
| 652 | |||
| 653 | case ROUNDPLUS: | ||
| 654 | if (Dbl_iszero_sign(resultp1)) { | ||
| 655 | /* Round up positive results */ | ||
| 656 | Dbl_increment(resultp1,resultp2); | ||
| 657 | } | ||
| 658 | break; | ||
| 659 | |||
| 660 | case ROUNDMINUS: | ||
| 661 | if (Dbl_isone_sign(resultp1)) { | ||
| 662 | /* Round down negative results */ | ||
| 663 | Dbl_increment(resultp1,resultp2); | ||
| 664 | } | ||
| 665 | |||
| 666 | case ROUNDZERO:; | ||
| 667 | /* truncate is simple */ | ||
| 668 | } /* end switch... */ | ||
| 669 | if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++; | ||
| 670 | } | ||
| 671 | if (result_exponent >= DBL_INFINITY_EXPONENT) { | ||
| 672 | /* trap if OVERFLOWTRAP enabled */ | ||
| 673 | if (Is_overflowtrap_enabled()) { | ||
| 674 | /* | ||
| 675 | * Adjust bias of result | ||
| 676 | */ | ||
| 677 | Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl); | ||
| 678 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 679 | if (inexact) | ||
| 680 | if (Is_inexacttrap_enabled()) | ||
| 681 | return (OPC_2E_OVERFLOWEXCEPTION | | ||
| 682 | OPC_2E_INEXACTEXCEPTION); | ||
| 683 | else Set_inexactflag(); | ||
| 684 | return (OPC_2E_OVERFLOWEXCEPTION); | ||
| 685 | } | ||
| 686 | inexact = TRUE; | ||
| 687 | Set_overflowflag(); | ||
| 688 | /* set result to infinity or largest number */ | ||
| 689 | Dbl_setoverflow(resultp1,resultp2); | ||
| 690 | |||
| 691 | } else if (result_exponent <= 0) { /* underflow case */ | ||
| 692 | if (Is_underflowtrap_enabled()) { | ||
| 693 | /* | ||
| 694 | * Adjust bias of result | ||
| 695 | */ | ||
| 696 | Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
| 697 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 698 | if (inexact) | ||
| 699 | if (Is_inexacttrap_enabled()) | ||
| 700 | return (OPC_2E_UNDERFLOWEXCEPTION | | ||
| 701 | OPC_2E_INEXACTEXCEPTION); | ||
| 702 | else Set_inexactflag(); | ||
| 703 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
| 704 | } | ||
| 705 | else if (inexact && is_tiny) Set_underflowflag(); | ||
| 706 | } | ||
| 707 | else Dbl_set_exponent(resultp1,result_exponent); | ||
| 708 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 709 | if (inexact) | ||
| 710 | if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); | ||
| 711 | else Set_inexactflag(); | ||
| 712 | return(NOEXCEPTION); | ||
| 713 | } | ||
| 714 | |||
| 715 | /* | ||
| 716 | * Double Floating-point Multiply Negate Fused Add | ||
| 717 | */ | ||
| 718 | |||
| 719 | dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) | ||
| 720 | |||
| 721 | dbl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr; | ||
| 722 | unsigned int *status; | ||
| 723 | { | ||
| 724 | unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2; | ||
| 725 | register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4; | ||
| 726 | unsigned int rightp1, rightp2, rightp3, rightp4; | ||
| 727 | unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0; | ||
| 728 | register int mpy_exponent, add_exponent, count; | ||
| 729 | boolean inexact = FALSE, is_tiny = FALSE; | ||
| 730 | |||
| 731 | unsigned int signlessleft1, signlessright1, save; | ||
| 732 | register int result_exponent, diff_exponent; | ||
| 733 | int sign_save, jumpsize; | ||
| 734 | |||
| 735 | Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2); | ||
| 736 | Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2); | ||
| 737 | Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2); | ||
| 738 | |||
| 739 | /* | ||
| 740 | * set sign bit of result of multiply | ||
| 741 | */ | ||
| 742 | if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) | ||
| 743 | Dbl_setzerop1(resultp1); | ||
| 744 | else | ||
| 745 | Dbl_setnegativezerop1(resultp1); | ||
| 746 | |||
| 747 | /* | ||
| 748 | * Generate multiply exponent | ||
| 749 | */ | ||
| 750 | mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS; | ||
| 751 | |||
| 752 | /* | ||
| 753 | * check first operand for NaN's or infinity | ||
| 754 | */ | ||
| 755 | if (Dbl_isinfinity_exponent(opnd1p1)) { | ||
| 756 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
| 757 | if (Dbl_isnotnan(opnd2p1,opnd2p2) && | ||
| 758 | Dbl_isnotnan(opnd3p1,opnd3p2)) { | ||
| 759 | if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { | ||
| 760 | /* | ||
| 761 | * invalid since operands are infinity | ||
| 762 | * and zero | ||
| 763 | */ | ||
| 764 | if (Is_invalidtrap_enabled()) | ||
| 765 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 766 | Set_invalidflag(); | ||
| 767 | Dbl_makequietnan(resultp1,resultp2); | ||
| 768 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 769 | return(NOEXCEPTION); | ||
| 770 | } | ||
| 771 | /* | ||
| 772 | * Check third operand for infinity with a | ||
| 773 | * sign opposite of the multiply result | ||
| 774 | */ | ||
| 775 | if (Dbl_isinfinity(opnd3p1,opnd3p2) && | ||
| 776 | (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { | ||
| 777 | /* | ||
| 778 | * invalid since attempting a magnitude | ||
| 779 | * subtraction of infinities | ||
| 780 | */ | ||
| 781 | if (Is_invalidtrap_enabled()) | ||
| 782 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 783 | Set_invalidflag(); | ||
| 784 | Dbl_makequietnan(resultp1,resultp2); | ||
| 785 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 786 | return(NOEXCEPTION); | ||
| 787 | } | ||
| 788 | |||
| 789 | /* | ||
| 790 | * return infinity | ||
| 791 | */ | ||
| 792 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
| 793 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 794 | return(NOEXCEPTION); | ||
| 795 | } | ||
| 796 | } | ||
| 797 | else { | ||
| 798 | /* | ||
| 799 | * is NaN; signaling or quiet? | ||
| 800 | */ | ||
| 801 | if (Dbl_isone_signaling(opnd1p1)) { | ||
| 802 | /* trap if INVALIDTRAP enabled */ | ||
| 803 | if (Is_invalidtrap_enabled()) | ||
| 804 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 805 | /* make NaN quiet */ | ||
| 806 | Set_invalidflag(); | ||
| 807 | Dbl_set_quiet(opnd1p1); | ||
| 808 | } | ||
| 809 | /* | ||
| 810 | * is second operand a signaling NaN? | ||
| 811 | */ | ||
| 812 | else if (Dbl_is_signalingnan(opnd2p1)) { | ||
| 813 | /* trap if INVALIDTRAP enabled */ | ||
| 814 | if (Is_invalidtrap_enabled()) | ||
| 815 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 816 | /* make NaN quiet */ | ||
| 817 | Set_invalidflag(); | ||
| 818 | Dbl_set_quiet(opnd2p1); | ||
| 819 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
| 820 | return(NOEXCEPTION); | ||
| 821 | } | ||
| 822 | /* | ||
| 823 | * is third operand a signaling NaN? | ||
| 824 | */ | ||
| 825 | else if (Dbl_is_signalingnan(opnd3p1)) { | ||
| 826 | /* trap if INVALIDTRAP enabled */ | ||
| 827 | if (Is_invalidtrap_enabled()) | ||
| 828 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 829 | /* make NaN quiet */ | ||
| 830 | Set_invalidflag(); | ||
| 831 | Dbl_set_quiet(opnd3p1); | ||
| 832 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 833 | return(NOEXCEPTION); | ||
| 834 | } | ||
| 835 | /* | ||
| 836 | * return quiet NaN | ||
| 837 | */ | ||
| 838 | Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); | ||
| 839 | return(NOEXCEPTION); | ||
| 840 | } | ||
| 841 | } | ||
| 842 | |||
| 843 | /* | ||
| 844 | * check second operand for NaN's or infinity | ||
| 845 | */ | ||
| 846 | if (Dbl_isinfinity_exponent(opnd2p1)) { | ||
| 847 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
| 848 | if (Dbl_isnotnan(opnd3p1,opnd3p2)) { | ||
| 849 | if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { | ||
| 850 | /* | ||
| 851 | * invalid since multiply operands are | ||
| 852 | * zero & infinity | ||
| 853 | */ | ||
| 854 | if (Is_invalidtrap_enabled()) | ||
| 855 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 856 | Set_invalidflag(); | ||
| 857 | Dbl_makequietnan(opnd2p1,opnd2p2); | ||
| 858 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
| 859 | return(NOEXCEPTION); | ||
| 860 | } | ||
| 861 | |||
| 862 | /* | ||
| 863 | * Check third operand for infinity with a | ||
| 864 | * sign opposite of the multiply result | ||
| 865 | */ | ||
| 866 | if (Dbl_isinfinity(opnd3p1,opnd3p2) && | ||
| 867 | (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) { | ||
| 868 | /* | ||
| 869 | * invalid since attempting a magnitude | ||
| 870 | * subtraction of infinities | ||
| 871 | */ | ||
| 872 | if (Is_invalidtrap_enabled()) | ||
| 873 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 874 | Set_invalidflag(); | ||
| 875 | Dbl_makequietnan(resultp1,resultp2); | ||
| 876 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 877 | return(NOEXCEPTION); | ||
| 878 | } | ||
| 879 | |||
| 880 | /* | ||
| 881 | * return infinity | ||
| 882 | */ | ||
| 883 | Dbl_setinfinity_exponentmantissa(resultp1,resultp2); | ||
| 884 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 885 | return(NOEXCEPTION); | ||
| 886 | } | ||
| 887 | } | ||
| 888 | else { | ||
| 889 | /* | ||
| 890 | * is NaN; signaling or quiet? | ||
| 891 | */ | ||
| 892 | if (Dbl_isone_signaling(opnd2p1)) { | ||
| 893 | /* trap if INVALIDTRAP enabled */ | ||
| 894 | if (Is_invalidtrap_enabled()) | ||
| 895 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 896 | /* make NaN quiet */ | ||
| 897 | Set_invalidflag(); | ||
| 898 | Dbl_set_quiet(opnd2p1); | ||
| 899 | } | ||
| 900 | /* | ||
| 901 | * is third operand a signaling NaN? | ||
| 902 | */ | ||
| 903 | else if (Dbl_is_signalingnan(opnd3p1)) { | ||
| 904 | /* trap if INVALIDTRAP enabled */ | ||
| 905 | if (Is_invalidtrap_enabled()) | ||
| 906 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 907 | /* make NaN quiet */ | ||
| 908 | Set_invalidflag(); | ||
| 909 | Dbl_set_quiet(opnd3p1); | ||
| 910 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 911 | return(NOEXCEPTION); | ||
| 912 | } | ||
| 913 | /* | ||
| 914 | * return quiet NaN | ||
| 915 | */ | ||
| 916 | Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); | ||
| 917 | return(NOEXCEPTION); | ||
| 918 | } | ||
| 919 | } | ||
| 920 | |||
| 921 | /* | ||
| 922 | * check third operand for NaN's or infinity | ||
| 923 | */ | ||
| 924 | if (Dbl_isinfinity_exponent(opnd3p1)) { | ||
| 925 | if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { | ||
| 926 | /* return infinity */ | ||
| 927 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 928 | return(NOEXCEPTION); | ||
| 929 | } else { | ||
| 930 | /* | ||
| 931 | * is NaN; signaling or quiet? | ||
| 932 | */ | ||
| 933 | if (Dbl_isone_signaling(opnd3p1)) { | ||
| 934 | /* trap if INVALIDTRAP enabled */ | ||
| 935 | if (Is_invalidtrap_enabled()) | ||
| 936 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 937 | /* make NaN quiet */ | ||
| 938 | Set_invalidflag(); | ||
| 939 | Dbl_set_quiet(opnd3p1); | ||
| 940 | } | ||
| 941 | /* | ||
| 942 | * return quiet NaN | ||
| 943 | */ | ||
| 944 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 945 | return(NOEXCEPTION); | ||
| 946 | } | ||
| 947 | } | ||
| 948 | |||
| 949 | /* | ||
| 950 | * Generate multiply mantissa | ||
| 951 | */ | ||
| 952 | if (Dbl_isnotzero_exponent(opnd1p1)) { | ||
| 953 | /* set hidden bit */ | ||
| 954 | Dbl_clear_signexponent_set_hidden(opnd1p1); | ||
| 955 | } | ||
| 956 | else { | ||
| 957 | /* check for zero */ | ||
| 958 | if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { | ||
| 959 | /* | ||
| 960 | * Perform the add opnd3 with zero here. | ||
| 961 | */ | ||
| 962 | if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { | ||
| 963 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
| 964 | Dbl_or_signs(opnd3p1,resultp1); | ||
| 965 | } else { | ||
| 966 | Dbl_and_signs(opnd3p1,resultp1); | ||
| 967 | } | ||
| 968 | } | ||
| 969 | /* | ||
| 970 | * Now let's check for trapped underflow case. | ||
| 971 | */ | ||
| 972 | else if (Dbl_iszero_exponent(opnd3p1) && | ||
| 973 | Is_underflowtrap_enabled()) { | ||
| 974 | /* need to normalize results mantissa */ | ||
| 975 | sign_save = Dbl_signextendedsign(opnd3p1); | ||
| 976 | result_exponent = 0; | ||
| 977 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
| 978 | Dbl_normalize(opnd3p1,opnd3p2,result_exponent); | ||
| 979 | Dbl_set_sign(opnd3p1,/*using*/sign_save); | ||
| 980 | Dbl_setwrapped_exponent(opnd3p1,result_exponent, | ||
| 981 | unfl); | ||
| 982 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 983 | /* inexact = FALSE */ | ||
| 984 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
| 985 | } | ||
| 986 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 987 | return(NOEXCEPTION); | ||
| 988 | } | ||
| 989 | /* is denormalized, adjust exponent */ | ||
| 990 | Dbl_clear_signexponent(opnd1p1); | ||
| 991 | Dbl_leftshiftby1(opnd1p1,opnd1p2); | ||
| 992 | Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent); | ||
| 993 | } | ||
| 994 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
| 995 | if (Dbl_isnotzero_exponent(opnd2p1)) { | ||
| 996 | Dbl_clear_signexponent_set_hidden(opnd2p1); | ||
| 997 | } | ||
| 998 | else { | ||
| 999 | /* check for zero */ | ||
| 1000 | if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { | ||
| 1001 | /* | ||
| 1002 | * Perform the add opnd3 with zero here. | ||
| 1003 | */ | ||
| 1004 | if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) { | ||
| 1005 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
| 1006 | Dbl_or_signs(opnd3p1,resultp1); | ||
| 1007 | } else { | ||
| 1008 | Dbl_and_signs(opnd3p1,resultp1); | ||
| 1009 | } | ||
| 1010 | } | ||
| 1011 | /* | ||
| 1012 | * Now let's check for trapped underflow case. | ||
| 1013 | */ | ||
| 1014 | else if (Dbl_iszero_exponent(opnd3p1) && | ||
| 1015 | Is_underflowtrap_enabled()) { | ||
| 1016 | /* need to normalize results mantissa */ | ||
| 1017 | sign_save = Dbl_signextendedsign(opnd3p1); | ||
| 1018 | result_exponent = 0; | ||
| 1019 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
| 1020 | Dbl_normalize(opnd3p1,opnd3p2,result_exponent); | ||
| 1021 | Dbl_set_sign(opnd3p1,/*using*/sign_save); | ||
| 1022 | Dbl_setwrapped_exponent(opnd3p1,result_exponent, | ||
| 1023 | unfl); | ||
| 1024 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 1025 | /* inexact = FALSE */ | ||
| 1026 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
| 1027 | } | ||
| 1028 | Dbl_copytoptr(opnd3p1,opnd3p2,dstptr); | ||
| 1029 | return(NOEXCEPTION); | ||
| 1030 | } | ||
| 1031 | /* is denormalized; want to normalize */ | ||
| 1032 | Dbl_clear_signexponent(opnd2p1); | ||
| 1033 | Dbl_leftshiftby1(opnd2p1,opnd2p2); | ||
| 1034 | Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent); | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | /* Multiply the first two source mantissas together */ | ||
| 1038 | |||
| 1039 | /* | ||
| 1040 | * The intermediate result will be kept in tmpres, | ||
| 1041 | * which needs enough room for 106 bits of mantissa, | ||
| 1042 | * so lets call it a Double extended. | ||
| 1043 | */ | ||
| 1044 | Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4); | ||
| 1045 | |||
| 1046 | /* | ||
| 1047 | * Four bits at a time are inspected in each loop, and a | ||
| 1048 | * simple shift and add multiply algorithm is used. | ||
| 1049 | */ | ||
| 1050 | for (count = DBL_P-1; count >= 0; count -= 4) { | ||
| 1051 | Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4); | ||
| 1052 | if (Dbit28p2(opnd1p2)) { | ||
| 1053 | /* Fourword_add should be an ADD followed by 3 ADDC's */ | ||
| 1054 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
| 1055 | opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0); | ||
| 1056 | } | ||
| 1057 | if (Dbit29p2(opnd1p2)) { | ||
| 1058 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
| 1059 | opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0); | ||
| 1060 | } | ||
| 1061 | if (Dbit30p2(opnd1p2)) { | ||
| 1062 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
| 1063 | opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0); | ||
| 1064 | } | ||
| 1065 | if (Dbit31p2(opnd1p2)) { | ||
| 1066 | Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, | ||
| 1067 | opnd2p1, opnd2p2, 0, 0); | ||
| 1068 | } | ||
| 1069 | Dbl_rightshiftby4(opnd1p1,opnd1p2); | ||
| 1070 | } | ||
| 1071 | if (Is_dexthiddenoverflow(tmpresp1)) { | ||
| 1072 | /* result mantissa >= 2 (mantissa overflow) */ | ||
| 1073 | mpy_exponent++; | ||
| 1074 | Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4); | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | /* | ||
| 1078 | * Restore the sign of the mpy result which was saved in resultp1. | ||
| 1079 | * The exponent will continue to be kept in mpy_exponent. | ||
| 1080 | */ | ||
| 1081 | Dblext_set_sign(tmpresp1,Dbl_sign(resultp1)); | ||
| 1082 | |||
| 1083 | /* | ||
| 1084 | * No rounding is required, since the result of the multiply | ||
| 1085 | * is exact in the extended format. | ||
| 1086 | */ | ||
| 1087 | |||
| 1088 | /* | ||
| 1089 | * Now we are ready to perform the add portion of the operation. | ||
| 1090 | * | ||
| 1091 | * The exponents need to be kept as integers for now, since the | ||
| 1092 | * multiply result might not fit into the exponent field. We | ||
| 1093 | * can't overflow or underflow because of this yet, since the | ||
| 1094 | * add could bring the final result back into range. | ||
| 1095 | */ | ||
| 1096 | add_exponent = Dbl_exponent(opnd3p1); | ||
| 1097 | |||
| 1098 | /* | ||
| 1099 | * Check for denormalized or zero add operand. | ||
| 1100 | */ | ||
| 1101 | if (add_exponent == 0) { | ||
| 1102 | /* check for zero */ | ||
| 1103 | if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) { | ||
| 1104 | /* right is zero */ | ||
| 1105 | /* Left can't be zero and must be result. | ||
| 1106 | * | ||
| 1107 | * The final result is now in tmpres and mpy_exponent, | ||
| 1108 | * and needs to be rounded and squeezed back into | ||
| 1109 | * double precision format from double extended. | ||
| 1110 | */ | ||
| 1111 | result_exponent = mpy_exponent; | ||
| 1112 | Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4, | ||
| 1113 | resultp1,resultp2,resultp3,resultp4); | ||
| 1114 | sign_save = Dbl_signextendedsign(resultp1);/*save sign*/ | ||
| 1115 | goto round; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | /* | ||
| 1119 | * Neither are zeroes. | ||
| 1120 | * Adjust exponent and normalize add operand. | ||
| 1121 | */ | ||
| 1122 | sign_save = Dbl_signextendedsign(opnd3p1); /* save sign */ | ||
| 1123 | Dbl_clear_signexponent(opnd3p1); | ||
| 1124 | Dbl_leftshiftby1(opnd3p1,opnd3p2); | ||
| 1125 | Dbl_normalize(opnd3p1,opnd3p2,add_exponent); | ||
| 1126 | Dbl_set_sign(opnd3p1,sign_save); /* restore sign */ | ||
| 1127 | } else { | ||
| 1128 | Dbl_clear_exponent_set_hidden(opnd3p1); | ||
| 1129 | } | ||
| 1130 | /* | ||
| 1131 | * Copy opnd3 to the double extended variable called right. | ||
| 1132 | */ | ||
| 1133 | Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4); | ||
| 1134 | |||
| 1135 | /* | ||
| 1136 | * A zero "save" helps discover equal operands (for later), | ||
| 1137 | * and is used in swapping operands (if needed). | ||
| 1138 | */ | ||
| 1139 | Dblext_xortointp1(tmpresp1,rightp1,/*to*/save); | ||
| 1140 | |||
| 1141 | /* | ||
| 1142 | * Compare magnitude of operands. | ||
| 1143 | */ | ||
| 1144 | Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1); | ||
| 1145 | Dblext_copytoint_exponentmantissap1(rightp1,signlessright1); | ||
| 1146 | if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && | ||
| 1147 | Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){ | ||
| 1148 | /* | ||
| 1149 | * Set the left operand to the larger one by XOR swap. | ||
| 1150 | * First finish the first word "save". | ||
| 1151 | */ | ||
| 1152 | Dblext_xorfromintp1(save,rightp1,/*to*/rightp1); | ||
| 1153 | Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); | ||
| 1154 | Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4, | ||
| 1155 | rightp2,rightp3,rightp4); | ||
| 1156 | /* also setup exponents used in rest of routine */ | ||
| 1157 | diff_exponent = add_exponent - mpy_exponent; | ||
| 1158 | result_exponent = add_exponent; | ||
| 1159 | } else { | ||
| 1160 | /* also setup exponents used in rest of routine */ | ||
| 1161 | diff_exponent = mpy_exponent - add_exponent; | ||
| 1162 | result_exponent = mpy_exponent; | ||
| 1163 | } | ||
| 1164 | /* Invariant: left is not smaller than right. */ | ||
| 1165 | |||
| 1166 | /* | ||
| 1167 | * Special case alignment of operands that would force alignment | ||
| 1168 | * beyond the extent of the extension. A further optimization | ||
| 1169 | * could special case this but only reduces the path length for | ||
| 1170 | * this infrequent case. | ||
| 1171 | */ | ||
| 1172 | if (diff_exponent > DBLEXT_THRESHOLD) { | ||
| 1173 | diff_exponent = DBLEXT_THRESHOLD; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | /* Align right operand by shifting it to the right */ | ||
| 1177 | Dblext_clear_sign(rightp1); | ||
| 1178 | Dblext_right_align(rightp1,rightp2,rightp3,rightp4, | ||
| 1179 | /*shifted by*/diff_exponent); | ||
| 1180 | |||
| 1181 | /* Treat sum and difference of the operands separately. */ | ||
| 1182 | if ((int)save < 0) { | ||
| 1183 | /* | ||
| 1184 | * Difference of the two operands. Overflow can occur if the | ||
| 1185 | * multiply overflowed. A borrow can occur out of the hidden | ||
| 1186 | * bit and force a post normalization phase. | ||
| 1187 | */ | ||
| 1188 | Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4, | ||
| 1189 | rightp1,rightp2,rightp3,rightp4, | ||
| 1190 | resultp1,resultp2,resultp3,resultp4); | ||
| 1191 | sign_save = Dbl_signextendedsign(resultp1); | ||
| 1192 | if (Dbl_iszero_hidden(resultp1)) { | ||
| 1193 | /* Handle normalization */ | ||
| 1194 | /* A straight foward algorithm would now shift the | ||
| 1195 | * result and extension left until the hidden bit | ||
| 1196 | * becomes one. Not all of the extension bits need | ||
| 1197 | * participate in the shift. Only the two most | ||
| 1198 | * significant bits (round and guard) are needed. | ||
| 1199 | * If only a single shift is needed then the guard | ||
| 1200 | * bit becomes a significant low order bit and the | ||
| 1201 | * extension must participate in the rounding. | ||
| 1202 | * If more than a single shift is needed, then all | ||
| 1203 | * bits to the right of the guard bit are zeros, | ||
| 1204 | * and the guard bit may or may not be zero. */ | ||
| 1205 | Dblext_leftshiftby1(resultp1,resultp2,resultp3, | ||
| 1206 | resultp4); | ||
| 1207 | |||
| 1208 | /* Need to check for a zero result. The sign and | ||
| 1209 | * exponent fields have already been zeroed. The more | ||
| 1210 | * efficient test of the full object can be used. | ||
| 1211 | */ | ||
| 1212 | if (Dblext_iszero(resultp1,resultp2,resultp3,resultp4)) { | ||
| 1213 | /* Must have been "x-x" or "x+(-x)". */ | ||
| 1214 | if (Is_rounding_mode(ROUNDMINUS)) | ||
| 1215 | Dbl_setone_sign(resultp1); | ||
| 1216 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 1217 | return(NOEXCEPTION); | ||
| 1218 | } | ||
| 1219 | result_exponent--; | ||
| 1220 | |||
| 1221 | /* Look to see if normalization is finished. */ | ||
| 1222 | if (Dbl_isone_hidden(resultp1)) { | ||
| 1223 | /* No further normalization is needed */ | ||
| 1224 | goto round; | ||
| 1225 | } | ||
| 1226 | |||
| 1227 | /* Discover first one bit to determine shift amount. | ||
| 1228 | * Use a modified binary search. We have already | ||
| 1229 | * shifted the result one position right and still | ||
| 1230 | * not found a one so the remainder of the extension | ||
| 1231 | * must be zero and simplifies rounding. */ | ||
| 1232 | /* Scan bytes */ | ||
| 1233 | while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) { | ||
| 1234 | Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4); | ||
| 1235 | result_exponent -= 8; | ||
| 1236 | } | ||
| 1237 | /* Now narrow it down to the nibble */ | ||
| 1238 | if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) { | ||
| 1239 | /* The lower nibble contains the | ||
| 1240 | * normalizing one */ | ||
| 1241 | Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4); | ||
| 1242 | result_exponent -= 4; | ||
| 1243 | } | ||
| 1244 | /* Select case where first bit is set (already | ||
| 1245 | * normalized) otherwise select the proper shift. */ | ||
| 1246 | jumpsize = Dbl_hiddenhigh3mantissa(resultp1); | ||
| 1247 | if (jumpsize <= 7) switch(jumpsize) { | ||
| 1248 | case 1: | ||
| 1249 | Dblext_leftshiftby3(resultp1,resultp2,resultp3, | ||
| 1250 | resultp4); | ||
| 1251 | result_exponent -= 3; | ||
| 1252 | break; | ||
| 1253 | case 2: | ||
| 1254 | case 3: | ||
| 1255 | Dblext_leftshiftby2(resultp1,resultp2,resultp3, | ||
| 1256 | resultp4); | ||
| 1257 | result_exponent -= 2; | ||
| 1258 | break; | ||
| 1259 | case 4: | ||
| 1260 | case 5: | ||
| 1261 | case 6: | ||
| 1262 | case 7: | ||
| 1263 | Dblext_leftshiftby1(resultp1,resultp2,resultp3, | ||
| 1264 | resultp4); | ||
| 1265 | result_exponent -= 1; | ||
| 1266 | break; | ||
| 1267 | } | ||
| 1268 | } /* end if (hidden...)... */ | ||
| 1269 | /* Fall through and round */ | ||
| 1270 | } /* end if (save < 0)... */ | ||
| 1271 | else { | ||
| 1272 | /* Add magnitudes */ | ||
| 1273 | Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4, | ||
| 1274 | rightp1,rightp2,rightp3,rightp4, | ||
| 1275 | /*to*/resultp1,resultp2,resultp3,resultp4); | ||
| 1276 | sign_save = Dbl_signextendedsign(resultp1); | ||
| 1277 | if (Dbl_isone_hiddenoverflow(resultp1)) { | ||
| 1278 | /* Prenormalization required. */ | ||
| 1279 | Dblext_arithrightshiftby1(resultp1,resultp2,resultp3, | ||
| 1280 | resultp4); | ||
| 1281 | result_exponent++; | ||
| 1282 | } /* end if hiddenoverflow... */ | ||
| 1283 | } /* end else ...add magnitudes... */ | ||
| 1284 | |||
| 1285 | /* Round the result. If the extension and lower two words are | ||
| 1286 | * all zeros, then the result is exact. Otherwise round in the | ||
| 1287 | * correct direction. Underflow is possible. If a postnormalization | ||
| 1288 | * is necessary, then the mantissa is all zeros so no shift is needed. | ||
| 1289 | */ | ||
| 1290 | round: | ||
| 1291 | if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { | ||
| 1292 | Dblext_denormalize(resultp1,resultp2,resultp3,resultp4, | ||
| 1293 | result_exponent,is_tiny); | ||
| 1294 | } | ||
| 1295 | Dbl_set_sign(resultp1,/*using*/sign_save); | ||
| 1296 | if (Dblext_isnotzero_mantissap3(resultp3) || | ||
| 1297 | Dblext_isnotzero_mantissap4(resultp4)) { | ||
| 1298 | inexact = TRUE; | ||
| 1299 | switch(Rounding_mode()) { | ||
| 1300 | case ROUNDNEAREST: /* The default. */ | ||
| 1301 | if (Dblext_isone_highp3(resultp3)) { | ||
| 1302 | /* at least 1/2 ulp */ | ||
| 1303 | if (Dblext_isnotzero_low31p3(resultp3) || | ||
| 1304 | Dblext_isnotzero_mantissap4(resultp4) || | ||
| 1305 | Dblext_isone_lowp2(resultp2)) { | ||
| 1306 | /* either exactly half way and odd or | ||
| 1307 | * more than 1/2ulp */ | ||
| 1308 | Dbl_increment(resultp1,resultp2); | ||
| 1309 | } | ||
| 1310 | } | ||
| 1311 | break; | ||
| 1312 | |||
| 1313 | case ROUNDPLUS: | ||
| 1314 | if (Dbl_iszero_sign(resultp1)) { | ||
| 1315 | /* Round up positive results */ | ||
| 1316 | Dbl_increment(resultp1,resultp2); | ||
| 1317 | } | ||
| 1318 | break; | ||
| 1319 | |||
| 1320 | case ROUNDMINUS: | ||
| 1321 | if (Dbl_isone_sign(resultp1)) { | ||
| 1322 | /* Round down negative results */ | ||
| 1323 | Dbl_increment(resultp1,resultp2); | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | case ROUNDZERO:; | ||
| 1327 | /* truncate is simple */ | ||
| 1328 | } /* end switch... */ | ||
| 1329 | if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++; | ||
| 1330 | } | ||
| 1331 | if (result_exponent >= DBL_INFINITY_EXPONENT) { | ||
| 1332 | /* Overflow */ | ||
| 1333 | if (Is_overflowtrap_enabled()) { | ||
| 1334 | /* | ||
| 1335 | * Adjust bias of result | ||
| 1336 | */ | ||
| 1337 | Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl); | ||
| 1338 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 1339 | if (inexact) | ||
| 1340 | if (Is_inexacttrap_enabled()) | ||
| 1341 | return (OPC_2E_OVERFLOWEXCEPTION | | ||
| 1342 | OPC_2E_INEXACTEXCEPTION); | ||
| 1343 | else Set_inexactflag(); | ||
| 1344 | return (OPC_2E_OVERFLOWEXCEPTION); | ||
| 1345 | } | ||
| 1346 | inexact = TRUE; | ||
| 1347 | Set_overflowflag(); | ||
| 1348 | Dbl_setoverflow(resultp1,resultp2); | ||
| 1349 | } else if (result_exponent <= 0) { /* underflow case */ | ||
| 1350 | if (Is_underflowtrap_enabled()) { | ||
| 1351 | /* | ||
| 1352 | * Adjust bias of result | ||
| 1353 | */ | ||
| 1354 | Dbl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
| 1355 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 1356 | if (inexact) | ||
| 1357 | if (Is_inexacttrap_enabled()) | ||
| 1358 | return (OPC_2E_UNDERFLOWEXCEPTION | | ||
| 1359 | OPC_2E_INEXACTEXCEPTION); | ||
| 1360 | else Set_inexactflag(); | ||
| 1361 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
| 1362 | } | ||
| 1363 | else if (inexact && is_tiny) Set_underflowflag(); | ||
| 1364 | } | ||
| 1365 | else Dbl_set_exponent(resultp1,result_exponent); | ||
| 1366 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 1367 | if (inexact) | ||
| 1368 | if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); | ||
| 1369 | else Set_inexactflag(); | ||
| 1370 | return(NOEXCEPTION); | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | /* | ||
| 1374 | * Single Floating-point Multiply Fused Add | ||
| 1375 | */ | ||
| 1376 | |||
| 1377 | sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr) | ||
| 1378 | |||
| 1379 | sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr; | ||
| 1380 | unsigned int *status; | ||
| 1381 | { | ||
| 1382 | unsigned int opnd1, opnd2, opnd3; | ||
| 1383 | register unsigned int tmpresp1, tmpresp2; | ||
| 1384 | unsigned int rightp1, rightp2; | ||
| 1385 | unsigned int resultp1, resultp2 = 0; | ||
| 1386 | register int mpy_exponent, add_exponent, count; | ||
| 1387 | boolean inexact = FALSE, is_tiny = FALSE; | ||
| 1388 | |||
| 1389 | unsigned int signlessleft1, signlessright1, save; | ||
| 1390 | register int result_exponent, diff_exponent; | ||
| 1391 | int sign_save, jumpsize; | ||
| 1392 | |||
| 1393 | Sgl_copyfromptr(src1ptr,opnd1); | ||
| 1394 | Sgl_copyfromptr(src2ptr,opnd2); | ||
| 1395 | Sgl_copyfromptr(src3ptr,opnd3); | ||
| 1396 | |||
| 1397 | /* | ||
| 1398 | * set sign bit of result of multiply | ||
| 1399 | */ | ||
| 1400 | if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) | ||
| 1401 | Sgl_setnegativezero(resultp1); | ||
| 1402 | else Sgl_setzero(resultp1); | ||
| 1403 | |||
| 1404 | /* | ||
| 1405 | * Generate multiply exponent | ||
| 1406 | */ | ||
| 1407 | mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS; | ||
| 1408 | |||
| 1409 | /* | ||
| 1410 | * check first operand for NaN's or infinity | ||
| 1411 | */ | ||
| 1412 | if (Sgl_isinfinity_exponent(opnd1)) { | ||
| 1413 | if (Sgl_iszero_mantissa(opnd1)) { | ||
| 1414 | if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) { | ||
| 1415 | if (Sgl_iszero_exponentmantissa(opnd2)) { | ||
| 1416 | /* | ||
| 1417 | * invalid since operands are infinity | ||
| 1418 | * and zero | ||
| 1419 | */ | ||
| 1420 | if (Is_invalidtrap_enabled()) | ||
| 1421 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 1422 | Set_invalidflag(); | ||
| 1423 | Sgl_makequietnan(resultp1); | ||
| 1424 | Sgl_copytoptr(resultp1,dstptr); | ||
| 1425 | return(NOEXCEPTION); | ||
| 1426 | } | ||
| 1427 | /* | ||
| 1428 | * Check third operand for infinity with a | ||
| 1429 | * sign opposite of the multiply result | ||
| 1430 | */ | ||
| 1431 | if (Sgl_isinfinity(opnd3) && | ||
| 1432 | (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { | ||
| 1433 | /* | ||
| 1434 | * invalid since attempting a magnitude | ||
| 1435 | * subtraction of infinities | ||
| 1436 | */ | ||
| 1437 | if (Is_invalidtrap_enabled()) | ||
| 1438 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 1439 | Set_invalidflag(); | ||
| 1440 | Sgl_makequietnan(resultp1); | ||
| 1441 | Sgl_copytoptr(resultp1,dstptr); | ||
| 1442 | return(NOEXCEPTION); | ||
| 1443 | } | ||
| 1444 | |||
| 1445 | /* | ||
| 1446 | * return infinity | ||
| 1447 | */ | ||
| 1448 | Sgl_setinfinity_exponentmantissa(resultp1); | ||
| 1449 | Sgl_copytoptr(resultp1,dstptr); | ||
| 1450 | return(NOEXCEPTION); | ||
| 1451 | } | ||
| 1452 | } | ||
| 1453 | else { | ||
| 1454 | /* | ||
| 1455 | * is NaN; signaling or quiet? | ||
| 1456 | */ | ||
| 1457 | if (Sgl_isone_signaling(opnd1)) { | ||
| 1458 | /* trap if INVALIDTRAP enabled */ | ||
| 1459 | if (Is_invalidtrap_enabled()) | ||
| 1460 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 1461 | /* make NaN quiet */ | ||
| 1462 | Set_invalidflag(); | ||
| 1463 | Sgl_set_quiet(opnd1); | ||
| 1464 | } | ||
| 1465 | /* | ||
| 1466 | * is second operand a signaling NaN? | ||
| 1467 | */ | ||
| 1468 | else if (Sgl_is_signalingnan(opnd2)) { | ||
| 1469 | /* trap if INVALIDTRAP enabled */ | ||
| 1470 | if (Is_invalidtrap_enabled()) | ||
| 1471 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 1472 | /* make NaN quiet */ | ||
| 1473 | Set_invalidflag(); | ||
| 1474 | Sgl_set_quiet(opnd2); | ||
| 1475 | Sgl_copytoptr(opnd2,dstptr); | ||
| 1476 | return(NOEXCEPTION); | ||
| 1477 | } | ||
| 1478 | /* | ||
| 1479 | * is third operand a signaling NaN? | ||
| 1480 | */ | ||
| 1481 | else if (Sgl_is_signalingnan(opnd3)) { | ||
| 1482 | /* trap if INVALIDTRAP enabled */ | ||
| 1483 | if (Is_invalidtrap_enabled()) | ||
| 1484 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 1485 | /* make NaN quiet */ | ||
| 1486 | Set_invalidflag(); | ||
| 1487 | Sgl_set_quiet(opnd3); | ||
| 1488 | Sgl_copytoptr(opnd3,dstptr); | ||
| 1489 | return(NOEXCEPTION); | ||
| 1490 | } | ||
| 1491 | /* | ||
| 1492 | * return quiet NaN | ||
| 1493 | */ | ||
| 1494 | Sgl_copytoptr(opnd1,dstptr); | ||
| 1495 | return(NOEXCEPTION); | ||
| 1496 | } | ||
| 1497 | } | ||
| 1498 | |||
| 1499 | /* | ||
| 1500 | * check second operand for NaN's or infinity | ||
| 1501 | */ | ||
| 1502 | if (Sgl_isinfinity_exponent(opnd2)) { | ||
| 1503 | if (Sgl_iszero_mantissa(opnd2)) { | ||
| 1504 | if (Sgl_isnotnan(opnd3)) { | ||
| 1505 | if (Sgl_iszero_exponentmantissa(opnd1)) { | ||
| 1506 | /* | ||
| 1507 | * invalid since multiply operands are | ||
| 1508 | * zero & infinity | ||
| 1509 | */ | ||
| 1510 | if (Is_invalidtrap_enabled()) | ||
| 1511 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 1512 | Set_invalidflag(); | ||
| 1513 | Sgl_makequietnan(opnd2); | ||
| 1514 | Sgl_copytoptr(opnd2,dstptr); | ||
| 1515 | return(NOEXCEPTION); | ||
| 1516 | } | ||
| 1517 | |||
| 1518 | /* | ||
| 1519 | * Check third operand for infinity with a | ||
| 1520 | * sign opposite of the multiply result | ||
| 1521 | */ | ||
| 1522 | if (Sgl_isinfinity(opnd3) && | ||
| 1523 | (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { | ||
| 1524 | /* | ||
| 1525 | * invalid since attempting a magnitude | ||
| 1526 | * subtraction of infinities | ||
| 1527 | */ | ||
| 1528 | if (Is_invalidtrap_enabled()) | ||
| 1529 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 1530 | Set_invalidflag(); | ||
| 1531 | Sgl_makequietnan(resultp1); | ||
| 1532 | Sgl_copytoptr(resultp1,dstptr); | ||
| 1533 | return(NOEXCEPTION); | ||
| 1534 | } | ||
| 1535 | |||
| 1536 | /* | ||
| 1537 | * return infinity | ||
| 1538 | */ | ||
| 1539 | Sgl_setinfinity_exponentmantissa(resultp1); | ||
| 1540 | Sgl_copytoptr(resultp1,dstptr); | ||
| 1541 | return(NOEXCEPTION); | ||
| 1542 | } | ||
| 1543 | } | ||
| 1544 | else { | ||
| 1545 | /* | ||
| 1546 | * is NaN; signaling or quiet? | ||
| 1547 | */ | ||
| 1548 | if (Sgl_isone_signaling(opnd2)) { | ||
| 1549 | /* trap if INVALIDTRAP enabled */ | ||
| 1550 | if (Is_invalidtrap_enabled()) | ||
| 1551 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 1552 | /* make NaN quiet */ | ||
| 1553 | Set_invalidflag(); | ||
| 1554 | Sgl_set_quiet(opnd2); | ||
| 1555 | } | ||
| 1556 | /* | ||
| 1557 | * is third operand a signaling NaN? | ||
| 1558 | */ | ||
| 1559 | else if (Sgl_is_signalingnan(opnd3)) { | ||
| 1560 | /* trap if INVALIDTRAP enabled */ | ||
| 1561 | if (Is_invalidtrap_enabled()) | ||
| 1562 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 1563 | /* make NaN quiet */ | ||
| 1564 | Set_invalidflag(); | ||
| 1565 | Sgl_set_quiet(opnd3); | ||
| 1566 | Sgl_copytoptr(opnd3,dstptr); | ||
| 1567 | return(NOEXCEPTION); | ||
| 1568 | } | ||
| 1569 | /* | ||
| 1570 | * return quiet NaN | ||
| 1571 | */ | ||
| 1572 | Sgl_copytoptr(opnd2,dstptr); | ||
| 1573 | return(NOEXCEPTION); | ||
| 1574 | } | ||
| 1575 | } | ||
| 1576 | |||
| 1577 | /* | ||
| 1578 | * check third operand for NaN's or infinity | ||
| 1579 | */ | ||
| 1580 | if (Sgl_isinfinity_exponent(opnd3)) { | ||
| 1581 | if (Sgl_iszero_mantissa(opnd3)) { | ||
| 1582 | /* return infinity */ | ||
| 1583 | Sgl_copytoptr(opnd3,dstptr); | ||
| 1584 | return(NOEXCEPTION); | ||
| 1585 | } else { | ||
| 1586 | /* | ||
| 1587 | * is NaN; signaling or quiet? | ||
| 1588 | */ | ||
| 1589 | if (Sgl_isone_signaling(opnd3)) { | ||
| 1590 | /* trap if INVALIDTRAP enabled */ | ||
| 1591 | if (Is_invalidtrap_enabled()) | ||
| 1592 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 1593 | /* make NaN quiet */ | ||
| 1594 | Set_invalidflag(); | ||
| 1595 | Sgl_set_quiet(opnd3); | ||
| 1596 | } | ||
| 1597 | /* | ||
| 1598 | * return quiet NaN | ||
| 1599 | */ | ||
| 1600 | Sgl_copytoptr(opnd3,dstptr); | ||
| 1601 | return(NOEXCEPTION); | ||
| 1602 | } | ||
| 1603 | } | ||
| 1604 | |||
| 1605 | /* | ||
| 1606 | * Generate multiply mantissa | ||
| 1607 | */ | ||
| 1608 | if (Sgl_isnotzero_exponent(opnd1)) { | ||
| 1609 | /* set hidden bit */ | ||
| 1610 | Sgl_clear_signexponent_set_hidden(opnd1); | ||
| 1611 | } | ||
| 1612 | else { | ||
| 1613 | /* check for zero */ | ||
| 1614 | if (Sgl_iszero_mantissa(opnd1)) { | ||
| 1615 | /* | ||
| 1616 | * Perform the add opnd3 with zero here. | ||
| 1617 | */ | ||
| 1618 | if (Sgl_iszero_exponentmantissa(opnd3)) { | ||
| 1619 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
| 1620 | Sgl_or_signs(opnd3,resultp1); | ||
| 1621 | } else { | ||
| 1622 | Sgl_and_signs(opnd3,resultp1); | ||
| 1623 | } | ||
| 1624 | } | ||
| 1625 | /* | ||
| 1626 | * Now let's check for trapped underflow case. | ||
| 1627 | */ | ||
| 1628 | else if (Sgl_iszero_exponent(opnd3) && | ||
| 1629 | Is_underflowtrap_enabled()) { | ||
| 1630 | /* need to normalize results mantissa */ | ||
| 1631 | sign_save = Sgl_signextendedsign(opnd3); | ||
| 1632 | result_exponent = 0; | ||
| 1633 | Sgl_leftshiftby1(opnd3); | ||
| 1634 | Sgl_normalize(opnd3,result_exponent); | ||
| 1635 | Sgl_set_sign(opnd3,/*using*/sign_save); | ||
| 1636 | Sgl_setwrapped_exponent(opnd3,result_exponent, | ||
| 1637 | unfl); | ||
| 1638 | Sgl_copytoptr(opnd3,dstptr); | ||
| 1639 | /* inexact = FALSE */ | ||
| 1640 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
| 1641 | } | ||
| 1642 | Sgl_copytoptr(opnd3,dstptr); | ||
| 1643 | return(NOEXCEPTION); | ||
| 1644 | } | ||
| 1645 | /* is denormalized, adjust exponent */ | ||
| 1646 | Sgl_clear_signexponent(opnd1); | ||
| 1647 | Sgl_leftshiftby1(opnd1); | ||
| 1648 | Sgl_normalize(opnd1,mpy_exponent); | ||
| 1649 | } | ||
| 1650 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
| 1651 | if (Sgl_isnotzero_exponent(opnd2)) { | ||
| 1652 | Sgl_clear_signexponent_set_hidden(opnd2); | ||
| 1653 | } | ||
| 1654 | else { | ||
| 1655 | /* check for zero */ | ||
| 1656 | if (Sgl_iszero_mantissa(opnd2)) { | ||
| 1657 | /* | ||
| 1658 | * Perform the add opnd3 with zero here. | ||
| 1659 | */ | ||
| 1660 | if (Sgl_iszero_exponentmantissa(opnd3)) { | ||
| 1661 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
| 1662 | Sgl_or_signs(opnd3,resultp1); | ||
| 1663 | } else { | ||
| 1664 | Sgl_and_signs(opnd3,resultp1); | ||
| 1665 | } | ||
| 1666 | } | ||
| 1667 | /* | ||
| 1668 | * Now let's check for trapped underflow case. | ||
| 1669 | */ | ||
| 1670 | else if (Sgl_iszero_exponent(opnd3) && | ||
| 1671 | Is_underflowtrap_enabled()) { | ||
| 1672 | /* need to normalize results mantissa */ | ||
| 1673 | sign_save = Sgl_signextendedsign(opnd3); | ||
| 1674 | result_exponent = 0; | ||
| 1675 | Sgl_leftshiftby1(opnd3); | ||
| 1676 | Sgl_normalize(opnd3,result_exponent); | ||
| 1677 | Sgl_set_sign(opnd3,/*using*/sign_save); | ||
| 1678 | Sgl_setwrapped_exponent(opnd3,result_exponent, | ||
| 1679 | unfl); | ||
| 1680 | Sgl_copytoptr(opnd3,dstptr); | ||
| 1681 | /* inexact = FALSE */ | ||
| 1682 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
| 1683 | } | ||
| 1684 | Sgl_copytoptr(opnd3,dstptr); | ||
| 1685 | return(NOEXCEPTION); | ||
| 1686 | } | ||
| 1687 | /* is denormalized; want to normalize */ | ||
| 1688 | Sgl_clear_signexponent(opnd2); | ||
| 1689 | Sgl_leftshiftby1(opnd2); | ||
| 1690 | Sgl_normalize(opnd2,mpy_exponent); | ||
| 1691 | } | ||
| 1692 | |||
| 1693 | /* Multiply the first two source mantissas together */ | ||
| 1694 | |||
| 1695 | /* | ||
| 1696 | * The intermediate result will be kept in tmpres, | ||
| 1697 | * which needs enough room for 106 bits of mantissa, | ||
| 1698 | * so lets call it a Double extended. | ||
| 1699 | */ | ||
| 1700 | Sglext_setzero(tmpresp1,tmpresp2); | ||
| 1701 | |||
| 1702 | /* | ||
| 1703 | * Four bits at a time are inspected in each loop, and a | ||
| 1704 | * simple shift and add multiply algorithm is used. | ||
| 1705 | */ | ||
| 1706 | for (count = SGL_P-1; count >= 0; count -= 4) { | ||
| 1707 | Sglext_rightshiftby4(tmpresp1,tmpresp2); | ||
| 1708 | if (Sbit28(opnd1)) { | ||
| 1709 | /* Twoword_add should be an ADD followed by 2 ADDC's */ | ||
| 1710 | Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0); | ||
| 1711 | } | ||
| 1712 | if (Sbit29(opnd1)) { | ||
| 1713 | Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0); | ||
| 1714 | } | ||
| 1715 | if (Sbit30(opnd1)) { | ||
| 1716 | Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0); | ||
| 1717 | } | ||
| 1718 | if (Sbit31(opnd1)) { | ||
| 1719 | Twoword_add(tmpresp1, tmpresp2, opnd2, 0); | ||
| 1720 | } | ||
| 1721 | Sgl_rightshiftby4(opnd1); | ||
| 1722 | } | ||
| 1723 | if (Is_sexthiddenoverflow(tmpresp1)) { | ||
| 1724 | /* result mantissa >= 2 (mantissa overflow) */ | ||
| 1725 | mpy_exponent++; | ||
| 1726 | Sglext_rightshiftby4(tmpresp1,tmpresp2); | ||
| 1727 | } else { | ||
| 1728 | Sglext_rightshiftby3(tmpresp1,tmpresp2); | ||
| 1729 | } | ||
| 1730 | |||
| 1731 | /* | ||
| 1732 | * Restore the sign of the mpy result which was saved in resultp1. | ||
| 1733 | * The exponent will continue to be kept in mpy_exponent. | ||
| 1734 | */ | ||
| 1735 | Sglext_set_sign(tmpresp1,Sgl_sign(resultp1)); | ||
| 1736 | |||
| 1737 | /* | ||
| 1738 | * No rounding is required, since the result of the multiply | ||
| 1739 | * is exact in the extended format. | ||
| 1740 | */ | ||
| 1741 | |||
| 1742 | /* | ||
| 1743 | * Now we are ready to perform the add portion of the operation. | ||
| 1744 | * | ||
| 1745 | * The exponents need to be kept as integers for now, since the | ||
| 1746 | * multiply result might not fit into the exponent field. We | ||
| 1747 | * can't overflow or underflow because of this yet, since the | ||
| 1748 | * add could bring the final result back into range. | ||
| 1749 | */ | ||
| 1750 | add_exponent = Sgl_exponent(opnd3); | ||
| 1751 | |||
| 1752 | /* | ||
| 1753 | * Check for denormalized or zero add operand. | ||
| 1754 | */ | ||
| 1755 | if (add_exponent == 0) { | ||
| 1756 | /* check for zero */ | ||
| 1757 | if (Sgl_iszero_mantissa(opnd3)) { | ||
| 1758 | /* right is zero */ | ||
| 1759 | /* Left can't be zero and must be result. | ||
| 1760 | * | ||
| 1761 | * The final result is now in tmpres and mpy_exponent, | ||
| 1762 | * and needs to be rounded and squeezed back into | ||
| 1763 | * double precision format from double extended. | ||
| 1764 | */ | ||
| 1765 | result_exponent = mpy_exponent; | ||
| 1766 | Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2); | ||
| 1767 | sign_save = Sgl_signextendedsign(resultp1);/*save sign*/ | ||
| 1768 | goto round; | ||
| 1769 | } | ||
| 1770 | |||
| 1771 | /* | ||
| 1772 | * Neither are zeroes. | ||
| 1773 | * Adjust exponent and normalize add operand. | ||
| 1774 | */ | ||
| 1775 | sign_save = Sgl_signextendedsign(opnd3); /* save sign */ | ||
| 1776 | Sgl_clear_signexponent(opnd3); | ||
| 1777 | Sgl_leftshiftby1(opnd3); | ||
| 1778 | Sgl_normalize(opnd3,add_exponent); | ||
| 1779 | Sgl_set_sign(opnd3,sign_save); /* restore sign */ | ||
| 1780 | } else { | ||
| 1781 | Sgl_clear_exponent_set_hidden(opnd3); | ||
| 1782 | } | ||
| 1783 | /* | ||
| 1784 | * Copy opnd3 to the double extended variable called right. | ||
| 1785 | */ | ||
| 1786 | Sgl_copyto_sglext(opnd3,rightp1,rightp2); | ||
| 1787 | |||
| 1788 | /* | ||
| 1789 | * A zero "save" helps discover equal operands (for later), | ||
| 1790 | * and is used in swapping operands (if needed). | ||
| 1791 | */ | ||
| 1792 | Sglext_xortointp1(tmpresp1,rightp1,/*to*/save); | ||
| 1793 | |||
| 1794 | /* | ||
| 1795 | * Compare magnitude of operands. | ||
| 1796 | */ | ||
| 1797 | Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1); | ||
| 1798 | Sglext_copytoint_exponentmantissa(rightp1,signlessright1); | ||
| 1799 | if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && | ||
| 1800 | Sglext_ismagnitudeless(signlessleft1,signlessright1)) { | ||
| 1801 | /* | ||
| 1802 | * Set the left operand to the larger one by XOR swap. | ||
| 1803 | * First finish the first word "save". | ||
| 1804 | */ | ||
| 1805 | Sglext_xorfromintp1(save,rightp1,/*to*/rightp1); | ||
| 1806 | Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); | ||
| 1807 | Sglext_swap_lower(tmpresp2,rightp2); | ||
| 1808 | /* also setup exponents used in rest of routine */ | ||
| 1809 | diff_exponent = add_exponent - mpy_exponent; | ||
| 1810 | result_exponent = add_exponent; | ||
| 1811 | } else { | ||
| 1812 | /* also setup exponents used in rest of routine */ | ||
| 1813 | diff_exponent = mpy_exponent - add_exponent; | ||
| 1814 | result_exponent = mpy_exponent; | ||
| 1815 | } | ||
| 1816 | /* Invariant: left is not smaller than right. */ | ||
| 1817 | |||
| 1818 | /* | ||
| 1819 | * Special case alignment of operands that would force alignment | ||
| 1820 | * beyond the extent of the extension. A further optimization | ||
| 1821 | * could special case this but only reduces the path length for | ||
| 1822 | * this infrequent case. | ||
| 1823 | */ | ||
| 1824 | if (diff_exponent > SGLEXT_THRESHOLD) { | ||
| 1825 | diff_exponent = SGLEXT_THRESHOLD; | ||
| 1826 | } | ||
| 1827 | |||
| 1828 | /* Align right operand by shifting it to the right */ | ||
| 1829 | Sglext_clear_sign(rightp1); | ||
| 1830 | Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent); | ||
| 1831 | |||
| 1832 | /* Treat sum and difference of the operands separately. */ | ||
| 1833 | if ((int)save < 0) { | ||
| 1834 | /* | ||
| 1835 | * Difference of the two operands. Overflow can occur if the | ||
| 1836 | * multiply overflowed. A borrow can occur out of the hidden | ||
| 1837 | * bit and force a post normalization phase. | ||
| 1838 | */ | ||
| 1839 | Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2, | ||
| 1840 | resultp1,resultp2); | ||
| 1841 | sign_save = Sgl_signextendedsign(resultp1); | ||
| 1842 | if (Sgl_iszero_hidden(resultp1)) { | ||
| 1843 | /* Handle normalization */ | ||
| 1844 | /* A straight foward algorithm would now shift the | ||
| 1845 | * result and extension left until the hidden bit | ||
| 1846 | * becomes one. Not all of the extension bits need | ||
| 1847 | * participate in the shift. Only the two most | ||
| 1848 | * significant bits (round and guard) are needed. | ||
| 1849 | * If only a single shift is needed then the guard | ||
| 1850 | * bit becomes a significant low order bit and the | ||
| 1851 | * extension must participate in the rounding. | ||
| 1852 | * If more than a single shift is needed, then all | ||
| 1853 | * bits to the right of the guard bit are zeros, | ||
| 1854 | * and the guard bit may or may not be zero. */ | ||
| 1855 | Sglext_leftshiftby1(resultp1,resultp2); | ||
| 1856 | |||
| 1857 | /* Need to check for a zero result. The sign and | ||
| 1858 | * exponent fields have already been zeroed. The more | ||
| 1859 | * efficient test of the full object can be used. | ||
| 1860 | */ | ||
| 1861 | if (Sglext_iszero(resultp1,resultp2)) { | ||
| 1862 | /* Must have been "x-x" or "x+(-x)". */ | ||
| 1863 | if (Is_rounding_mode(ROUNDMINUS)) | ||
| 1864 | Sgl_setone_sign(resultp1); | ||
| 1865 | Sgl_copytoptr(resultp1,dstptr); | ||
| 1866 | return(NOEXCEPTION); | ||
| 1867 | } | ||
| 1868 | result_exponent--; | ||
| 1869 | |||
| 1870 | /* Look to see if normalization is finished. */ | ||
| 1871 | if (Sgl_isone_hidden(resultp1)) { | ||
| 1872 | /* No further normalization is needed */ | ||
| 1873 | goto round; | ||
| 1874 | } | ||
| 1875 | |||
| 1876 | /* Discover first one bit to determine shift amount. | ||
| 1877 | * Use a modified binary search. We have already | ||
| 1878 | * shifted the result one position right and still | ||
| 1879 | * not found a one so the remainder of the extension | ||
| 1880 | * must be zero and simplifies rounding. */ | ||
| 1881 | /* Scan bytes */ | ||
| 1882 | while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) { | ||
| 1883 | Sglext_leftshiftby8(resultp1,resultp2); | ||
| 1884 | result_exponent -= 8; | ||
| 1885 | } | ||
| 1886 | /* Now narrow it down to the nibble */ | ||
| 1887 | if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) { | ||
| 1888 | /* The lower nibble contains the | ||
| 1889 | * normalizing one */ | ||
| 1890 | Sglext_leftshiftby4(resultp1,resultp2); | ||
| 1891 | result_exponent -= 4; | ||
| 1892 | } | ||
| 1893 | /* Select case where first bit is set (already | ||
| 1894 | * normalized) otherwise select the proper shift. */ | ||
| 1895 | jumpsize = Sgl_hiddenhigh3mantissa(resultp1); | ||
| 1896 | if (jumpsize <= 7) switch(jumpsize) { | ||
| 1897 | case 1: | ||
| 1898 | Sglext_leftshiftby3(resultp1,resultp2); | ||
| 1899 | result_exponent -= 3; | ||
| 1900 | break; | ||
| 1901 | case 2: | ||
| 1902 | case 3: | ||
| 1903 | Sglext_leftshiftby2(resultp1,resultp2); | ||
| 1904 | result_exponent -= 2; | ||
| 1905 | break; | ||
| 1906 | case 4: | ||
| 1907 | case 5: | ||
| 1908 | case 6: | ||
| 1909 | case 7: | ||
| 1910 | Sglext_leftshiftby1(resultp1,resultp2); | ||
| 1911 | result_exponent -= 1; | ||
| 1912 | break; | ||
| 1913 | } | ||
| 1914 | } /* end if (hidden...)... */ | ||
| 1915 | /* Fall through and round */ | ||
| 1916 | } /* end if (save < 0)... */ | ||
| 1917 | else { | ||
| 1918 | /* Add magnitudes */ | ||
| 1919 | Sglext_addition(tmpresp1,tmpresp2, | ||
| 1920 | rightp1,rightp2, /*to*/resultp1,resultp2); | ||
| 1921 | sign_save = Sgl_signextendedsign(resultp1); | ||
| 1922 | if (Sgl_isone_hiddenoverflow(resultp1)) { | ||
| 1923 | /* Prenormalization required. */ | ||
| 1924 | Sglext_arithrightshiftby1(resultp1,resultp2); | ||
| 1925 | result_exponent++; | ||
| 1926 | } /* end if hiddenoverflow... */ | ||
| 1927 | } /* end else ...add magnitudes... */ | ||
| 1928 | |||
| 1929 | /* Round the result. If the extension and lower two words are | ||
| 1930 | * all zeros, then the result is exact. Otherwise round in the | ||
| 1931 | * correct direction. Underflow is possible. If a postnormalization | ||
| 1932 | * is necessary, then the mantissa is all zeros so no shift is needed. | ||
| 1933 | */ | ||
| 1934 | round: | ||
| 1935 | if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { | ||
| 1936 | Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny); | ||
| 1937 | } | ||
| 1938 | Sgl_set_sign(resultp1,/*using*/sign_save); | ||
| 1939 | if (Sglext_isnotzero_mantissap2(resultp2)) { | ||
| 1940 | inexact = TRUE; | ||
| 1941 | switch(Rounding_mode()) { | ||
| 1942 | case ROUNDNEAREST: /* The default. */ | ||
| 1943 | if (Sglext_isone_highp2(resultp2)) { | ||
| 1944 | /* at least 1/2 ulp */ | ||
| 1945 | if (Sglext_isnotzero_low31p2(resultp2) || | ||
| 1946 | Sglext_isone_lowp1(resultp1)) { | ||
| 1947 | /* either exactly half way and odd or | ||
| 1948 | * more than 1/2ulp */ | ||
| 1949 | Sgl_increment(resultp1); | ||
| 1950 | } | ||
| 1951 | } | ||
| 1952 | break; | ||
| 1953 | |||
| 1954 | case ROUNDPLUS: | ||
| 1955 | if (Sgl_iszero_sign(resultp1)) { | ||
| 1956 | /* Round up positive results */ | ||
| 1957 | Sgl_increment(resultp1); | ||
| 1958 | } | ||
| 1959 | break; | ||
| 1960 | |||
| 1961 | case ROUNDMINUS: | ||
| 1962 | if (Sgl_isone_sign(resultp1)) { | ||
| 1963 | /* Round down negative results */ | ||
| 1964 | Sgl_increment(resultp1); | ||
| 1965 | } | ||
| 1966 | |||
| 1967 | case ROUNDZERO:; | ||
| 1968 | /* truncate is simple */ | ||
| 1969 | } /* end switch... */ | ||
| 1970 | if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++; | ||
| 1971 | } | ||
| 1972 | if (result_exponent >= SGL_INFINITY_EXPONENT) { | ||
| 1973 | /* Overflow */ | ||
| 1974 | if (Is_overflowtrap_enabled()) { | ||
| 1975 | /* | ||
| 1976 | * Adjust bias of result | ||
| 1977 | */ | ||
| 1978 | Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl); | ||
| 1979 | Sgl_copytoptr(resultp1,dstptr); | ||
| 1980 | if (inexact) | ||
| 1981 | if (Is_inexacttrap_enabled()) | ||
| 1982 | return (OPC_2E_OVERFLOWEXCEPTION | | ||
| 1983 | OPC_2E_INEXACTEXCEPTION); | ||
| 1984 | else Set_inexactflag(); | ||
| 1985 | return (OPC_2E_OVERFLOWEXCEPTION); | ||
| 1986 | } | ||
| 1987 | inexact = TRUE; | ||
| 1988 | Set_overflowflag(); | ||
| 1989 | Sgl_setoverflow(resultp1); | ||
| 1990 | } else if (result_exponent <= 0) { /* underflow case */ | ||
| 1991 | if (Is_underflowtrap_enabled()) { | ||
| 1992 | /* | ||
| 1993 | * Adjust bias of result | ||
| 1994 | */ | ||
| 1995 | Sgl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
| 1996 | Sgl_copytoptr(resultp1,dstptr); | ||
| 1997 | if (inexact) | ||
| 1998 | if (Is_inexacttrap_enabled()) | ||
| 1999 | return (OPC_2E_UNDERFLOWEXCEPTION | | ||
| 2000 | OPC_2E_INEXACTEXCEPTION); | ||
| 2001 | else Set_inexactflag(); | ||
| 2002 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
| 2003 | } | ||
| 2004 | else if (inexact && is_tiny) Set_underflowflag(); | ||
| 2005 | } | ||
| 2006 | else Sgl_set_exponent(resultp1,result_exponent); | ||
| 2007 | Sgl_copytoptr(resultp1,dstptr); | ||
| 2008 | if (inexact) | ||
| 2009 | if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); | ||
| 2010 | else Set_inexactflag(); | ||
| 2011 | return(NOEXCEPTION); | ||
| 2012 | } | ||
| 2013 | |||
| 2014 | /* | ||
| 2015 | * Single Floating-point Multiply Negate Fused Add | ||
| 2016 | */ | ||
| 2017 | |||
| 2018 | sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr) | ||
| 2019 | |||
| 2020 | sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr; | ||
| 2021 | unsigned int *status; | ||
| 2022 | { | ||
| 2023 | unsigned int opnd1, opnd2, opnd3; | ||
| 2024 | register unsigned int tmpresp1, tmpresp2; | ||
| 2025 | unsigned int rightp1, rightp2; | ||
| 2026 | unsigned int resultp1, resultp2 = 0; | ||
| 2027 | register int mpy_exponent, add_exponent, count; | ||
| 2028 | boolean inexact = FALSE, is_tiny = FALSE; | ||
| 2029 | |||
| 2030 | unsigned int signlessleft1, signlessright1, save; | ||
| 2031 | register int result_exponent, diff_exponent; | ||
| 2032 | int sign_save, jumpsize; | ||
| 2033 | |||
| 2034 | Sgl_copyfromptr(src1ptr,opnd1); | ||
| 2035 | Sgl_copyfromptr(src2ptr,opnd2); | ||
| 2036 | Sgl_copyfromptr(src3ptr,opnd3); | ||
| 2037 | |||
| 2038 | /* | ||
| 2039 | * set sign bit of result of multiply | ||
| 2040 | */ | ||
| 2041 | if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) | ||
| 2042 | Sgl_setzero(resultp1); | ||
| 2043 | else | ||
| 2044 | Sgl_setnegativezero(resultp1); | ||
| 2045 | |||
| 2046 | /* | ||
| 2047 | * Generate multiply exponent | ||
| 2048 | */ | ||
| 2049 | mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS; | ||
| 2050 | |||
| 2051 | /* | ||
| 2052 | * check first operand for NaN's or infinity | ||
| 2053 | */ | ||
| 2054 | if (Sgl_isinfinity_exponent(opnd1)) { | ||
| 2055 | if (Sgl_iszero_mantissa(opnd1)) { | ||
| 2056 | if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) { | ||
| 2057 | if (Sgl_iszero_exponentmantissa(opnd2)) { | ||
| 2058 | /* | ||
| 2059 | * invalid since operands are infinity | ||
| 2060 | * and zero | ||
| 2061 | */ | ||
| 2062 | if (Is_invalidtrap_enabled()) | ||
| 2063 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 2064 | Set_invalidflag(); | ||
| 2065 | Sgl_makequietnan(resultp1); | ||
| 2066 | Sgl_copytoptr(resultp1,dstptr); | ||
| 2067 | return(NOEXCEPTION); | ||
| 2068 | } | ||
| 2069 | /* | ||
| 2070 | * Check third operand for infinity with a | ||
| 2071 | * sign opposite of the multiply result | ||
| 2072 | */ | ||
| 2073 | if (Sgl_isinfinity(opnd3) && | ||
| 2074 | (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { | ||
| 2075 | /* | ||
| 2076 | * invalid since attempting a magnitude | ||
| 2077 | * subtraction of infinities | ||
| 2078 | */ | ||
| 2079 | if (Is_invalidtrap_enabled()) | ||
| 2080 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 2081 | Set_invalidflag(); | ||
| 2082 | Sgl_makequietnan(resultp1); | ||
| 2083 | Sgl_copytoptr(resultp1,dstptr); | ||
| 2084 | return(NOEXCEPTION); | ||
| 2085 | } | ||
| 2086 | |||
| 2087 | /* | ||
| 2088 | * return infinity | ||
| 2089 | */ | ||
| 2090 | Sgl_setinfinity_exponentmantissa(resultp1); | ||
| 2091 | Sgl_copytoptr(resultp1,dstptr); | ||
| 2092 | return(NOEXCEPTION); | ||
| 2093 | } | ||
| 2094 | } | ||
| 2095 | else { | ||
| 2096 | /* | ||
| 2097 | * is NaN; signaling or quiet? | ||
| 2098 | */ | ||
| 2099 | if (Sgl_isone_signaling(opnd1)) { | ||
| 2100 | /* trap if INVALIDTRAP enabled */ | ||
| 2101 | if (Is_invalidtrap_enabled()) | ||
| 2102 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 2103 | /* make NaN quiet */ | ||
| 2104 | Set_invalidflag(); | ||
| 2105 | Sgl_set_quiet(opnd1); | ||
| 2106 | } | ||
| 2107 | /* | ||
| 2108 | * is second operand a signaling NaN? | ||
| 2109 | */ | ||
| 2110 | else if (Sgl_is_signalingnan(opnd2)) { | ||
| 2111 | /* trap if INVALIDTRAP enabled */ | ||
| 2112 | if (Is_invalidtrap_enabled()) | ||
| 2113 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 2114 | /* make NaN quiet */ | ||
| 2115 | Set_invalidflag(); | ||
| 2116 | Sgl_set_quiet(opnd2); | ||
| 2117 | Sgl_copytoptr(opnd2,dstptr); | ||
| 2118 | return(NOEXCEPTION); | ||
| 2119 | } | ||
| 2120 | /* | ||
| 2121 | * is third operand a signaling NaN? | ||
| 2122 | */ | ||
| 2123 | else if (Sgl_is_signalingnan(opnd3)) { | ||
| 2124 | /* trap if INVALIDTRAP enabled */ | ||
| 2125 | if (Is_invalidtrap_enabled()) | ||
| 2126 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 2127 | /* make NaN quiet */ | ||
| 2128 | Set_invalidflag(); | ||
| 2129 | Sgl_set_quiet(opnd3); | ||
| 2130 | Sgl_copytoptr(opnd3,dstptr); | ||
| 2131 | return(NOEXCEPTION); | ||
| 2132 | } | ||
| 2133 | /* | ||
| 2134 | * return quiet NaN | ||
| 2135 | */ | ||
| 2136 | Sgl_copytoptr(opnd1,dstptr); | ||
| 2137 | return(NOEXCEPTION); | ||
| 2138 | } | ||
| 2139 | } | ||
| 2140 | |||
| 2141 | /* | ||
| 2142 | * check second operand for NaN's or infinity | ||
| 2143 | */ | ||
| 2144 | if (Sgl_isinfinity_exponent(opnd2)) { | ||
| 2145 | if (Sgl_iszero_mantissa(opnd2)) { | ||
| 2146 | if (Sgl_isnotnan(opnd3)) { | ||
| 2147 | if (Sgl_iszero_exponentmantissa(opnd1)) { | ||
| 2148 | /* | ||
| 2149 | * invalid since multiply operands are | ||
| 2150 | * zero & infinity | ||
| 2151 | */ | ||
| 2152 | if (Is_invalidtrap_enabled()) | ||
| 2153 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 2154 | Set_invalidflag(); | ||
| 2155 | Sgl_makequietnan(opnd2); | ||
| 2156 | Sgl_copytoptr(opnd2,dstptr); | ||
| 2157 | return(NOEXCEPTION); | ||
| 2158 | } | ||
| 2159 | |||
| 2160 | /* | ||
| 2161 | * Check third operand for infinity with a | ||
| 2162 | * sign opposite of the multiply result | ||
| 2163 | */ | ||
| 2164 | if (Sgl_isinfinity(opnd3) && | ||
| 2165 | (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) { | ||
| 2166 | /* | ||
| 2167 | * invalid since attempting a magnitude | ||
| 2168 | * subtraction of infinities | ||
| 2169 | */ | ||
| 2170 | if (Is_invalidtrap_enabled()) | ||
| 2171 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 2172 | Set_invalidflag(); | ||
| 2173 | Sgl_makequietnan(resultp1); | ||
| 2174 | Sgl_copytoptr(resultp1,dstptr); | ||
| 2175 | return(NOEXCEPTION); | ||
| 2176 | } | ||
| 2177 | |||
| 2178 | /* | ||
| 2179 | * return infinity | ||
| 2180 | */ | ||
| 2181 | Sgl_setinfinity_exponentmantissa(resultp1); | ||
| 2182 | Sgl_copytoptr(resultp1,dstptr); | ||
| 2183 | return(NOEXCEPTION); | ||
| 2184 | } | ||
| 2185 | } | ||
| 2186 | else { | ||
| 2187 | /* | ||
| 2188 | * is NaN; signaling or quiet? | ||
| 2189 | */ | ||
| 2190 | if (Sgl_isone_signaling(opnd2)) { | ||
| 2191 | /* trap if INVALIDTRAP enabled */ | ||
| 2192 | if (Is_invalidtrap_enabled()) | ||
| 2193 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 2194 | /* make NaN quiet */ | ||
| 2195 | Set_invalidflag(); | ||
| 2196 | Sgl_set_quiet(opnd2); | ||
| 2197 | } | ||
| 2198 | /* | ||
| 2199 | * is third operand a signaling NaN? | ||
| 2200 | */ | ||
| 2201 | else if (Sgl_is_signalingnan(opnd3)) { | ||
| 2202 | /* trap if INVALIDTRAP enabled */ | ||
| 2203 | if (Is_invalidtrap_enabled()) | ||
| 2204 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 2205 | /* make NaN quiet */ | ||
| 2206 | Set_invalidflag(); | ||
| 2207 | Sgl_set_quiet(opnd3); | ||
| 2208 | Sgl_copytoptr(opnd3,dstptr); | ||
| 2209 | return(NOEXCEPTION); | ||
| 2210 | } | ||
| 2211 | /* | ||
| 2212 | * return quiet NaN | ||
| 2213 | */ | ||
| 2214 | Sgl_copytoptr(opnd2,dstptr); | ||
| 2215 | return(NOEXCEPTION); | ||
| 2216 | } | ||
| 2217 | } | ||
| 2218 | |||
| 2219 | /* | ||
| 2220 | * check third operand for NaN's or infinity | ||
| 2221 | */ | ||
| 2222 | if (Sgl_isinfinity_exponent(opnd3)) { | ||
| 2223 | if (Sgl_iszero_mantissa(opnd3)) { | ||
| 2224 | /* return infinity */ | ||
| 2225 | Sgl_copytoptr(opnd3,dstptr); | ||
| 2226 | return(NOEXCEPTION); | ||
| 2227 | } else { | ||
| 2228 | /* | ||
| 2229 | * is NaN; signaling or quiet? | ||
| 2230 | */ | ||
| 2231 | if (Sgl_isone_signaling(opnd3)) { | ||
| 2232 | /* trap if INVALIDTRAP enabled */ | ||
| 2233 | if (Is_invalidtrap_enabled()) | ||
| 2234 | return(OPC_2E_INVALIDEXCEPTION); | ||
| 2235 | /* make NaN quiet */ | ||
| 2236 | Set_invalidflag(); | ||
| 2237 | Sgl_set_quiet(opnd3); | ||
| 2238 | } | ||
| 2239 | /* | ||
| 2240 | * return quiet NaN | ||
| 2241 | */ | ||
| 2242 | Sgl_copytoptr(opnd3,dstptr); | ||
| 2243 | return(NOEXCEPTION); | ||
| 2244 | } | ||
| 2245 | } | ||
| 2246 | |||
| 2247 | /* | ||
| 2248 | * Generate multiply mantissa | ||
| 2249 | */ | ||
| 2250 | if (Sgl_isnotzero_exponent(opnd1)) { | ||
| 2251 | /* set hidden bit */ | ||
| 2252 | Sgl_clear_signexponent_set_hidden(opnd1); | ||
| 2253 | } | ||
| 2254 | else { | ||
| 2255 | /* check for zero */ | ||
| 2256 | if (Sgl_iszero_mantissa(opnd1)) { | ||
| 2257 | /* | ||
| 2258 | * Perform the add opnd3 with zero here. | ||
| 2259 | */ | ||
| 2260 | if (Sgl_iszero_exponentmantissa(opnd3)) { | ||
| 2261 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
| 2262 | Sgl_or_signs(opnd3,resultp1); | ||
| 2263 | } else { | ||
| 2264 | Sgl_and_signs(opnd3,resultp1); | ||
| 2265 | } | ||
| 2266 | } | ||
| 2267 | /* | ||
| 2268 | * Now let's check for trapped underflow case. | ||
| 2269 | */ | ||
| 2270 | else if (Sgl_iszero_exponent(opnd3) && | ||
| 2271 | Is_underflowtrap_enabled()) { | ||
| 2272 | /* need to normalize results mantissa */ | ||
| 2273 | sign_save = Sgl_signextendedsign(opnd3); | ||
| 2274 | result_exponent = 0; | ||
| 2275 | Sgl_leftshiftby1(opnd3); | ||
| 2276 | Sgl_normalize(opnd3,result_exponent); | ||
| 2277 | Sgl_set_sign(opnd3,/*using*/sign_save); | ||
| 2278 | Sgl_setwrapped_exponent(opnd3,result_exponent, | ||
| 2279 | unfl); | ||
| 2280 | Sgl_copytoptr(opnd3,dstptr); | ||
| 2281 | /* inexact = FALSE */ | ||
| 2282 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
| 2283 | } | ||
| 2284 | Sgl_copytoptr(opnd3,dstptr); | ||
| 2285 | return(NOEXCEPTION); | ||
| 2286 | } | ||
| 2287 | /* is denormalized, adjust exponent */ | ||
| 2288 | Sgl_clear_signexponent(opnd1); | ||
| 2289 | Sgl_leftshiftby1(opnd1); | ||
| 2290 | Sgl_normalize(opnd1,mpy_exponent); | ||
| 2291 | } | ||
| 2292 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
| 2293 | if (Sgl_isnotzero_exponent(opnd2)) { | ||
| 2294 | Sgl_clear_signexponent_set_hidden(opnd2); | ||
| 2295 | } | ||
| 2296 | else { | ||
| 2297 | /* check for zero */ | ||
| 2298 | if (Sgl_iszero_mantissa(opnd2)) { | ||
| 2299 | /* | ||
| 2300 | * Perform the add opnd3 with zero here. | ||
| 2301 | */ | ||
| 2302 | if (Sgl_iszero_exponentmantissa(opnd3)) { | ||
| 2303 | if (Is_rounding_mode(ROUNDMINUS)) { | ||
| 2304 | Sgl_or_signs(opnd3,resultp1); | ||
| 2305 | } else { | ||
| 2306 | Sgl_and_signs(opnd3,resultp1); | ||
| 2307 | } | ||
| 2308 | } | ||
| 2309 | /* | ||
| 2310 | * Now let's check for trapped underflow case. | ||
| 2311 | */ | ||
| 2312 | else if (Sgl_iszero_exponent(opnd3) && | ||
| 2313 | Is_underflowtrap_enabled()) { | ||
| 2314 | /* need to normalize results mantissa */ | ||
| 2315 | sign_save = Sgl_signextendedsign(opnd3); | ||
| 2316 | result_exponent = 0; | ||
| 2317 | Sgl_leftshiftby1(opnd3); | ||
| 2318 | Sgl_normalize(opnd3,result_exponent); | ||
| 2319 | Sgl_set_sign(opnd3,/*using*/sign_save); | ||
| 2320 | Sgl_setwrapped_exponent(opnd3,result_exponent, | ||
| 2321 | unfl); | ||
| 2322 | Sgl_copytoptr(opnd3,dstptr); | ||
| 2323 | /* inexact = FALSE */ | ||
| 2324 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
| 2325 | } | ||
| 2326 | Sgl_copytoptr(opnd3,dstptr); | ||
| 2327 | return(NOEXCEPTION); | ||
| 2328 | } | ||
| 2329 | /* is denormalized; want to normalize */ | ||
| 2330 | Sgl_clear_signexponent(opnd2); | ||
| 2331 | Sgl_leftshiftby1(opnd2); | ||
| 2332 | Sgl_normalize(opnd2,mpy_exponent); | ||
| 2333 | } | ||
| 2334 | |||
| 2335 | /* Multiply the first two source mantissas together */ | ||
| 2336 | |||
| 2337 | /* | ||
| 2338 | * The intermediate result will be kept in tmpres, | ||
| 2339 | * which needs enough room for 106 bits of mantissa, | ||
| 2340 | * so lets call it a Double extended. | ||
| 2341 | */ | ||
| 2342 | Sglext_setzero(tmpresp1,tmpresp2); | ||
| 2343 | |||
| 2344 | /* | ||
| 2345 | * Four bits at a time are inspected in each loop, and a | ||
| 2346 | * simple shift and add multiply algorithm is used. | ||
| 2347 | */ | ||
| 2348 | for (count = SGL_P-1; count >= 0; count -= 4) { | ||
| 2349 | Sglext_rightshiftby4(tmpresp1,tmpresp2); | ||
| 2350 | if (Sbit28(opnd1)) { | ||
| 2351 | /* Twoword_add should be an ADD followed by 2 ADDC's */ | ||
| 2352 | Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0); | ||
| 2353 | } | ||
| 2354 | if (Sbit29(opnd1)) { | ||
| 2355 | Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0); | ||
| 2356 | } | ||
| 2357 | if (Sbit30(opnd1)) { | ||
| 2358 | Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0); | ||
| 2359 | } | ||
| 2360 | if (Sbit31(opnd1)) { | ||
| 2361 | Twoword_add(tmpresp1, tmpresp2, opnd2, 0); | ||
| 2362 | } | ||
| 2363 | Sgl_rightshiftby4(opnd1); | ||
| 2364 | } | ||
| 2365 | if (Is_sexthiddenoverflow(tmpresp1)) { | ||
| 2366 | /* result mantissa >= 2 (mantissa overflow) */ | ||
| 2367 | mpy_exponent++; | ||
| 2368 | Sglext_rightshiftby4(tmpresp1,tmpresp2); | ||
| 2369 | } else { | ||
| 2370 | Sglext_rightshiftby3(tmpresp1,tmpresp2); | ||
| 2371 | } | ||
| 2372 | |||
| 2373 | /* | ||
| 2374 | * Restore the sign of the mpy result which was saved in resultp1. | ||
| 2375 | * The exponent will continue to be kept in mpy_exponent. | ||
| 2376 | */ | ||
| 2377 | Sglext_set_sign(tmpresp1,Sgl_sign(resultp1)); | ||
| 2378 | |||
| 2379 | /* | ||
| 2380 | * No rounding is required, since the result of the multiply | ||
| 2381 | * is exact in the extended format. | ||
| 2382 | */ | ||
| 2383 | |||
| 2384 | /* | ||
| 2385 | * Now we are ready to perform the add portion of the operation. | ||
| 2386 | * | ||
| 2387 | * The exponents need to be kept as integers for now, since the | ||
| 2388 | * multiply result might not fit into the exponent field. We | ||
| 2389 | * can't overflow or underflow because of this yet, since the | ||
| 2390 | * add could bring the final result back into range. | ||
| 2391 | */ | ||
| 2392 | add_exponent = Sgl_exponent(opnd3); | ||
| 2393 | |||
| 2394 | /* | ||
| 2395 | * Check for denormalized or zero add operand. | ||
| 2396 | */ | ||
| 2397 | if (add_exponent == 0) { | ||
| 2398 | /* check for zero */ | ||
| 2399 | if (Sgl_iszero_mantissa(opnd3)) { | ||
| 2400 | /* right is zero */ | ||
| 2401 | /* Left can't be zero and must be result. | ||
| 2402 | * | ||
| 2403 | * The final result is now in tmpres and mpy_exponent, | ||
| 2404 | * and needs to be rounded and squeezed back into | ||
| 2405 | * double precision format from double extended. | ||
| 2406 | */ | ||
| 2407 | result_exponent = mpy_exponent; | ||
| 2408 | Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2); | ||
| 2409 | sign_save = Sgl_signextendedsign(resultp1);/*save sign*/ | ||
| 2410 | goto round; | ||
| 2411 | } | ||
| 2412 | |||
| 2413 | /* | ||
| 2414 | * Neither are zeroes. | ||
| 2415 | * Adjust exponent and normalize add operand. | ||
| 2416 | */ | ||
| 2417 | sign_save = Sgl_signextendedsign(opnd3); /* save sign */ | ||
| 2418 | Sgl_clear_signexponent(opnd3); | ||
| 2419 | Sgl_leftshiftby1(opnd3); | ||
| 2420 | Sgl_normalize(opnd3,add_exponent); | ||
| 2421 | Sgl_set_sign(opnd3,sign_save); /* restore sign */ | ||
| 2422 | } else { | ||
| 2423 | Sgl_clear_exponent_set_hidden(opnd3); | ||
| 2424 | } | ||
| 2425 | /* | ||
| 2426 | * Copy opnd3 to the double extended variable called right. | ||
| 2427 | */ | ||
| 2428 | Sgl_copyto_sglext(opnd3,rightp1,rightp2); | ||
| 2429 | |||
| 2430 | /* | ||
| 2431 | * A zero "save" helps discover equal operands (for later), | ||
| 2432 | * and is used in swapping operands (if needed). | ||
| 2433 | */ | ||
| 2434 | Sglext_xortointp1(tmpresp1,rightp1,/*to*/save); | ||
| 2435 | |||
| 2436 | /* | ||
| 2437 | * Compare magnitude of operands. | ||
| 2438 | */ | ||
| 2439 | Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1); | ||
| 2440 | Sglext_copytoint_exponentmantissa(rightp1,signlessright1); | ||
| 2441 | if (mpy_exponent < add_exponent || mpy_exponent == add_exponent && | ||
| 2442 | Sglext_ismagnitudeless(signlessleft1,signlessright1)) { | ||
| 2443 | /* | ||
| 2444 | * Set the left operand to the larger one by XOR swap. | ||
| 2445 | * First finish the first word "save". | ||
| 2446 | */ | ||
| 2447 | Sglext_xorfromintp1(save,rightp1,/*to*/rightp1); | ||
| 2448 | Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1); | ||
| 2449 | Sglext_swap_lower(tmpresp2,rightp2); | ||
| 2450 | /* also setup exponents used in rest of routine */ | ||
| 2451 | diff_exponent = add_exponent - mpy_exponent; | ||
| 2452 | result_exponent = add_exponent; | ||
| 2453 | } else { | ||
| 2454 | /* also setup exponents used in rest of routine */ | ||
| 2455 | diff_exponent = mpy_exponent - add_exponent; | ||
| 2456 | result_exponent = mpy_exponent; | ||
| 2457 | } | ||
| 2458 | /* Invariant: left is not smaller than right. */ | ||
| 2459 | |||
| 2460 | /* | ||
| 2461 | * Special case alignment of operands that would force alignment | ||
| 2462 | * beyond the extent of the extension. A further optimization | ||
| 2463 | * could special case this but only reduces the path length for | ||
| 2464 | * this infrequent case. | ||
| 2465 | */ | ||
| 2466 | if (diff_exponent > SGLEXT_THRESHOLD) { | ||
| 2467 | diff_exponent = SGLEXT_THRESHOLD; | ||
| 2468 | } | ||
| 2469 | |||
| 2470 | /* Align right operand by shifting it to the right */ | ||
| 2471 | Sglext_clear_sign(rightp1); | ||
| 2472 | Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent); | ||
| 2473 | |||
| 2474 | /* Treat sum and difference of the operands separately. */ | ||
| 2475 | if ((int)save < 0) { | ||
| 2476 | /* | ||
| 2477 | * Difference of the two operands. Overflow can occur if the | ||
| 2478 | * multiply overflowed. A borrow can occur out of the hidden | ||
| 2479 | * bit and force a post normalization phase. | ||
| 2480 | */ | ||
| 2481 | Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2, | ||
| 2482 | resultp1,resultp2); | ||
| 2483 | sign_save = Sgl_signextendedsign(resultp1); | ||
| 2484 | if (Sgl_iszero_hidden(resultp1)) { | ||
| 2485 | /* Handle normalization */ | ||
| 2486 | /* A straight foward algorithm would now shift the | ||
| 2487 | * result and extension left until the hidden bit | ||
| 2488 | * becomes one. Not all of the extension bits need | ||
| 2489 | * participate in the shift. Only the two most | ||
| 2490 | * significant bits (round and guard) are needed. | ||
| 2491 | * If only a single shift is needed then the guard | ||
| 2492 | * bit becomes a significant low order bit and the | ||
| 2493 | * extension must participate in the rounding. | ||
| 2494 | * If more than a single shift is needed, then all | ||
| 2495 | * bits to the right of the guard bit are zeros, | ||
| 2496 | * and the guard bit may or may not be zero. */ | ||
| 2497 | Sglext_leftshiftby1(resultp1,resultp2); | ||
| 2498 | |||
| 2499 | /* Need to check for a zero result. The sign and | ||
| 2500 | * exponent fields have already been zeroed. The more | ||
| 2501 | * efficient test of the full object can be used. | ||
| 2502 | */ | ||
| 2503 | if (Sglext_iszero(resultp1,resultp2)) { | ||
| 2504 | /* Must have been "x-x" or "x+(-x)". */ | ||
| 2505 | if (Is_rounding_mode(ROUNDMINUS)) | ||
| 2506 | Sgl_setone_sign(resultp1); | ||
| 2507 | Sgl_copytoptr(resultp1,dstptr); | ||
| 2508 | return(NOEXCEPTION); | ||
| 2509 | } | ||
| 2510 | result_exponent--; | ||
| 2511 | |||
| 2512 | /* Look to see if normalization is finished. */ | ||
| 2513 | if (Sgl_isone_hidden(resultp1)) { | ||
| 2514 | /* No further normalization is needed */ | ||
| 2515 | goto round; | ||
| 2516 | } | ||
| 2517 | |||
| 2518 | /* Discover first one bit to determine shift amount. | ||
| 2519 | * Use a modified binary search. We have already | ||
| 2520 | * shifted the result one position right and still | ||
| 2521 | * not found a one so the remainder of the extension | ||
| 2522 | * must be zero and simplifies rounding. */ | ||
| 2523 | /* Scan bytes */ | ||
| 2524 | while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) { | ||
| 2525 | Sglext_leftshiftby8(resultp1,resultp2); | ||
| 2526 | result_exponent -= 8; | ||
| 2527 | } | ||
| 2528 | /* Now narrow it down to the nibble */ | ||
| 2529 | if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) { | ||
| 2530 | /* The lower nibble contains the | ||
| 2531 | * normalizing one */ | ||
| 2532 | Sglext_leftshiftby4(resultp1,resultp2); | ||
| 2533 | result_exponent -= 4; | ||
| 2534 | } | ||
| 2535 | /* Select case where first bit is set (already | ||
| 2536 | * normalized) otherwise select the proper shift. */ | ||
| 2537 | jumpsize = Sgl_hiddenhigh3mantissa(resultp1); | ||
| 2538 | if (jumpsize <= 7) switch(jumpsize) { | ||
| 2539 | case 1: | ||
| 2540 | Sglext_leftshiftby3(resultp1,resultp2); | ||
| 2541 | result_exponent -= 3; | ||
| 2542 | break; | ||
| 2543 | case 2: | ||
| 2544 | case 3: | ||
| 2545 | Sglext_leftshiftby2(resultp1,resultp2); | ||
| 2546 | result_exponent -= 2; | ||
| 2547 | break; | ||
| 2548 | case 4: | ||
| 2549 | case 5: | ||
| 2550 | case 6: | ||
| 2551 | case 7: | ||
| 2552 | Sglext_leftshiftby1(resultp1,resultp2); | ||
| 2553 | result_exponent -= 1; | ||
| 2554 | break; | ||
| 2555 | } | ||
| 2556 | } /* end if (hidden...)... */ | ||
| 2557 | /* Fall through and round */ | ||
| 2558 | } /* end if (save < 0)... */ | ||
| 2559 | else { | ||
| 2560 | /* Add magnitudes */ | ||
| 2561 | Sglext_addition(tmpresp1,tmpresp2, | ||
| 2562 | rightp1,rightp2, /*to*/resultp1,resultp2); | ||
| 2563 | sign_save = Sgl_signextendedsign(resultp1); | ||
| 2564 | if (Sgl_isone_hiddenoverflow(resultp1)) { | ||
| 2565 | /* Prenormalization required. */ | ||
| 2566 | Sglext_arithrightshiftby1(resultp1,resultp2); | ||
| 2567 | result_exponent++; | ||
| 2568 | } /* end if hiddenoverflow... */ | ||
| 2569 | } /* end else ...add magnitudes... */ | ||
| 2570 | |||
| 2571 | /* Round the result. If the extension and lower two words are | ||
| 2572 | * all zeros, then the result is exact. Otherwise round in the | ||
| 2573 | * correct direction. Underflow is possible. If a postnormalization | ||
| 2574 | * is necessary, then the mantissa is all zeros so no shift is needed. | ||
| 2575 | */ | ||
| 2576 | round: | ||
| 2577 | if (result_exponent <= 0 && !Is_underflowtrap_enabled()) { | ||
| 2578 | Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny); | ||
| 2579 | } | ||
| 2580 | Sgl_set_sign(resultp1,/*using*/sign_save); | ||
| 2581 | if (Sglext_isnotzero_mantissap2(resultp2)) { | ||
| 2582 | inexact = TRUE; | ||
| 2583 | switch(Rounding_mode()) { | ||
| 2584 | case ROUNDNEAREST: /* The default. */ | ||
| 2585 | if (Sglext_isone_highp2(resultp2)) { | ||
| 2586 | /* at least 1/2 ulp */ | ||
| 2587 | if (Sglext_isnotzero_low31p2(resultp2) || | ||
| 2588 | Sglext_isone_lowp1(resultp1)) { | ||
| 2589 | /* either exactly half way and odd or | ||
| 2590 | * more than 1/2ulp */ | ||
| 2591 | Sgl_increment(resultp1); | ||
| 2592 | } | ||
| 2593 | } | ||
| 2594 | break; | ||
| 2595 | |||
| 2596 | case ROUNDPLUS: | ||
| 2597 | if (Sgl_iszero_sign(resultp1)) { | ||
| 2598 | /* Round up positive results */ | ||
| 2599 | Sgl_increment(resultp1); | ||
| 2600 | } | ||
| 2601 | break; | ||
| 2602 | |||
| 2603 | case ROUNDMINUS: | ||
| 2604 | if (Sgl_isone_sign(resultp1)) { | ||
| 2605 | /* Round down negative results */ | ||
| 2606 | Sgl_increment(resultp1); | ||
| 2607 | } | ||
| 2608 | |||
| 2609 | case ROUNDZERO:; | ||
| 2610 | /* truncate is simple */ | ||
| 2611 | } /* end switch... */ | ||
| 2612 | if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++; | ||
| 2613 | } | ||
| 2614 | if (result_exponent >= SGL_INFINITY_EXPONENT) { | ||
| 2615 | /* Overflow */ | ||
| 2616 | if (Is_overflowtrap_enabled()) { | ||
| 2617 | /* | ||
| 2618 | * Adjust bias of result | ||
| 2619 | */ | ||
| 2620 | Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl); | ||
| 2621 | Sgl_copytoptr(resultp1,dstptr); | ||
| 2622 | if (inexact) | ||
| 2623 | if (Is_inexacttrap_enabled()) | ||
| 2624 | return (OPC_2E_OVERFLOWEXCEPTION | | ||
| 2625 | OPC_2E_INEXACTEXCEPTION); | ||
| 2626 | else Set_inexactflag(); | ||
| 2627 | return (OPC_2E_OVERFLOWEXCEPTION); | ||
| 2628 | } | ||
| 2629 | inexact = TRUE; | ||
| 2630 | Set_overflowflag(); | ||
| 2631 | Sgl_setoverflow(resultp1); | ||
| 2632 | } else if (result_exponent <= 0) { /* underflow case */ | ||
| 2633 | if (Is_underflowtrap_enabled()) { | ||
| 2634 | /* | ||
| 2635 | * Adjust bias of result | ||
| 2636 | */ | ||
| 2637 | Sgl_setwrapped_exponent(resultp1,result_exponent,unfl); | ||
| 2638 | Sgl_copytoptr(resultp1,dstptr); | ||
| 2639 | if (inexact) | ||
| 2640 | if (Is_inexacttrap_enabled()) | ||
| 2641 | return (OPC_2E_UNDERFLOWEXCEPTION | | ||
| 2642 | OPC_2E_INEXACTEXCEPTION); | ||
| 2643 | else Set_inexactflag(); | ||
| 2644 | return(OPC_2E_UNDERFLOWEXCEPTION); | ||
| 2645 | } | ||
| 2646 | else if (inexact && is_tiny) Set_underflowflag(); | ||
| 2647 | } | ||
| 2648 | else Sgl_set_exponent(resultp1,result_exponent); | ||
| 2649 | Sgl_copytoptr(resultp1,dstptr); | ||
| 2650 | if (inexact) | ||
| 2651 | if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION); | ||
| 2652 | else Set_inexactflag(); | ||
| 2653 | return(NOEXCEPTION); | ||
| 2654 | } | ||
| 2655 | |||
diff --git a/arch/parisc/math-emu/fpbits.h b/arch/parisc/math-emu/fpbits.h new file mode 100644 index 000000000000..cefad064d74a --- /dev/null +++ b/arch/parisc/math-emu/fpbits.h | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifdef __NO_PA_HDRS | ||
| 23 | PA header file -- do not include this header file for non-PA builds. | ||
| 24 | #endif | ||
| 25 | |||
| 26 | |||
| 27 | /* | ||
| 28 | * These macros are designed to be portable to all machines that have | ||
| 29 | * a wordsize greater than or equal to 32 bits that support the portable | ||
| 30 | * C compiler and the standard C preprocessor. Wordsize (default 32) | ||
| 31 | * and bitfield assignment (default left-to-right, unlike VAX, PDP-11) | ||
| 32 | * should be predefined using the constants HOSTWDSZ and BITFRL and | ||
| 33 | * the C compiler "-D" flag (e.g., -DHOSTWDSZ=36 -DBITFLR for the DEC-20). | ||
| 34 | * Note that the macro arguments assume that the integer being referenced | ||
| 35 | * is a 32-bit integer (right-justified on the 20) and that bit 0 is the | ||
| 36 | * most significant bit. | ||
| 37 | */ | ||
| 38 | |||
| 39 | #ifndef HOSTWDSZ | ||
| 40 | #define HOSTWDSZ 32 | ||
| 41 | #endif | ||
| 42 | |||
| 43 | |||
| 44 | /*########################### Macros ######################################*/ | ||
| 45 | |||
| 46 | /*------------------------------------------------------------------------- | ||
| 47 | * NewDeclareBitField_Reference - Declare a structure similar to the simulator | ||
| 48 | * function "DeclBitfR" except its use is restricted to occur within a larger | ||
| 49 | * enclosing structure or union definition. This declaration is an unnamed | ||
| 50 | * structure with the argument, name, as the member name and the argument, | ||
| 51 | * uname, as the element name. | ||
| 52 | *----------------------------------------------------------------------- */ | ||
| 53 | #define Bitfield_extract(start, length, object) \ | ||
| 54 | ((object) >> (HOSTWDSZ - (start) - (length)) & \ | ||
| 55 | ((unsigned)-1 >> (HOSTWDSZ - (length)))) | ||
| 56 | |||
| 57 | #define Bitfield_signed_extract(start, length, object) \ | ||
| 58 | ((int)((object) << start) >> (HOSTWDSZ - (length))) | ||
| 59 | |||
| 60 | #define Bitfield_mask(start, len, object) \ | ||
| 61 | ((object) & (((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len))) | ||
| 62 | |||
| 63 | #define Bitfield_deposit(value,start,len,object) object = \ | ||
| 64 | ((object) & ~(((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len))) | \ | ||
| 65 | (((value) & ((unsigned)-1 >> (HOSTWDSZ-len))) << (HOSTWDSZ-start-len)) | ||
diff --git a/arch/parisc/math-emu/fpu.h b/arch/parisc/math-emu/fpu.h new file mode 100644 index 000000000000..0af5c3c88949 --- /dev/null +++ b/arch/parisc/math-emu/fpu.h | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/fp/fpu.h $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * <<please update with a synopis of the functionality provided by this file>> | ||
| 29 | * | ||
| 30 | * | ||
| 31 | * END_DESC | ||
| 32 | */ | ||
| 33 | |||
| 34 | #ifdef __NO_PA_HDRS | ||
| 35 | PA header file -- do not include this header file for non-PA builds. | ||
| 36 | #endif | ||
| 37 | |||
| 38 | |||
| 39 | #ifndef _MACHINE_FPU_INCLUDED /* allows multiple inclusion */ | ||
| 40 | #define _MACHINE_FPU_INCLUDED | ||
| 41 | |||
| 42 | #if 0 | ||
| 43 | #ifndef _SYS_STDSYMS_INCLUDED | ||
| 44 | # include <sys/stdsyms.h> | ||
| 45 | #endif /* _SYS_STDSYMS_INCLUDED */ | ||
| 46 | #include <machine/pdc/pdc_rqsts.h> | ||
| 47 | #endif | ||
| 48 | |||
| 49 | #define PA83_FPU_FLAG 0x00000001 | ||
| 50 | #define PA89_FPU_FLAG 0x00000002 | ||
| 51 | #define PA2_0_FPU_FLAG 0x00000010 | ||
| 52 | |||
| 53 | #define TIMEX_EXTEN_FLAG 0x00000004 | ||
| 54 | |||
| 55 | #define ROLEX_EXTEN_FLAG 0x00000008 | ||
| 56 | #define COPR_FP 0x00000080 /* Floating point -- Coprocessor 0 */ | ||
| 57 | #define SFU_MPY_DIVIDE 0x00008000 /* Multiply/Divide __ SFU 0 */ | ||
| 58 | |||
| 59 | |||
| 60 | #define EM_FPU_TYPE_OFFSET 272 | ||
| 61 | |||
| 62 | /* version of EMULATION software for COPR,0,0 instruction */ | ||
| 63 | #define EMULATION_VERSION 4 | ||
| 64 | |||
| 65 | /* | ||
| 66 | * The only was to differeniate between TIMEX and ROLEX (or PCX-S and PCX-T) | ||
| 67 | * is thorough the potential type field from the PDC_MODEL call. The | ||
| 68 | * following flags are used at assist this differeniation. | ||
| 69 | */ | ||
| 70 | |||
| 71 | #define ROLEX_POTENTIAL_KEY_FLAGS PDC_MODEL_CPU_KEY_WORD_TO_IO | ||
| 72 | #define TIMEX_POTENTIAL_KEY_FLAGS (PDC_MODEL_CPU_KEY_QUAD_STORE | \ | ||
| 73 | PDC_MODEL_CPU_KEY_RECIP_SQRT) | ||
| 74 | |||
| 75 | |||
| 76 | #endif /* ! _MACHINE_FPU_INCLUDED */ | ||
diff --git a/arch/parisc/math-emu/fpudispatch.c b/arch/parisc/math-emu/fpudispatch.c new file mode 100644 index 000000000000..6e28f9f4c620 --- /dev/null +++ b/arch/parisc/math-emu/fpudispatch.c | |||
| @@ -0,0 +1,1442 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/fp/fpudispatch.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * <<please update with a synopsis of the functionality provided by this file>> | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * <<the following list was autogenerated, please review>> | ||
| 32 | * emfpudispatch(ir, dummy1, dummy2, fpregs) | ||
| 33 | * fpudispatch(ir, excp_code, holder, fpregs) | ||
| 34 | * | ||
| 35 | * Internal Interfaces: | ||
| 36 | * <<the following list was autogenerated, please review>> | ||
| 37 | * static u_int decode_06(u_int, u_int *) | ||
| 38 | * static u_int decode_0c(u_int, u_int, u_int, u_int *) | ||
| 39 | * static u_int decode_0e(u_int, u_int, u_int, u_int *) | ||
| 40 | * static u_int decode_26(u_int, u_int *) | ||
| 41 | * static u_int decode_2e(u_int, u_int *) | ||
| 42 | * static void update_status_cbit(u_int *, u_int, u_int, u_int) | ||
| 43 | * | ||
| 44 | * Theory: | ||
| 45 | * <<please update with a overview of the operation of this file>> | ||
| 46 | * | ||
| 47 | * END_DESC | ||
| 48 | */ | ||
| 49 | |||
| 50 | #define FPUDEBUG 0 | ||
| 51 | |||
| 52 | #include "float.h" | ||
| 53 | #include <linux/kernel.h> | ||
| 54 | #include <asm/processor.h> | ||
| 55 | /* #include <sys/debug.h> */ | ||
| 56 | /* #include <machine/sys/mdep_private.h> */ | ||
| 57 | |||
| 58 | #define COPR_INST 0x30000000 | ||
| 59 | |||
| 60 | /* | ||
| 61 | * definition of extru macro. If pos and len are constants, the compiler | ||
| 62 | * will generate an extru instruction when optimized | ||
| 63 | */ | ||
| 64 | #define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1)) | ||
| 65 | /* definitions of bit field locations in the instruction */ | ||
| 66 | #define fpmajorpos 5 | ||
| 67 | #define fpr1pos 10 | ||
| 68 | #define fpr2pos 15 | ||
| 69 | #define fptpos 31 | ||
| 70 | #define fpsubpos 18 | ||
| 71 | #define fpclass1subpos 16 | ||
| 72 | #define fpclasspos 22 | ||
| 73 | #define fpfmtpos 20 | ||
| 74 | #define fpdfpos 18 | ||
| 75 | #define fpnulpos 26 | ||
| 76 | /* | ||
| 77 | * the following are the extra bits for the 0E major op | ||
| 78 | */ | ||
| 79 | #define fpxr1pos 24 | ||
| 80 | #define fpxr2pos 19 | ||
| 81 | #define fpxtpos 25 | ||
| 82 | #define fpxpos 23 | ||
| 83 | #define fp0efmtpos 20 | ||
| 84 | /* | ||
| 85 | * the following are for the multi-ops | ||
| 86 | */ | ||
| 87 | #define fprm1pos 10 | ||
| 88 | #define fprm2pos 15 | ||
| 89 | #define fptmpos 31 | ||
| 90 | #define fprapos 25 | ||
| 91 | #define fptapos 20 | ||
| 92 | #define fpmultifmt 26 | ||
| 93 | /* | ||
| 94 | * the following are for the fused FP instructions | ||
| 95 | */ | ||
| 96 | /* fprm1pos 10 */ | ||
| 97 | /* fprm2pos 15 */ | ||
| 98 | #define fpraupos 18 | ||
| 99 | #define fpxrm2pos 19 | ||
| 100 | /* fpfmtpos 20 */ | ||
| 101 | #define fpralpos 23 | ||
| 102 | #define fpxrm1pos 24 | ||
| 103 | /* fpxtpos 25 */ | ||
| 104 | #define fpfusedsubop 26 | ||
| 105 | /* fptpos 31 */ | ||
| 106 | |||
| 107 | /* | ||
| 108 | * offset to constant zero in the FP emulation registers | ||
| 109 | */ | ||
| 110 | #define fpzeroreg (32*sizeof(double)/sizeof(u_int)) | ||
| 111 | |||
| 112 | /* | ||
| 113 | * extract the major opcode from the instruction | ||
| 114 | */ | ||
| 115 | #define get_major(op) extru(op,fpmajorpos,6) | ||
| 116 | /* | ||
| 117 | * extract the two bit class field from the FP instruction. The class is at bit | ||
| 118 | * positions 21-22 | ||
| 119 | */ | ||
| 120 | #define get_class(op) extru(op,fpclasspos,2) | ||
| 121 | /* | ||
| 122 | * extract the 3 bit subop field. For all but class 1 instructions, it is | ||
| 123 | * located at bit positions 16-18 | ||
| 124 | */ | ||
| 125 | #define get_subop(op) extru(op,fpsubpos,3) | ||
| 126 | /* | ||
| 127 | * extract the 2 or 3 bit subop field from class 1 instructions. It is located | ||
| 128 | * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0) | ||
| 129 | */ | ||
| 130 | #define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2) /* PA89 (1.1) fmt */ | ||
| 131 | #define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3) /* PA 2.0 fmt */ | ||
| 132 | |||
| 133 | /* definitions of unimplemented exceptions */ | ||
| 134 | #define MAJOR_0C_EXCP 0x09 | ||
| 135 | #define MAJOR_0E_EXCP 0x0b | ||
| 136 | #define MAJOR_06_EXCP 0x03 | ||
| 137 | #define MAJOR_26_EXCP 0x23 | ||
| 138 | #define MAJOR_2E_EXCP 0x2b | ||
| 139 | #define PA83_UNIMP_EXCP 0x01 | ||
| 140 | |||
| 141 | /* | ||
| 142 | * Special Defines for TIMEX specific code | ||
| 143 | */ | ||
| 144 | |||
| 145 | #define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2) | ||
| 146 | #define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG) | ||
| 147 | |||
| 148 | /* | ||
| 149 | * Static function definitions | ||
| 150 | */ | ||
| 151 | #define _PROTOTYPES | ||
| 152 | #if defined(_PROTOTYPES) || defined(_lint) | ||
| 153 | static u_int decode_0c(u_int, u_int, u_int, u_int *); | ||
| 154 | static u_int decode_0e(u_int, u_int, u_int, u_int *); | ||
| 155 | static u_int decode_06(u_int, u_int *); | ||
| 156 | static u_int decode_26(u_int, u_int *); | ||
| 157 | static u_int decode_2e(u_int, u_int *); | ||
| 158 | static void update_status_cbit(u_int *, u_int, u_int, u_int); | ||
| 159 | #else /* !_PROTOTYPES&&!_lint */ | ||
| 160 | static u_int decode_0c(); | ||
| 161 | static u_int decode_0e(); | ||
| 162 | static u_int decode_06(); | ||
| 163 | static u_int decode_26(); | ||
| 164 | static u_int decode_2e(); | ||
| 165 | static void update_status_cbit(); | ||
| 166 | #endif /* _PROTOTYPES&&!_lint */ | ||
| 167 | |||
| 168 | #define VASSERT(x) | ||
| 169 | |||
| 170 | static void parisc_linux_get_fpu_type(u_int fpregs[]) | ||
| 171 | { | ||
| 172 | /* on pa-linux the fpu type is not filled in by the | ||
| 173 | * caller; it is constructed here | ||
| 174 | */ | ||
| 175 | if (boot_cpu_data.cpu_type == pcxs) | ||
| 176 | fpregs[FPU_TYPE_FLAG_POS] = TIMEX_EXTEN_FLAG; | ||
| 177 | else if (boot_cpu_data.cpu_type == pcxt || | ||
| 178 | boot_cpu_data.cpu_type == pcxt_) | ||
| 179 | fpregs[FPU_TYPE_FLAG_POS] = ROLEX_EXTEN_FLAG; | ||
| 180 | else if (boot_cpu_data.cpu_type >= pcxu) | ||
| 181 | fpregs[FPU_TYPE_FLAG_POS] = PA2_0_FPU_FLAG; | ||
| 182 | } | ||
| 183 | |||
| 184 | /* | ||
| 185 | * this routine will decode the excepting floating point instruction and | ||
| 186 | * call the approiate emulation routine. | ||
| 187 | * It is called by decode_fpu with the following parameters: | ||
| 188 | * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register) | ||
| 189 | * where current_ir is the instruction to be emulated, | ||
| 190 | * unimplemented_code is the exception_code that the hardware generated | ||
| 191 | * and &Fpu_register is the address of emulated FP reg 0. | ||
| 192 | */ | ||
| 193 | u_int | ||
| 194 | fpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[]) | ||
| 195 | { | ||
| 196 | u_int class, subop; | ||
| 197 | u_int fpu_type_flags; | ||
| 198 | |||
| 199 | /* All FP emulation code assumes that ints are 4-bytes in length */ | ||
| 200 | VASSERT(sizeof(int) == 4); | ||
| 201 | |||
| 202 | parisc_linux_get_fpu_type(fpregs); | ||
| 203 | |||
| 204 | fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ | ||
| 205 | |||
| 206 | class = get_class(ir); | ||
| 207 | if (class == 1) { | ||
| 208 | if (fpu_type_flags & PA2_0_FPU_FLAG) | ||
| 209 | subop = get_subop1_PA2_0(ir); | ||
| 210 | else | ||
| 211 | subop = get_subop1_PA1_1(ir); | ||
| 212 | } | ||
| 213 | else | ||
| 214 | subop = get_subop(ir); | ||
| 215 | |||
| 216 | if (FPUDEBUG) printk("class %d subop %d\n", class, subop); | ||
| 217 | |||
| 218 | switch (excp_code) { | ||
| 219 | case MAJOR_0C_EXCP: | ||
| 220 | case PA83_UNIMP_EXCP: | ||
| 221 | return(decode_0c(ir,class,subop,fpregs)); | ||
| 222 | case MAJOR_0E_EXCP: | ||
| 223 | return(decode_0e(ir,class,subop,fpregs)); | ||
| 224 | case MAJOR_06_EXCP: | ||
| 225 | return(decode_06(ir,fpregs)); | ||
| 226 | case MAJOR_26_EXCP: | ||
| 227 | return(decode_26(ir,fpregs)); | ||
| 228 | case MAJOR_2E_EXCP: | ||
| 229 | return(decode_2e(ir,fpregs)); | ||
| 230 | default: | ||
| 231 | /* "crashme Night Gallery painting nr 2. (asm_crash.s). | ||
| 232 | * This was fixed for multi-user kernels, but | ||
| 233 | * workstation kernels had a panic here. This allowed | ||
| 234 | * any arbitrary user to panic the kernel by executing | ||
| 235 | * setting the FP exception registers to strange values | ||
| 236 | * and generating an emulation trap. The emulation and | ||
| 237 | * exception code must never be able to panic the | ||
| 238 | * kernel. | ||
| 239 | */ | ||
| 240 | return(UNIMPLEMENTEDEXCEPTION); | ||
| 241 | } | ||
| 242 | } | ||
| 243 | |||
| 244 | /* | ||
| 245 | * this routine is called by $emulation_trap to emulate a coprocessor | ||
| 246 | * instruction if one doesn't exist | ||
| 247 | */ | ||
| 248 | u_int | ||
| 249 | emfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[]) | ||
| 250 | { | ||
| 251 | u_int class, subop, major; | ||
| 252 | u_int fpu_type_flags; | ||
| 253 | |||
| 254 | /* All FP emulation code assumes that ints are 4-bytes in length */ | ||
| 255 | VASSERT(sizeof(int) == 4); | ||
| 256 | |||
| 257 | fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ | ||
| 258 | |||
| 259 | major = get_major(ir); | ||
| 260 | class = get_class(ir); | ||
| 261 | if (class == 1) { | ||
| 262 | if (fpu_type_flags & PA2_0_FPU_FLAG) | ||
| 263 | subop = get_subop1_PA2_0(ir); | ||
| 264 | else | ||
| 265 | subop = get_subop1_PA1_1(ir); | ||
| 266 | } | ||
| 267 | else | ||
| 268 | subop = get_subop(ir); | ||
| 269 | switch (major) { | ||
| 270 | case 0x0C: | ||
| 271 | return(decode_0c(ir,class,subop,fpregs)); | ||
| 272 | case 0x0E: | ||
| 273 | return(decode_0e(ir,class,subop,fpregs)); | ||
| 274 | case 0x06: | ||
| 275 | return(decode_06(ir,fpregs)); | ||
| 276 | case 0x26: | ||
| 277 | return(decode_26(ir,fpregs)); | ||
| 278 | case 0x2E: | ||
| 279 | return(decode_2e(ir,fpregs)); | ||
| 280 | default: | ||
| 281 | return(PA83_UNIMP_EXCP); | ||
| 282 | } | ||
| 283 | } | ||
| 284 | |||
| 285 | |||
| 286 | static u_int | ||
| 287 | decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[]) | ||
| 288 | { | ||
| 289 | u_int r1,r2,t; /* operand register offsets */ | ||
| 290 | u_int fmt; /* also sf for class 1 conversions */ | ||
| 291 | u_int df; /* for class 1 conversions */ | ||
| 292 | u_int *status; | ||
| 293 | u_int retval, local_status; | ||
| 294 | u_int fpu_type_flags; | ||
| 295 | |||
| 296 | if (ir == COPR_INST) { | ||
| 297 | fpregs[0] = EMULATION_VERSION << 11; | ||
| 298 | return(NOEXCEPTION); | ||
| 299 | } | ||
| 300 | status = &fpregs[0]; /* fp status register */ | ||
| 301 | local_status = fpregs[0]; /* and local copy */ | ||
| 302 | r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int); | ||
| 303 | if (r1 == 0) /* map fr0 source to constant zero */ | ||
| 304 | r1 = fpzeroreg; | ||
| 305 | t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int); | ||
| 306 | if (t == 0 && class != 2) /* don't allow fr0 as a dest */ | ||
| 307 | return(MAJOR_0C_EXCP); | ||
| 308 | fmt = extru(ir,fpfmtpos,2); /* get fmt completer */ | ||
| 309 | |||
| 310 | switch (class) { | ||
| 311 | case 0: | ||
| 312 | switch (subop) { | ||
| 313 | case 0: /* COPR 0,0 emulated above*/ | ||
| 314 | case 1: | ||
| 315 | return(MAJOR_0C_EXCP); | ||
| 316 | case 2: /* FCPY */ | ||
| 317 | switch (fmt) { | ||
| 318 | case 2: /* illegal */ | ||
| 319 | return(MAJOR_0C_EXCP); | ||
| 320 | case 3: /* quad */ | ||
| 321 | t &= ~3; /* force to even reg #s */ | ||
| 322 | r1 &= ~3; | ||
| 323 | fpregs[t+3] = fpregs[r1+3]; | ||
| 324 | fpregs[t+2] = fpregs[r1+2]; | ||
| 325 | case 1: /* double */ | ||
| 326 | fpregs[t+1] = fpregs[r1+1]; | ||
| 327 | case 0: /* single */ | ||
| 328 | fpregs[t] = fpregs[r1]; | ||
| 329 | return(NOEXCEPTION); | ||
| 330 | } | ||
| 331 | case 3: /* FABS */ | ||
| 332 | switch (fmt) { | ||
| 333 | case 2: /* illegal */ | ||
| 334 | return(MAJOR_0C_EXCP); | ||
| 335 | case 3: /* quad */ | ||
| 336 | t &= ~3; /* force to even reg #s */ | ||
| 337 | r1 &= ~3; | ||
| 338 | fpregs[t+3] = fpregs[r1+3]; | ||
| 339 | fpregs[t+2] = fpregs[r1+2]; | ||
| 340 | case 1: /* double */ | ||
| 341 | fpregs[t+1] = fpregs[r1+1]; | ||
| 342 | case 0: /* single */ | ||
| 343 | /* copy and clear sign bit */ | ||
| 344 | fpregs[t] = fpregs[r1] & 0x7fffffff; | ||
| 345 | return(NOEXCEPTION); | ||
| 346 | } | ||
| 347 | case 6: /* FNEG */ | ||
| 348 | switch (fmt) { | ||
| 349 | case 2: /* illegal */ | ||
| 350 | return(MAJOR_0C_EXCP); | ||
| 351 | case 3: /* quad */ | ||
| 352 | t &= ~3; /* force to even reg #s */ | ||
| 353 | r1 &= ~3; | ||
| 354 | fpregs[t+3] = fpregs[r1+3]; | ||
| 355 | fpregs[t+2] = fpregs[r1+2]; | ||
| 356 | case 1: /* double */ | ||
| 357 | fpregs[t+1] = fpregs[r1+1]; | ||
| 358 | case 0: /* single */ | ||
| 359 | /* copy and invert sign bit */ | ||
| 360 | fpregs[t] = fpregs[r1] ^ 0x80000000; | ||
| 361 | return(NOEXCEPTION); | ||
| 362 | } | ||
| 363 | case 7: /* FNEGABS */ | ||
| 364 | switch (fmt) { | ||
| 365 | case 2: /* illegal */ | ||
| 366 | return(MAJOR_0C_EXCP); | ||
| 367 | case 3: /* quad */ | ||
| 368 | t &= ~3; /* force to even reg #s */ | ||
| 369 | r1 &= ~3; | ||
| 370 | fpregs[t+3] = fpregs[r1+3]; | ||
| 371 | fpregs[t+2] = fpregs[r1+2]; | ||
| 372 | case 1: /* double */ | ||
| 373 | fpregs[t+1] = fpregs[r1+1]; | ||
| 374 | case 0: /* single */ | ||
| 375 | /* copy and set sign bit */ | ||
| 376 | fpregs[t] = fpregs[r1] | 0x80000000; | ||
| 377 | return(NOEXCEPTION); | ||
| 378 | } | ||
| 379 | case 4: /* FSQRT */ | ||
| 380 | switch (fmt) { | ||
| 381 | case 0: | ||
| 382 | return(sgl_fsqrt(&fpregs[r1],0, | ||
| 383 | &fpregs[t],status)); | ||
| 384 | case 1: | ||
| 385 | return(dbl_fsqrt(&fpregs[r1],0, | ||
| 386 | &fpregs[t],status)); | ||
| 387 | case 2: | ||
| 388 | case 3: /* quad not implemented */ | ||
| 389 | return(MAJOR_0C_EXCP); | ||
| 390 | } | ||
| 391 | case 5: /* FRND */ | ||
| 392 | switch (fmt) { | ||
| 393 | case 0: | ||
| 394 | return(sgl_frnd(&fpregs[r1],0, | ||
| 395 | &fpregs[t],status)); | ||
| 396 | case 1: | ||
| 397 | return(dbl_frnd(&fpregs[r1],0, | ||
| 398 | &fpregs[t],status)); | ||
| 399 | case 2: | ||
| 400 | case 3: /* quad not implemented */ | ||
| 401 | return(MAJOR_0C_EXCP); | ||
| 402 | } | ||
| 403 | } /* end of switch (subop) */ | ||
| 404 | |||
| 405 | case 1: /* class 1 */ | ||
| 406 | df = extru(ir,fpdfpos,2); /* get dest format */ | ||
| 407 | if ((df & 2) || (fmt & 2)) { | ||
| 408 | /* | ||
| 409 | * fmt's 2 and 3 are illegal of not implemented | ||
| 410 | * quad conversions | ||
| 411 | */ | ||
| 412 | return(MAJOR_0C_EXCP); | ||
| 413 | } | ||
| 414 | /* | ||
| 415 | * encode source and dest formats into 2 bits. | ||
| 416 | * high bit is source, low bit is dest. | ||
| 417 | * bit = 1 --> double precision | ||
| 418 | */ | ||
| 419 | fmt = (fmt << 1) | df; | ||
| 420 | switch (subop) { | ||
| 421 | case 0: /* FCNVFF */ | ||
| 422 | switch(fmt) { | ||
| 423 | case 0: /* sgl/sgl */ | ||
| 424 | return(MAJOR_0C_EXCP); | ||
| 425 | case 1: /* sgl/dbl */ | ||
| 426 | return(sgl_to_dbl_fcnvff(&fpregs[r1],0, | ||
| 427 | &fpregs[t],status)); | ||
| 428 | case 2: /* dbl/sgl */ | ||
| 429 | return(dbl_to_sgl_fcnvff(&fpregs[r1],0, | ||
| 430 | &fpregs[t],status)); | ||
| 431 | case 3: /* dbl/dbl */ | ||
| 432 | return(MAJOR_0C_EXCP); | ||
| 433 | } | ||
| 434 | case 1: /* FCNVXF */ | ||
| 435 | switch(fmt) { | ||
| 436 | case 0: /* sgl/sgl */ | ||
| 437 | return(sgl_to_sgl_fcnvxf(&fpregs[r1],0, | ||
| 438 | &fpregs[t],status)); | ||
| 439 | case 1: /* sgl/dbl */ | ||
| 440 | return(sgl_to_dbl_fcnvxf(&fpregs[r1],0, | ||
| 441 | &fpregs[t],status)); | ||
| 442 | case 2: /* dbl/sgl */ | ||
| 443 | return(dbl_to_sgl_fcnvxf(&fpregs[r1],0, | ||
| 444 | &fpregs[t],status)); | ||
| 445 | case 3: /* dbl/dbl */ | ||
| 446 | return(dbl_to_dbl_fcnvxf(&fpregs[r1],0, | ||
| 447 | &fpregs[t],status)); | ||
| 448 | } | ||
| 449 | case 2: /* FCNVFX */ | ||
| 450 | switch(fmt) { | ||
| 451 | case 0: /* sgl/sgl */ | ||
| 452 | return(sgl_to_sgl_fcnvfx(&fpregs[r1],0, | ||
| 453 | &fpregs[t],status)); | ||
| 454 | case 1: /* sgl/dbl */ | ||
| 455 | return(sgl_to_dbl_fcnvfx(&fpregs[r1],0, | ||
| 456 | &fpregs[t],status)); | ||
| 457 | case 2: /* dbl/sgl */ | ||
| 458 | return(dbl_to_sgl_fcnvfx(&fpregs[r1],0, | ||
| 459 | &fpregs[t],status)); | ||
| 460 | case 3: /* dbl/dbl */ | ||
| 461 | return(dbl_to_dbl_fcnvfx(&fpregs[r1],0, | ||
| 462 | &fpregs[t],status)); | ||
| 463 | } | ||
| 464 | case 3: /* FCNVFXT */ | ||
| 465 | switch(fmt) { | ||
| 466 | case 0: /* sgl/sgl */ | ||
| 467 | return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0, | ||
| 468 | &fpregs[t],status)); | ||
| 469 | case 1: /* sgl/dbl */ | ||
| 470 | return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0, | ||
| 471 | &fpregs[t],status)); | ||
| 472 | case 2: /* dbl/sgl */ | ||
| 473 | return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0, | ||
| 474 | &fpregs[t],status)); | ||
| 475 | case 3: /* dbl/dbl */ | ||
| 476 | return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0, | ||
| 477 | &fpregs[t],status)); | ||
| 478 | } | ||
| 479 | case 5: /* FCNVUF (PA2.0 only) */ | ||
| 480 | switch(fmt) { | ||
| 481 | case 0: /* sgl/sgl */ | ||
| 482 | return(sgl_to_sgl_fcnvuf(&fpregs[r1],0, | ||
| 483 | &fpregs[t],status)); | ||
| 484 | case 1: /* sgl/dbl */ | ||
| 485 | return(sgl_to_dbl_fcnvuf(&fpregs[r1],0, | ||
| 486 | &fpregs[t],status)); | ||
| 487 | case 2: /* dbl/sgl */ | ||
| 488 | return(dbl_to_sgl_fcnvuf(&fpregs[r1],0, | ||
| 489 | &fpregs[t],status)); | ||
| 490 | case 3: /* dbl/dbl */ | ||
| 491 | return(dbl_to_dbl_fcnvuf(&fpregs[r1],0, | ||
| 492 | &fpregs[t],status)); | ||
| 493 | } | ||
| 494 | case 6: /* FCNVFU (PA2.0 only) */ | ||
| 495 | switch(fmt) { | ||
| 496 | case 0: /* sgl/sgl */ | ||
| 497 | return(sgl_to_sgl_fcnvfu(&fpregs[r1],0, | ||
| 498 | &fpregs[t],status)); | ||
| 499 | case 1: /* sgl/dbl */ | ||
| 500 | return(sgl_to_dbl_fcnvfu(&fpregs[r1],0, | ||
| 501 | &fpregs[t],status)); | ||
| 502 | case 2: /* dbl/sgl */ | ||
| 503 | return(dbl_to_sgl_fcnvfu(&fpregs[r1],0, | ||
| 504 | &fpregs[t],status)); | ||
| 505 | case 3: /* dbl/dbl */ | ||
| 506 | return(dbl_to_dbl_fcnvfu(&fpregs[r1],0, | ||
| 507 | &fpregs[t],status)); | ||
| 508 | } | ||
| 509 | case 7: /* FCNVFUT (PA2.0 only) */ | ||
| 510 | switch(fmt) { | ||
| 511 | case 0: /* sgl/sgl */ | ||
| 512 | return(sgl_to_sgl_fcnvfut(&fpregs[r1],0, | ||
| 513 | &fpregs[t],status)); | ||
| 514 | case 1: /* sgl/dbl */ | ||
| 515 | return(sgl_to_dbl_fcnvfut(&fpregs[r1],0, | ||
| 516 | &fpregs[t],status)); | ||
| 517 | case 2: /* dbl/sgl */ | ||
| 518 | return(dbl_to_sgl_fcnvfut(&fpregs[r1],0, | ||
| 519 | &fpregs[t],status)); | ||
| 520 | case 3: /* dbl/dbl */ | ||
| 521 | return(dbl_to_dbl_fcnvfut(&fpregs[r1],0, | ||
| 522 | &fpregs[t],status)); | ||
| 523 | } | ||
| 524 | case 4: /* undefined */ | ||
| 525 | return(MAJOR_0C_EXCP); | ||
| 526 | } /* end of switch subop */ | ||
| 527 | |||
| 528 | case 2: /* class 2 */ | ||
| 529 | fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; | ||
| 530 | r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int); | ||
| 531 | if (r2 == 0) | ||
| 532 | r2 = fpzeroreg; | ||
| 533 | if (fpu_type_flags & PA2_0_FPU_FLAG) { | ||
| 534 | /* FTEST if nullify bit set, otherwise FCMP */ | ||
| 535 | if (extru(ir, fpnulpos, 1)) { /* FTEST */ | ||
| 536 | switch (fmt) { | ||
| 537 | case 0: | ||
| 538 | /* | ||
| 539 | * arg0 is not used | ||
| 540 | * second param is the t field used for | ||
| 541 | * ftest,acc and ftest,rej | ||
| 542 | * third param is the subop (y-field) | ||
| 543 | */ | ||
| 544 | BUG(); | ||
| 545 | /* Unsupported | ||
| 546 | * return(ftest(0L,extru(ir,fptpos,5), | ||
| 547 | * &fpregs[0],subop)); | ||
| 548 | */ | ||
| 549 | case 1: | ||
| 550 | case 2: | ||
| 551 | case 3: | ||
| 552 | return(MAJOR_0C_EXCP); | ||
| 553 | } | ||
| 554 | } else { /* FCMP */ | ||
| 555 | switch (fmt) { | ||
| 556 | case 0: | ||
| 557 | retval = sgl_fcmp(&fpregs[r1], | ||
| 558 | &fpregs[r2],extru(ir,fptpos,5), | ||
| 559 | &local_status); | ||
| 560 | update_status_cbit(status,local_status, | ||
| 561 | fpu_type_flags, subop); | ||
| 562 | return(retval); | ||
| 563 | case 1: | ||
| 564 | retval = dbl_fcmp(&fpregs[r1], | ||
| 565 | &fpregs[r2],extru(ir,fptpos,5), | ||
| 566 | &local_status); | ||
| 567 | update_status_cbit(status,local_status, | ||
| 568 | fpu_type_flags, subop); | ||
| 569 | return(retval); | ||
| 570 | case 2: /* illegal */ | ||
| 571 | case 3: /* quad not implemented */ | ||
| 572 | return(MAJOR_0C_EXCP); | ||
| 573 | } | ||
| 574 | } | ||
| 575 | } /* end of if for PA2.0 */ | ||
| 576 | else { /* PA1.0 & PA1.1 */ | ||
| 577 | switch (subop) { | ||
| 578 | case 2: | ||
| 579 | case 3: | ||
| 580 | case 4: | ||
| 581 | case 5: | ||
| 582 | case 6: | ||
| 583 | case 7: | ||
| 584 | return(MAJOR_0C_EXCP); | ||
| 585 | case 0: /* FCMP */ | ||
| 586 | switch (fmt) { | ||
| 587 | case 0: | ||
| 588 | retval = sgl_fcmp(&fpregs[r1], | ||
| 589 | &fpregs[r2],extru(ir,fptpos,5), | ||
| 590 | &local_status); | ||
| 591 | update_status_cbit(status,local_status, | ||
| 592 | fpu_type_flags, subop); | ||
| 593 | return(retval); | ||
| 594 | case 1: | ||
| 595 | retval = dbl_fcmp(&fpregs[r1], | ||
| 596 | &fpregs[r2],extru(ir,fptpos,5), | ||
| 597 | &local_status); | ||
| 598 | update_status_cbit(status,local_status, | ||
| 599 | fpu_type_flags, subop); | ||
| 600 | return(retval); | ||
| 601 | case 2: /* illegal */ | ||
| 602 | case 3: /* quad not implemented */ | ||
| 603 | return(MAJOR_0C_EXCP); | ||
| 604 | } | ||
| 605 | case 1: /* FTEST */ | ||
| 606 | switch (fmt) { | ||
| 607 | case 0: | ||
| 608 | /* | ||
| 609 | * arg0 is not used | ||
| 610 | * second param is the t field used for | ||
| 611 | * ftest,acc and ftest,rej | ||
| 612 | * third param is the subop (y-field) | ||
| 613 | */ | ||
| 614 | BUG(); | ||
| 615 | /* unsupported | ||
| 616 | * return(ftest(0L,extru(ir,fptpos,5), | ||
| 617 | * &fpregs[0],subop)); | ||
| 618 | */ | ||
| 619 | case 1: | ||
| 620 | case 2: | ||
| 621 | case 3: | ||
| 622 | return(MAJOR_0C_EXCP); | ||
| 623 | } | ||
| 624 | } /* end of switch subop */ | ||
| 625 | } /* end of else for PA1.0 & PA1.1 */ | ||
| 626 | case 3: /* class 3 */ | ||
| 627 | r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int); | ||
| 628 | if (r2 == 0) | ||
| 629 | r2 = fpzeroreg; | ||
| 630 | switch (subop) { | ||
| 631 | case 5: | ||
| 632 | case 6: | ||
| 633 | case 7: | ||
| 634 | return(MAJOR_0C_EXCP); | ||
| 635 | |||
| 636 | case 0: /* FADD */ | ||
| 637 | switch (fmt) { | ||
| 638 | case 0: | ||
| 639 | return(sgl_fadd(&fpregs[r1],&fpregs[r2], | ||
| 640 | &fpregs[t],status)); | ||
| 641 | case 1: | ||
| 642 | return(dbl_fadd(&fpregs[r1],&fpregs[r2], | ||
| 643 | &fpregs[t],status)); | ||
| 644 | case 2: /* illegal */ | ||
| 645 | case 3: /* quad not implemented */ | ||
| 646 | return(MAJOR_0C_EXCP); | ||
| 647 | } | ||
| 648 | case 1: /* FSUB */ | ||
| 649 | switch (fmt) { | ||
| 650 | case 0: | ||
| 651 | return(sgl_fsub(&fpregs[r1],&fpregs[r2], | ||
| 652 | &fpregs[t],status)); | ||
| 653 | case 1: | ||
| 654 | return(dbl_fsub(&fpregs[r1],&fpregs[r2], | ||
| 655 | &fpregs[t],status)); | ||
| 656 | case 2: /* illegal */ | ||
| 657 | case 3: /* quad not implemented */ | ||
| 658 | return(MAJOR_0C_EXCP); | ||
| 659 | } | ||
| 660 | case 2: /* FMPY */ | ||
| 661 | switch (fmt) { | ||
| 662 | case 0: | ||
| 663 | return(sgl_fmpy(&fpregs[r1],&fpregs[r2], | ||
| 664 | &fpregs[t],status)); | ||
| 665 | case 1: | ||
| 666 | return(dbl_fmpy(&fpregs[r1],&fpregs[r2], | ||
| 667 | &fpregs[t],status)); | ||
| 668 | case 2: /* illegal */ | ||
| 669 | case 3: /* quad not implemented */ | ||
| 670 | return(MAJOR_0C_EXCP); | ||
| 671 | } | ||
| 672 | case 3: /* FDIV */ | ||
| 673 | switch (fmt) { | ||
| 674 | case 0: | ||
| 675 | return(sgl_fdiv(&fpregs[r1],&fpregs[r2], | ||
| 676 | &fpregs[t],status)); | ||
| 677 | case 1: | ||
| 678 | return(dbl_fdiv(&fpregs[r1],&fpregs[r2], | ||
| 679 | &fpregs[t],status)); | ||
| 680 | case 2: /* illegal */ | ||
| 681 | case 3: /* quad not implemented */ | ||
| 682 | return(MAJOR_0C_EXCP); | ||
| 683 | } | ||
| 684 | case 4: /* FREM */ | ||
| 685 | switch (fmt) { | ||
| 686 | case 0: | ||
| 687 | return(sgl_frem(&fpregs[r1],&fpregs[r2], | ||
| 688 | &fpregs[t],status)); | ||
| 689 | case 1: | ||
| 690 | return(dbl_frem(&fpregs[r1],&fpregs[r2], | ||
| 691 | &fpregs[t],status)); | ||
| 692 | case 2: /* illegal */ | ||
| 693 | case 3: /* quad not implemented */ | ||
| 694 | return(MAJOR_0C_EXCP); | ||
| 695 | } | ||
| 696 | } /* end of class 3 switch */ | ||
| 697 | } /* end of switch(class) */ | ||
| 698 | |||
| 699 | /* If we get here, something is really wrong! */ | ||
| 700 | return(MAJOR_0C_EXCP); | ||
| 701 | } | ||
| 702 | |||
| 703 | static u_int | ||
| 704 | decode_0e(ir,class,subop,fpregs) | ||
| 705 | u_int ir,class,subop; | ||
| 706 | u_int fpregs[]; | ||
| 707 | { | ||
| 708 | u_int r1,r2,t; /* operand register offsets */ | ||
| 709 | u_int fmt; /* also sf for class 1 conversions */ | ||
| 710 | u_int df; /* dest format for class 1 conversions */ | ||
| 711 | u_int *status; | ||
| 712 | u_int retval, local_status; | ||
| 713 | u_int fpu_type_flags; | ||
| 714 | |||
| 715 | status = &fpregs[0]; | ||
| 716 | local_status = fpregs[0]; | ||
| 717 | r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1))); | ||
| 718 | if (r1 == 0) | ||
| 719 | r1 = fpzeroreg; | ||
| 720 | t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1))); | ||
| 721 | if (t == 0 && class != 2) | ||
| 722 | return(MAJOR_0E_EXCP); | ||
| 723 | if (class < 2) /* class 0 or 1 has 2 bit fmt */ | ||
| 724 | fmt = extru(ir,fpfmtpos,2); | ||
| 725 | else /* class 2 and 3 have 1 bit fmt */ | ||
| 726 | fmt = extru(ir,fp0efmtpos,1); | ||
| 727 | /* | ||
| 728 | * An undefined combination, double precision accessing the | ||
| 729 | * right half of a FPR, can get us into trouble. | ||
| 730 | * Let's just force proper alignment on it. | ||
| 731 | */ | ||
| 732 | if (fmt == DBL) { | ||
| 733 | r1 &= ~1; | ||
| 734 | if (class != 1) | ||
| 735 | t &= ~1; | ||
| 736 | } | ||
| 737 | |||
| 738 | switch (class) { | ||
| 739 | case 0: | ||
| 740 | switch (subop) { | ||
| 741 | case 0: /* unimplemented */ | ||
| 742 | case 1: | ||
| 743 | return(MAJOR_0E_EXCP); | ||
| 744 | case 2: /* FCPY */ | ||
| 745 | switch (fmt) { | ||
| 746 | case 2: | ||
| 747 | case 3: | ||
| 748 | return(MAJOR_0E_EXCP); | ||
| 749 | case 1: /* double */ | ||
| 750 | fpregs[t+1] = fpregs[r1+1]; | ||
| 751 | case 0: /* single */ | ||
| 752 | fpregs[t] = fpregs[r1]; | ||
| 753 | return(NOEXCEPTION); | ||
| 754 | } | ||
| 755 | case 3: /* FABS */ | ||
| 756 | switch (fmt) { | ||
| 757 | case 2: | ||
| 758 | case 3: | ||
| 759 | return(MAJOR_0E_EXCP); | ||
| 760 | case 1: /* double */ | ||
| 761 | fpregs[t+1] = fpregs[r1+1]; | ||
| 762 | case 0: /* single */ | ||
| 763 | fpregs[t] = fpregs[r1] & 0x7fffffff; | ||
| 764 | return(NOEXCEPTION); | ||
| 765 | } | ||
| 766 | case 6: /* FNEG */ | ||
| 767 | switch (fmt) { | ||
| 768 | case 2: | ||
| 769 | case 3: | ||
| 770 | return(MAJOR_0E_EXCP); | ||
| 771 | case 1: /* double */ | ||
| 772 | fpregs[t+1] = fpregs[r1+1]; | ||
| 773 | case 0: /* single */ | ||
| 774 | fpregs[t] = fpregs[r1] ^ 0x80000000; | ||
| 775 | return(NOEXCEPTION); | ||
| 776 | } | ||
| 777 | case 7: /* FNEGABS */ | ||
| 778 | switch (fmt) { | ||
| 779 | case 2: | ||
| 780 | case 3: | ||
| 781 | return(MAJOR_0E_EXCP); | ||
| 782 | case 1: /* double */ | ||
| 783 | fpregs[t+1] = fpregs[r1+1]; | ||
| 784 | case 0: /* single */ | ||
| 785 | fpregs[t] = fpregs[r1] | 0x80000000; | ||
| 786 | return(NOEXCEPTION); | ||
| 787 | } | ||
| 788 | case 4: /* FSQRT */ | ||
| 789 | switch (fmt) { | ||
| 790 | case 0: | ||
| 791 | return(sgl_fsqrt(&fpregs[r1],0, | ||
| 792 | &fpregs[t], status)); | ||
| 793 | case 1: | ||
| 794 | return(dbl_fsqrt(&fpregs[r1],0, | ||
| 795 | &fpregs[t], status)); | ||
| 796 | case 2: | ||
| 797 | case 3: | ||
| 798 | return(MAJOR_0E_EXCP); | ||
| 799 | } | ||
| 800 | case 5: /* FRMD */ | ||
| 801 | switch (fmt) { | ||
| 802 | case 0: | ||
| 803 | return(sgl_frnd(&fpregs[r1],0, | ||
| 804 | &fpregs[t], status)); | ||
| 805 | case 1: | ||
| 806 | return(dbl_frnd(&fpregs[r1],0, | ||
| 807 | &fpregs[t], status)); | ||
| 808 | case 2: | ||
| 809 | case 3: | ||
| 810 | return(MAJOR_0E_EXCP); | ||
| 811 | } | ||
| 812 | } /* end of switch (subop */ | ||
| 813 | |||
| 814 | case 1: /* class 1 */ | ||
| 815 | df = extru(ir,fpdfpos,2); /* get dest format */ | ||
| 816 | /* | ||
| 817 | * Fix Crashme problem (writing to 31R in double precision) | ||
| 818 | * here too. | ||
| 819 | */ | ||
| 820 | if (df == DBL) { | ||
| 821 | t &= ~1; | ||
| 822 | } | ||
| 823 | if ((df & 2) || (fmt & 2)) | ||
| 824 | return(MAJOR_0E_EXCP); | ||
| 825 | |||
| 826 | fmt = (fmt << 1) | df; | ||
| 827 | switch (subop) { | ||
| 828 | case 0: /* FCNVFF */ | ||
| 829 | switch(fmt) { | ||
| 830 | case 0: /* sgl/sgl */ | ||
| 831 | return(MAJOR_0E_EXCP); | ||
| 832 | case 1: /* sgl/dbl */ | ||
| 833 | return(sgl_to_dbl_fcnvff(&fpregs[r1],0, | ||
| 834 | &fpregs[t],status)); | ||
| 835 | case 2: /* dbl/sgl */ | ||
| 836 | return(dbl_to_sgl_fcnvff(&fpregs[r1],0, | ||
| 837 | &fpregs[t],status)); | ||
| 838 | case 3: /* dbl/dbl */ | ||
| 839 | return(MAJOR_0E_EXCP); | ||
| 840 | } | ||
| 841 | case 1: /* FCNVXF */ | ||
| 842 | switch(fmt) { | ||
| 843 | case 0: /* sgl/sgl */ | ||
| 844 | return(sgl_to_sgl_fcnvxf(&fpregs[r1],0, | ||
| 845 | &fpregs[t],status)); | ||
| 846 | case 1: /* sgl/dbl */ | ||
| 847 | return(sgl_to_dbl_fcnvxf(&fpregs[r1],0, | ||
| 848 | &fpregs[t],status)); | ||
| 849 | case 2: /* dbl/sgl */ | ||
| 850 | return(dbl_to_sgl_fcnvxf(&fpregs[r1],0, | ||
| 851 | &fpregs[t],status)); | ||
| 852 | case 3: /* dbl/dbl */ | ||
| 853 | return(dbl_to_dbl_fcnvxf(&fpregs[r1],0, | ||
| 854 | &fpregs[t],status)); | ||
| 855 | } | ||
| 856 | case 2: /* FCNVFX */ | ||
| 857 | switch(fmt) { | ||
| 858 | case 0: /* sgl/sgl */ | ||
| 859 | return(sgl_to_sgl_fcnvfx(&fpregs[r1],0, | ||
| 860 | &fpregs[t],status)); | ||
| 861 | case 1: /* sgl/dbl */ | ||
| 862 | return(sgl_to_dbl_fcnvfx(&fpregs[r1],0, | ||
| 863 | &fpregs[t],status)); | ||
| 864 | case 2: /* dbl/sgl */ | ||
| 865 | return(dbl_to_sgl_fcnvfx(&fpregs[r1],0, | ||
| 866 | &fpregs[t],status)); | ||
| 867 | case 3: /* dbl/dbl */ | ||
| 868 | return(dbl_to_dbl_fcnvfx(&fpregs[r1],0, | ||
| 869 | &fpregs[t],status)); | ||
| 870 | } | ||
| 871 | case 3: /* FCNVFXT */ | ||
| 872 | switch(fmt) { | ||
| 873 | case 0: /* sgl/sgl */ | ||
| 874 | return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0, | ||
| 875 | &fpregs[t],status)); | ||
| 876 | case 1: /* sgl/dbl */ | ||
| 877 | return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0, | ||
| 878 | &fpregs[t],status)); | ||
| 879 | case 2: /* dbl/sgl */ | ||
| 880 | return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0, | ||
| 881 | &fpregs[t],status)); | ||
| 882 | case 3: /* dbl/dbl */ | ||
| 883 | return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0, | ||
| 884 | &fpregs[t],status)); | ||
| 885 | } | ||
| 886 | case 5: /* FCNVUF (PA2.0 only) */ | ||
| 887 | switch(fmt) { | ||
| 888 | case 0: /* sgl/sgl */ | ||
| 889 | return(sgl_to_sgl_fcnvuf(&fpregs[r1],0, | ||
| 890 | &fpregs[t],status)); | ||
| 891 | case 1: /* sgl/dbl */ | ||
| 892 | return(sgl_to_dbl_fcnvuf(&fpregs[r1],0, | ||
| 893 | &fpregs[t],status)); | ||
| 894 | case 2: /* dbl/sgl */ | ||
| 895 | return(dbl_to_sgl_fcnvuf(&fpregs[r1],0, | ||
| 896 | &fpregs[t],status)); | ||
| 897 | case 3: /* dbl/dbl */ | ||
| 898 | return(dbl_to_dbl_fcnvuf(&fpregs[r1],0, | ||
| 899 | &fpregs[t],status)); | ||
| 900 | } | ||
| 901 | case 6: /* FCNVFU (PA2.0 only) */ | ||
| 902 | switch(fmt) { | ||
| 903 | case 0: /* sgl/sgl */ | ||
| 904 | return(sgl_to_sgl_fcnvfu(&fpregs[r1],0, | ||
| 905 | &fpregs[t],status)); | ||
| 906 | case 1: /* sgl/dbl */ | ||
| 907 | return(sgl_to_dbl_fcnvfu(&fpregs[r1],0, | ||
| 908 | &fpregs[t],status)); | ||
| 909 | case 2: /* dbl/sgl */ | ||
| 910 | return(dbl_to_sgl_fcnvfu(&fpregs[r1],0, | ||
| 911 | &fpregs[t],status)); | ||
| 912 | case 3: /* dbl/dbl */ | ||
| 913 | return(dbl_to_dbl_fcnvfu(&fpregs[r1],0, | ||
| 914 | &fpregs[t],status)); | ||
| 915 | } | ||
| 916 | case 7: /* FCNVFUT (PA2.0 only) */ | ||
| 917 | switch(fmt) { | ||
| 918 | case 0: /* sgl/sgl */ | ||
| 919 | return(sgl_to_sgl_fcnvfut(&fpregs[r1],0, | ||
| 920 | &fpregs[t],status)); | ||
| 921 | case 1: /* sgl/dbl */ | ||
| 922 | return(sgl_to_dbl_fcnvfut(&fpregs[r1],0, | ||
| 923 | &fpregs[t],status)); | ||
| 924 | case 2: /* dbl/sgl */ | ||
| 925 | return(dbl_to_sgl_fcnvfut(&fpregs[r1],0, | ||
| 926 | &fpregs[t],status)); | ||
| 927 | case 3: /* dbl/dbl */ | ||
| 928 | return(dbl_to_dbl_fcnvfut(&fpregs[r1],0, | ||
| 929 | &fpregs[t],status)); | ||
| 930 | } | ||
| 931 | case 4: /* undefined */ | ||
| 932 | return(MAJOR_0C_EXCP); | ||
| 933 | } /* end of switch subop */ | ||
| 934 | case 2: /* class 2 */ | ||
| 935 | /* | ||
| 936 | * Be careful out there. | ||
| 937 | * Crashme can generate cases where FR31R is specified | ||
| 938 | * as the source or target of a double precision operation. | ||
| 939 | * Since we just pass the address of the floating-point | ||
| 940 | * register to the emulation routines, this can cause | ||
| 941 | * corruption of fpzeroreg. | ||
| 942 | */ | ||
| 943 | if (fmt == DBL) | ||
| 944 | r2 = (extru(ir,fpr2pos,5)<<1); | ||
| 945 | else | ||
| 946 | r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1))); | ||
| 947 | fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; | ||
| 948 | if (r2 == 0) | ||
| 949 | r2 = fpzeroreg; | ||
| 950 | if (fpu_type_flags & PA2_0_FPU_FLAG) { | ||
| 951 | /* FTEST if nullify bit set, otherwise FCMP */ | ||
| 952 | if (extru(ir, fpnulpos, 1)) { /* FTEST */ | ||
| 953 | /* not legal */ | ||
| 954 | return(MAJOR_0E_EXCP); | ||
| 955 | } else { /* FCMP */ | ||
| 956 | switch (fmt) { | ||
| 957 | /* | ||
| 958 | * fmt is only 1 bit long | ||
| 959 | */ | ||
| 960 | case 0: | ||
| 961 | retval = sgl_fcmp(&fpregs[r1], | ||
| 962 | &fpregs[r2],extru(ir,fptpos,5), | ||
| 963 | &local_status); | ||
| 964 | update_status_cbit(status,local_status, | ||
| 965 | fpu_type_flags, subop); | ||
| 966 | return(retval); | ||
| 967 | case 1: | ||
| 968 | retval = dbl_fcmp(&fpregs[r1], | ||
| 969 | &fpregs[r2],extru(ir,fptpos,5), | ||
| 970 | &local_status); | ||
| 971 | update_status_cbit(status,local_status, | ||
| 972 | fpu_type_flags, subop); | ||
| 973 | return(retval); | ||
| 974 | } | ||
| 975 | } | ||
| 976 | } /* end of if for PA2.0 */ | ||
| 977 | else { /* PA1.0 & PA1.1 */ | ||
| 978 | switch (subop) { | ||
| 979 | case 1: | ||
| 980 | case 2: | ||
| 981 | case 3: | ||
| 982 | case 4: | ||
| 983 | case 5: | ||
| 984 | case 6: | ||
| 985 | case 7: | ||
| 986 | return(MAJOR_0E_EXCP); | ||
| 987 | case 0: /* FCMP */ | ||
| 988 | switch (fmt) { | ||
| 989 | /* | ||
| 990 | * fmt is only 1 bit long | ||
| 991 | */ | ||
| 992 | case 0: | ||
| 993 | retval = sgl_fcmp(&fpregs[r1], | ||
| 994 | &fpregs[r2],extru(ir,fptpos,5), | ||
| 995 | &local_status); | ||
| 996 | update_status_cbit(status,local_status, | ||
| 997 | fpu_type_flags, subop); | ||
| 998 | return(retval); | ||
| 999 | case 1: | ||
| 1000 | retval = dbl_fcmp(&fpregs[r1], | ||
| 1001 | &fpregs[r2],extru(ir,fptpos,5), | ||
| 1002 | &local_status); | ||
| 1003 | update_status_cbit(status,local_status, | ||
| 1004 | fpu_type_flags, subop); | ||
| 1005 | return(retval); | ||
| 1006 | } | ||
| 1007 | } /* end of switch subop */ | ||
| 1008 | } /* end of else for PA1.0 & PA1.1 */ | ||
| 1009 | case 3: /* class 3 */ | ||
| 1010 | /* | ||
| 1011 | * Be careful out there. | ||
| 1012 | * Crashme can generate cases where FR31R is specified | ||
| 1013 | * as the source or target of a double precision operation. | ||
| 1014 | * Since we just pass the address of the floating-point | ||
| 1015 | * register to the emulation routines, this can cause | ||
| 1016 | * corruption of fpzeroreg. | ||
| 1017 | */ | ||
| 1018 | if (fmt == DBL) | ||
| 1019 | r2 = (extru(ir,fpr2pos,5)<<1); | ||
| 1020 | else | ||
| 1021 | r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1))); | ||
| 1022 | if (r2 == 0) | ||
| 1023 | r2 = fpzeroreg; | ||
| 1024 | switch (subop) { | ||
| 1025 | case 5: | ||
| 1026 | case 6: | ||
| 1027 | case 7: | ||
| 1028 | return(MAJOR_0E_EXCP); | ||
| 1029 | |||
| 1030 | /* | ||
| 1031 | * Note that fmt is only 1 bit for class 3 */ | ||
| 1032 | case 0: /* FADD */ | ||
| 1033 | switch (fmt) { | ||
| 1034 | case 0: | ||
| 1035 | return(sgl_fadd(&fpregs[r1],&fpregs[r2], | ||
| 1036 | &fpregs[t],status)); | ||
| 1037 | case 1: | ||
| 1038 | return(dbl_fadd(&fpregs[r1],&fpregs[r2], | ||
| 1039 | &fpregs[t],status)); | ||
| 1040 | } | ||
| 1041 | case 1: /* FSUB */ | ||
| 1042 | switch (fmt) { | ||
| 1043 | case 0: | ||
| 1044 | return(sgl_fsub(&fpregs[r1],&fpregs[r2], | ||
| 1045 | &fpregs[t],status)); | ||
| 1046 | case 1: | ||
| 1047 | return(dbl_fsub(&fpregs[r1],&fpregs[r2], | ||
| 1048 | &fpregs[t],status)); | ||
| 1049 | } | ||
| 1050 | case 2: /* FMPY or XMPYU */ | ||
| 1051 | /* | ||
| 1052 | * check for integer multiply (x bit set) | ||
| 1053 | */ | ||
| 1054 | if (extru(ir,fpxpos,1)) { | ||
| 1055 | /* | ||
| 1056 | * emulate XMPYU | ||
| 1057 | */ | ||
| 1058 | switch (fmt) { | ||
| 1059 | case 0: | ||
| 1060 | /* | ||
| 1061 | * bad instruction if t specifies | ||
| 1062 | * the right half of a register | ||
| 1063 | */ | ||
| 1064 | if (t & 1) | ||
| 1065 | return(MAJOR_0E_EXCP); | ||
| 1066 | BUG(); | ||
| 1067 | /* unsupported | ||
| 1068 | * impyu(&fpregs[r1],&fpregs[r2], | ||
| 1069 | * &fpregs[t]); | ||
| 1070 | */ | ||
| 1071 | return(NOEXCEPTION); | ||
| 1072 | case 1: | ||
| 1073 | return(MAJOR_0E_EXCP); | ||
| 1074 | } | ||
| 1075 | } | ||
| 1076 | else { /* FMPY */ | ||
| 1077 | switch (fmt) { | ||
| 1078 | case 0: | ||
| 1079 | return(sgl_fmpy(&fpregs[r1], | ||
| 1080 | &fpregs[r2],&fpregs[t],status)); | ||
| 1081 | case 1: | ||
| 1082 | return(dbl_fmpy(&fpregs[r1], | ||
| 1083 | &fpregs[r2],&fpregs[t],status)); | ||
| 1084 | } | ||
| 1085 | } | ||
| 1086 | case 3: /* FDIV */ | ||
| 1087 | switch (fmt) { | ||
| 1088 | case 0: | ||
| 1089 | return(sgl_fdiv(&fpregs[r1],&fpregs[r2], | ||
| 1090 | &fpregs[t],status)); | ||
| 1091 | case 1: | ||
| 1092 | return(dbl_fdiv(&fpregs[r1],&fpregs[r2], | ||
| 1093 | &fpregs[t],status)); | ||
| 1094 | } | ||
| 1095 | case 4: /* FREM */ | ||
| 1096 | switch (fmt) { | ||
| 1097 | case 0: | ||
| 1098 | return(sgl_frem(&fpregs[r1],&fpregs[r2], | ||
| 1099 | &fpregs[t],status)); | ||
| 1100 | case 1: | ||
| 1101 | return(dbl_frem(&fpregs[r1],&fpregs[r2], | ||
| 1102 | &fpregs[t],status)); | ||
| 1103 | } | ||
| 1104 | } /* end of class 3 switch */ | ||
| 1105 | } /* end of switch(class) */ | ||
| 1106 | |||
| 1107 | /* If we get here, something is really wrong! */ | ||
| 1108 | return(MAJOR_0E_EXCP); | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | |||
| 1112 | /* | ||
| 1113 | * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction | ||
| 1114 | */ | ||
| 1115 | static u_int | ||
| 1116 | decode_06(ir,fpregs) | ||
| 1117 | u_int ir; | ||
| 1118 | u_int fpregs[]; | ||
| 1119 | { | ||
| 1120 | u_int rm1, rm2, tm, ra, ta; /* operands */ | ||
| 1121 | u_int fmt; | ||
| 1122 | u_int error = 0; | ||
| 1123 | u_int status; | ||
| 1124 | u_int fpu_type_flags; | ||
| 1125 | union { | ||
| 1126 | double dbl; | ||
| 1127 | float flt; | ||
| 1128 | struct { u_int i1; u_int i2; } ints; | ||
| 1129 | } mtmp, atmp; | ||
| 1130 | |||
| 1131 | |||
| 1132 | status = fpregs[0]; /* use a local copy of status reg */ | ||
| 1133 | fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS]; /* get fpu type flags */ | ||
| 1134 | fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */ | ||
| 1135 | if (fmt == 0) { /* DBL */ | ||
| 1136 | rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int); | ||
| 1137 | if (rm1 == 0) | ||
| 1138 | rm1 = fpzeroreg; | ||
| 1139 | rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int); | ||
| 1140 | if (rm2 == 0) | ||
| 1141 | rm2 = fpzeroreg; | ||
| 1142 | tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int); | ||
| 1143 | if (tm == 0) | ||
| 1144 | return(MAJOR_06_EXCP); | ||
| 1145 | ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int); | ||
| 1146 | ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int); | ||
| 1147 | if (ta == 0) | ||
| 1148 | return(MAJOR_06_EXCP); | ||
| 1149 | |||
| 1150 | if (fpu_type_flags & TIMEX_ROLEX_FPU_MASK) { | ||
| 1151 | |||
| 1152 | if (ra == 0) { | ||
| 1153 | /* special case FMPYCFXT, see sgl case below */ | ||
| 1154 | if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2], | ||
| 1155 | &mtmp.ints.i1,&status)) | ||
| 1156 | error = 1; | ||
| 1157 | if (dbl_to_sgl_fcnvfxt(&fpregs[ta], | ||
| 1158 | &atmp.ints.i1,&atmp.ints.i1,&status)) | ||
| 1159 | error = 1; | ||
| 1160 | } | ||
| 1161 | else { | ||
| 1162 | |||
| 1163 | if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, | ||
| 1164 | &status)) | ||
| 1165 | error = 1; | ||
| 1166 | if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, | ||
| 1167 | &status)) | ||
| 1168 | error = 1; | ||
| 1169 | } | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | else | ||
| 1173 | |||
| 1174 | { | ||
| 1175 | if (ra == 0) | ||
| 1176 | ra = fpzeroreg; | ||
| 1177 | |||
| 1178 | if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, | ||
| 1179 | &status)) | ||
| 1180 | error = 1; | ||
| 1181 | if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, | ||
| 1182 | &status)) | ||
| 1183 | error = 1; | ||
| 1184 | |||
| 1185 | } | ||
| 1186 | |||
| 1187 | if (error) | ||
| 1188 | return(MAJOR_06_EXCP); | ||
| 1189 | else { | ||
| 1190 | /* copy results */ | ||
| 1191 | fpregs[tm] = mtmp.ints.i1; | ||
| 1192 | fpregs[tm+1] = mtmp.ints.i2; | ||
| 1193 | fpregs[ta] = atmp.ints.i1; | ||
| 1194 | fpregs[ta+1] = atmp.ints.i2; | ||
| 1195 | fpregs[0] = status; | ||
| 1196 | return(NOEXCEPTION); | ||
| 1197 | } | ||
| 1198 | } | ||
| 1199 | else { /* SGL */ | ||
| 1200 | /* | ||
| 1201 | * calculate offsets for single precision numbers | ||
| 1202 | * See table 6-14 in PA-89 architecture for mapping | ||
| 1203 | */ | ||
| 1204 | rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */ | ||
| 1205 | rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */ | ||
| 1206 | |||
| 1207 | rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */ | ||
| 1208 | rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */ | ||
| 1209 | |||
| 1210 | tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */ | ||
| 1211 | tm |= extru(ir,fptmpos-4,1); /* add right word offset */ | ||
| 1212 | |||
| 1213 | ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */ | ||
| 1214 | ra |= extru(ir,fprapos-4,1); /* add right word offset */ | ||
| 1215 | |||
| 1216 | ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */ | ||
| 1217 | ta |= extru(ir,fptapos-4,1); /* add right word offset */ | ||
| 1218 | |||
| 1219 | if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) { | ||
| 1220 | /* special case FMPYCFXT (really 0) | ||
| 1221 | * This instruction is only present on the Timex and | ||
| 1222 | * Rolex fpu's in so if it is the special case and | ||
| 1223 | * one of these fpu's we run the FMPYCFXT instruction | ||
| 1224 | */ | ||
| 1225 | if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, | ||
| 1226 | &status)) | ||
| 1227 | error = 1; | ||
| 1228 | if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1, | ||
| 1229 | &atmp.ints.i1,&status)) | ||
| 1230 | error = 1; | ||
| 1231 | } | ||
| 1232 | else { | ||
| 1233 | if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1, | ||
| 1234 | &status)) | ||
| 1235 | error = 1; | ||
| 1236 | if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1, | ||
| 1237 | &status)) | ||
| 1238 | error = 1; | ||
| 1239 | } | ||
| 1240 | if (error) | ||
| 1241 | return(MAJOR_06_EXCP); | ||
| 1242 | else { | ||
| 1243 | /* copy results */ | ||
| 1244 | fpregs[tm] = mtmp.ints.i1; | ||
| 1245 | fpregs[ta] = atmp.ints.i1; | ||
| 1246 | fpregs[0] = status; | ||
| 1247 | return(NOEXCEPTION); | ||
| 1248 | } | ||
| 1249 | } | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | /* | ||
| 1253 | * routine to decode the 26 (FMPYSUB) instruction | ||
| 1254 | */ | ||
| 1255 | static u_int | ||
| 1256 | decode_26(ir,fpregs) | ||
| 1257 | u_int ir; | ||
| 1258 | u_int fpregs[]; | ||
| 1259 | { | ||
| 1260 | u_int rm1, rm2, tm, ra, ta; /* operands */ | ||
| 1261 | u_int fmt; | ||
| 1262 | u_int error = 0; | ||
| 1263 | u_int status; | ||
| 1264 | union { | ||
| 1265 | double dbl; | ||
| 1266 | float flt; | ||
| 1267 | struct { u_int i1; u_int i2; } ints; | ||
| 1268 | } mtmp, atmp; | ||
| 1269 | |||
| 1270 | |||
| 1271 | status = fpregs[0]; | ||
| 1272 | fmt = extru(ir, fpmultifmt, 1); /* get sgl/dbl flag */ | ||
| 1273 | if (fmt == 0) { /* DBL */ | ||
| 1274 | rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int); | ||
| 1275 | if (rm1 == 0) | ||
| 1276 | rm1 = fpzeroreg; | ||
| 1277 | rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int); | ||
| 1278 | if (rm2 == 0) | ||
| 1279 | rm2 = fpzeroreg; | ||
| 1280 | tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int); | ||
| 1281 | if (tm == 0) | ||
| 1282 | return(MAJOR_26_EXCP); | ||
| 1283 | ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int); | ||
| 1284 | if (ra == 0) | ||
| 1285 | return(MAJOR_26_EXCP); | ||
| 1286 | ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int); | ||
| 1287 | if (ta == 0) | ||
| 1288 | return(MAJOR_26_EXCP); | ||
| 1289 | |||
| 1290 | if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status)) | ||
| 1291 | error = 1; | ||
| 1292 | if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status)) | ||
| 1293 | error = 1; | ||
| 1294 | if (error) | ||
| 1295 | return(MAJOR_26_EXCP); | ||
| 1296 | else { | ||
| 1297 | /* copy results */ | ||
| 1298 | fpregs[tm] = mtmp.ints.i1; | ||
| 1299 | fpregs[tm+1] = mtmp.ints.i2; | ||
| 1300 | fpregs[ta] = atmp.ints.i1; | ||
| 1301 | fpregs[ta+1] = atmp.ints.i2; | ||
| 1302 | fpregs[0] = status; | ||
| 1303 | return(NOEXCEPTION); | ||
| 1304 | } | ||
| 1305 | } | ||
| 1306 | else { /* SGL */ | ||
| 1307 | /* | ||
| 1308 | * calculate offsets for single precision numbers | ||
| 1309 | * See table 6-14 in PA-89 architecture for mapping | ||
| 1310 | */ | ||
| 1311 | rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1; /* get offset */ | ||
| 1312 | rm1 |= extru(ir,fprm1pos-4,1); /* add right word offset */ | ||
| 1313 | |||
| 1314 | rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1; /* get offset */ | ||
| 1315 | rm2 |= extru(ir,fprm2pos-4,1); /* add right word offset */ | ||
| 1316 | |||
| 1317 | tm = (extru(ir,fptmpos,4) | 0x10 ) << 1; /* get offset */ | ||
| 1318 | tm |= extru(ir,fptmpos-4,1); /* add right word offset */ | ||
| 1319 | |||
| 1320 | ra = (extru(ir,fprapos,4) | 0x10 ) << 1; /* get offset */ | ||
| 1321 | ra |= extru(ir,fprapos-4,1); /* add right word offset */ | ||
| 1322 | |||
| 1323 | ta = (extru(ir,fptapos,4) | 0x10 ) << 1; /* get offset */ | ||
| 1324 | ta |= extru(ir,fptapos-4,1); /* add right word offset */ | ||
| 1325 | |||
| 1326 | if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status)) | ||
| 1327 | error = 1; | ||
| 1328 | if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status)) | ||
| 1329 | error = 1; | ||
| 1330 | if (error) | ||
| 1331 | return(MAJOR_26_EXCP); | ||
| 1332 | else { | ||
| 1333 | /* copy results */ | ||
| 1334 | fpregs[tm] = mtmp.ints.i1; | ||
| 1335 | fpregs[ta] = atmp.ints.i1; | ||
| 1336 | fpregs[0] = status; | ||
| 1337 | return(NOEXCEPTION); | ||
| 1338 | } | ||
| 1339 | } | ||
| 1340 | |||
| 1341 | } | ||
| 1342 | |||
| 1343 | /* | ||
| 1344 | * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions | ||
| 1345 | */ | ||
| 1346 | static u_int | ||
| 1347 | decode_2e(ir,fpregs) | ||
| 1348 | u_int ir; | ||
| 1349 | u_int fpregs[]; | ||
| 1350 | { | ||
| 1351 | u_int rm1, rm2, ra, t; /* operands */ | ||
| 1352 | u_int fmt; | ||
| 1353 | |||
| 1354 | fmt = extru(ir,fpfmtpos,1); /* get fmt completer */ | ||
| 1355 | if (fmt == DBL) { /* DBL */ | ||
| 1356 | rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int); | ||
| 1357 | if (rm1 == 0) | ||
| 1358 | rm1 = fpzeroreg; | ||
| 1359 | rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int); | ||
| 1360 | if (rm2 == 0) | ||
| 1361 | rm2 = fpzeroreg; | ||
| 1362 | ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) * | ||
| 1363 | sizeof(double)/sizeof(u_int); | ||
| 1364 | if (ra == 0) | ||
| 1365 | ra = fpzeroreg; | ||
| 1366 | t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int); | ||
| 1367 | if (t == 0) | ||
| 1368 | return(MAJOR_2E_EXCP); | ||
| 1369 | |||
| 1370 | if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */ | ||
| 1371 | return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2], | ||
| 1372 | &fpregs[ra], &fpregs[0], &fpregs[t])); | ||
| 1373 | } else { | ||
| 1374 | return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2], | ||
| 1375 | &fpregs[ra], &fpregs[0], &fpregs[t])); | ||
| 1376 | } | ||
| 1377 | } /* end DBL */ | ||
| 1378 | else { /* SGL */ | ||
| 1379 | rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1)); | ||
| 1380 | if (rm1 == 0) | ||
| 1381 | rm1 = fpzeroreg; | ||
| 1382 | rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1)); | ||
| 1383 | if (rm2 == 0) | ||
| 1384 | rm2 = fpzeroreg; | ||
| 1385 | ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3); | ||
| 1386 | if (ra == 0) | ||
| 1387 | ra = fpzeroreg; | ||
| 1388 | t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1))); | ||
| 1389 | if (t == 0) | ||
| 1390 | return(MAJOR_2E_EXCP); | ||
| 1391 | |||
| 1392 | if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */ | ||
| 1393 | return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2], | ||
| 1394 | &fpregs[ra], &fpregs[0], &fpregs[t])); | ||
| 1395 | } else { | ||
| 1396 | return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2], | ||
| 1397 | &fpregs[ra], &fpregs[0], &fpregs[t])); | ||
| 1398 | } | ||
| 1399 | } /* end SGL */ | ||
| 1400 | } | ||
| 1401 | |||
| 1402 | /* | ||
| 1403 | * update_status_cbit | ||
| 1404 | * | ||
| 1405 | * This routine returns the correct FP status register value in | ||
| 1406 | * *status, based on the C-bit & V-bit returned by the FCMP | ||
| 1407 | * emulation routine in new_status. The architecture type | ||
| 1408 | * (PA83, PA89 or PA2.0) is available in fpu_type. The y_field | ||
| 1409 | * and the architecture type are used to determine what flavor | ||
| 1410 | * of FCMP is being emulated. | ||
| 1411 | */ | ||
| 1412 | static void | ||
| 1413 | update_status_cbit(status, new_status, fpu_type, y_field) | ||
| 1414 | u_int *status, new_status; | ||
| 1415 | u_int fpu_type; | ||
| 1416 | u_int y_field; | ||
| 1417 | { | ||
| 1418 | /* | ||
| 1419 | * For PA89 FPU's which implement the Compare Queue and | ||
| 1420 | * for PA2.0 FPU's, update the Compare Queue if the y-field = 0, | ||
| 1421 | * otherwise update the specified bit in the Compare Array. | ||
| 1422 | * Note that the y-field will always be 0 for non-PA2.0 FPU's. | ||
| 1423 | */ | ||
| 1424 | if ((fpu_type & TIMEX_EXTEN_FLAG) || | ||
| 1425 | (fpu_type & ROLEX_EXTEN_FLAG) || | ||
| 1426 | (fpu_type & PA2_0_FPU_FLAG)) { | ||
| 1427 | if (y_field == 0) { | ||
| 1428 | *status = ((*status & 0x04000000) >> 5) | /* old Cbit */ | ||
| 1429 | ((*status & 0x003ff000) >> 1) | /* old CQ */ | ||
| 1430 | (new_status & 0xffc007ff); /* all other bits*/ | ||
| 1431 | } else { | ||
| 1432 | *status = (*status & 0x04000000) | /* old Cbit */ | ||
| 1433 | ((new_status & 0x04000000) >> (y_field+4)) | | ||
| 1434 | (new_status & ~0x04000000 & /* other bits */ | ||
| 1435 | ~(0x04000000 >> (y_field+4))); | ||
| 1436 | } | ||
| 1437 | } | ||
| 1438 | /* if PA83, just update the C-bit */ | ||
| 1439 | else { | ||
| 1440 | *status = new_status; | ||
| 1441 | } | ||
| 1442 | } | ||
diff --git a/arch/parisc/math-emu/frnd.c b/arch/parisc/math-emu/frnd.c new file mode 100644 index 000000000000..904b3844bf26 --- /dev/null +++ b/arch/parisc/math-emu/frnd.c | |||
| @@ -0,0 +1,252 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * Purpose: | ||
| 25 | * Single Floating-point Round to Integer | ||
| 26 | * Double Floating-point Round to Integer | ||
| 27 | * Quad Floating-point Round to Integer (returns unimplemented) | ||
| 28 | * | ||
| 29 | * External Interfaces: | ||
| 30 | * dbl_frnd(srcptr,nullptr,dstptr,status) | ||
| 31 | * sgl_frnd(srcptr,nullptr,dstptr,status) | ||
| 32 | * | ||
| 33 | * END_DESC | ||
| 34 | */ | ||
| 35 | |||
| 36 | |||
| 37 | #include "float.h" | ||
| 38 | #include "sgl_float.h" | ||
| 39 | #include "dbl_float.h" | ||
| 40 | #include "cnv_float.h" | ||
| 41 | |||
| 42 | /* | ||
| 43 | * Single Floating-point Round to Integer | ||
| 44 | */ | ||
| 45 | |||
| 46 | /*ARGSUSED*/ | ||
| 47 | int | ||
| 48 | sgl_frnd(sgl_floating_point *srcptr, | ||
| 49 | unsigned int *nullptr, | ||
| 50 | sgl_floating_point *dstptr, | ||
| 51 | unsigned int *status) | ||
| 52 | { | ||
| 53 | register unsigned int src, result; | ||
| 54 | register int src_exponent; | ||
| 55 | register boolean inexact = FALSE; | ||
| 56 | |||
| 57 | src = *srcptr; | ||
| 58 | /* | ||
| 59 | * check source operand for NaN or infinity | ||
| 60 | */ | ||
| 61 | if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) { | ||
| 62 | /* | ||
| 63 | * is signaling NaN? | ||
| 64 | */ | ||
| 65 | if (Sgl_isone_signaling(src)) { | ||
| 66 | /* trap if INVALIDTRAP enabled */ | ||
| 67 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 68 | /* make NaN quiet */ | ||
| 69 | Set_invalidflag(); | ||
| 70 | Sgl_set_quiet(src); | ||
| 71 | } | ||
| 72 | /* | ||
| 73 | * return quiet NaN or infinity | ||
| 74 | */ | ||
| 75 | *dstptr = src; | ||
| 76 | return(NOEXCEPTION); | ||
| 77 | } | ||
| 78 | /* | ||
| 79 | * Need to round? | ||
| 80 | */ | ||
| 81 | if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) { | ||
| 82 | *dstptr = src; | ||
| 83 | return(NOEXCEPTION); | ||
| 84 | } | ||
| 85 | /* | ||
| 86 | * Generate result | ||
| 87 | */ | ||
| 88 | if (src_exponent >= 0) { | ||
| 89 | Sgl_clear_exponent_set_hidden(src); | ||
| 90 | result = src; | ||
| 91 | Sgl_rightshift(result,(SGL_P-1) - (src_exponent)); | ||
| 92 | /* check for inexact */ | ||
| 93 | if (Sgl_isinexact_to_fix(src,src_exponent)) { | ||
| 94 | inexact = TRUE; | ||
| 95 | /* round result */ | ||
| 96 | switch (Rounding_mode()) { | ||
| 97 | case ROUNDPLUS: | ||
| 98 | if (Sgl_iszero_sign(src)) Sgl_increment(result); | ||
| 99 | break; | ||
| 100 | case ROUNDMINUS: | ||
| 101 | if (Sgl_isone_sign(src)) Sgl_increment(result); | ||
| 102 | break; | ||
| 103 | case ROUNDNEAREST: | ||
| 104 | if (Sgl_isone_roundbit(src,src_exponent)) | ||
| 105 | if (Sgl_isone_stickybit(src,src_exponent) | ||
| 106 | || (Sgl_isone_lowmantissa(result))) | ||
| 107 | Sgl_increment(result); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | Sgl_leftshift(result,(SGL_P-1) - (src_exponent)); | ||
| 111 | if (Sgl_isone_hiddenoverflow(result)) | ||
| 112 | Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1)); | ||
| 113 | else Sgl_set_exponent(result,src_exponent + SGL_BIAS); | ||
| 114 | } | ||
| 115 | else { | ||
| 116 | result = src; /* set sign */ | ||
| 117 | Sgl_setzero_exponentmantissa(result); | ||
| 118 | /* check for inexact */ | ||
| 119 | if (Sgl_isnotzero_exponentmantissa(src)) { | ||
| 120 | inexact = TRUE; | ||
| 121 | /* round result */ | ||
| 122 | switch (Rounding_mode()) { | ||
| 123 | case ROUNDPLUS: | ||
| 124 | if (Sgl_iszero_sign(src)) | ||
| 125 | Sgl_set_exponent(result,SGL_BIAS); | ||
| 126 | break; | ||
| 127 | case ROUNDMINUS: | ||
| 128 | if (Sgl_isone_sign(src)) | ||
| 129 | Sgl_set_exponent(result,SGL_BIAS); | ||
| 130 | break; | ||
| 131 | case ROUNDNEAREST: | ||
| 132 | if (src_exponent == -1) | ||
| 133 | if (Sgl_isnotzero_mantissa(src)) | ||
| 134 | Sgl_set_exponent(result,SGL_BIAS); | ||
| 135 | } | ||
| 136 | } | ||
| 137 | } | ||
| 138 | *dstptr = result; | ||
| 139 | if (inexact) { | ||
| 140 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 141 | else Set_inexactflag(); | ||
| 142 | } | ||
| 143 | return(NOEXCEPTION); | ||
| 144 | } | ||
| 145 | |||
| 146 | /* | ||
| 147 | * Double Floating-point Round to Integer | ||
| 148 | */ | ||
| 149 | |||
| 150 | /*ARGSUSED*/ | ||
| 151 | int | ||
| 152 | dbl_frnd( | ||
| 153 | dbl_floating_point *srcptr, | ||
| 154 | unsigned int *nullptr, | ||
| 155 | dbl_floating_point *dstptr, | ||
| 156 | unsigned int *status) | ||
| 157 | { | ||
| 158 | register unsigned int srcp1, srcp2, resultp1, resultp2; | ||
| 159 | register int src_exponent; | ||
| 160 | register boolean inexact = FALSE; | ||
| 161 | |||
| 162 | Dbl_copyfromptr(srcptr,srcp1,srcp2); | ||
| 163 | /* | ||
| 164 | * check source operand for NaN or infinity | ||
| 165 | */ | ||
| 166 | if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) { | ||
| 167 | /* | ||
| 168 | * is signaling NaN? | ||
| 169 | */ | ||
| 170 | if (Dbl_isone_signaling(srcp1)) { | ||
| 171 | /* trap if INVALIDTRAP enabled */ | ||
| 172 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 173 | /* make NaN quiet */ | ||
| 174 | Set_invalidflag(); | ||
| 175 | Dbl_set_quiet(srcp1); | ||
| 176 | } | ||
| 177 | /* | ||
| 178 | * return quiet NaN or infinity | ||
| 179 | */ | ||
| 180 | Dbl_copytoptr(srcp1,srcp2,dstptr); | ||
| 181 | return(NOEXCEPTION); | ||
| 182 | } | ||
| 183 | /* | ||
| 184 | * Need to round? | ||
| 185 | */ | ||
| 186 | if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) { | ||
| 187 | Dbl_copytoptr(srcp1,srcp2,dstptr); | ||
| 188 | return(NOEXCEPTION); | ||
| 189 | } | ||
| 190 | /* | ||
| 191 | * Generate result | ||
| 192 | */ | ||
| 193 | if (src_exponent >= 0) { | ||
| 194 | Dbl_clear_exponent_set_hidden(srcp1); | ||
| 195 | resultp1 = srcp1; | ||
| 196 | resultp2 = srcp2; | ||
| 197 | Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent)); | ||
| 198 | /* check for inexact */ | ||
| 199 | if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) { | ||
| 200 | inexact = TRUE; | ||
| 201 | /* round result */ | ||
| 202 | switch (Rounding_mode()) { | ||
| 203 | case ROUNDPLUS: | ||
| 204 | if (Dbl_iszero_sign(srcp1)) | ||
| 205 | Dbl_increment(resultp1,resultp2); | ||
| 206 | break; | ||
| 207 | case ROUNDMINUS: | ||
| 208 | if (Dbl_isone_sign(srcp1)) | ||
| 209 | Dbl_increment(resultp1,resultp2); | ||
| 210 | break; | ||
| 211 | case ROUNDNEAREST: | ||
| 212 | if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent)) | ||
| 213 | if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) | ||
| 214 | || (Dbl_isone_lowmantissap2(resultp2))) | ||
| 215 | Dbl_increment(resultp1,resultp2); | ||
| 216 | } | ||
| 217 | } | ||
| 218 | Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent)); | ||
| 219 | if (Dbl_isone_hiddenoverflow(resultp1)) | ||
| 220 | Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1)); | ||
| 221 | else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS); | ||
| 222 | } | ||
| 223 | else { | ||
| 224 | resultp1 = srcp1; /* set sign */ | ||
| 225 | Dbl_setzero_exponentmantissa(resultp1,resultp2); | ||
| 226 | /* check for inexact */ | ||
| 227 | if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) { | ||
| 228 | inexact = TRUE; | ||
| 229 | /* round result */ | ||
| 230 | switch (Rounding_mode()) { | ||
| 231 | case ROUNDPLUS: | ||
| 232 | if (Dbl_iszero_sign(srcp1)) | ||
| 233 | Dbl_set_exponent(resultp1,DBL_BIAS); | ||
| 234 | break; | ||
| 235 | case ROUNDMINUS: | ||
| 236 | if (Dbl_isone_sign(srcp1)) | ||
| 237 | Dbl_set_exponent(resultp1,DBL_BIAS); | ||
| 238 | break; | ||
| 239 | case ROUNDNEAREST: | ||
| 240 | if (src_exponent == -1) | ||
| 241 | if (Dbl_isnotzero_mantissa(srcp1,srcp2)) | ||
| 242 | Dbl_set_exponent(resultp1,DBL_BIAS); | ||
| 243 | } | ||
| 244 | } | ||
| 245 | } | ||
| 246 | Dbl_copytoptr(resultp1,resultp2,dstptr); | ||
| 247 | if (inexact) { | ||
| 248 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 249 | else Set_inexactflag(); | ||
| 250 | } | ||
| 251 | return(NOEXCEPTION); | ||
| 252 | } | ||
diff --git a/arch/parisc/math-emu/hppa.h b/arch/parisc/math-emu/hppa.h new file mode 100644 index 000000000000..5d3d52f7323a --- /dev/null +++ b/arch/parisc/math-emu/hppa.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifdef __NO_PA_HDRS | ||
| 23 | PA header file -- do not include this header file for non-PA builds. | ||
| 24 | #endif | ||
| 25 | |||
| 26 | |||
| 27 | /* amount is assumed to be a constant between 0 and 32 (non-inclusive) */ | ||
| 28 | #define Shiftdouble(left,right,amount,dest) \ | ||
| 29 | /* int left, right, amount, dest; */ \ | ||
| 30 | dest = ((left) << (32-(amount))) | ((unsigned int)(right) >> (amount)) | ||
| 31 | |||
| 32 | /* amount must be less than 32 */ | ||
| 33 | #define Variableshiftdouble(left,right,amount,dest) \ | ||
| 34 | /* unsigned int left, right; int amount, dest; */ \ | ||
| 35 | if (amount == 0) dest = right; \ | ||
| 36 | else dest = ((((unsigned) left)&0x7fffffff) << (32-(amount))) | \ | ||
| 37 | ((unsigned) right >> (amount)) | ||
| 38 | |||
| 39 | /* amount must be between 0 and 32 (non-inclusive) */ | ||
| 40 | #define Variable_shift_double(left,right,amount,dest) \ | ||
| 41 | /* unsigned int left, right; int amount, dest; */ \ | ||
| 42 | dest = (left << (32-(amount))) | ((unsigned) right >> (amount)) | ||
diff --git a/arch/parisc/math-emu/math-emu.h b/arch/parisc/math-emu/math-emu.h new file mode 100644 index 000000000000..3a99f5929291 --- /dev/null +++ b/arch/parisc/math-emu/math-emu.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | #ifndef _PARISC_MATH_EMU_H | ||
| 22 | #define _PARISC_MATH_EMU_H | ||
| 23 | |||
| 24 | #include <asm/ptrace.h> | ||
| 25 | extern int handle_fpe(struct pt_regs *regs); | ||
| 26 | |||
| 27 | #endif | ||
diff --git a/arch/parisc/math-emu/sfadd.c b/arch/parisc/math-emu/sfadd.c new file mode 100644 index 000000000000..008d721b5d22 --- /dev/null +++ b/arch/parisc/math-emu/sfadd.c | |||
| @@ -0,0 +1,518 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/sfadd.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Single_add: add two single precision values. | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * sgl_fadd(leftptr, rightptr, dstptr, status) | ||
| 32 | * | ||
| 33 | * Internal Interfaces: | ||
| 34 | * | ||
| 35 | * Theory: | ||
| 36 | * <<please update with a overview of the operation of this file>> | ||
| 37 | * | ||
| 38 | * END_DESC | ||
| 39 | */ | ||
| 40 | |||
| 41 | |||
| 42 | #include "float.h" | ||
| 43 | #include "sgl_float.h" | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Single_add: add two single precision values. | ||
| 47 | */ | ||
| 48 | int | ||
| 49 | sgl_fadd( | ||
| 50 | sgl_floating_point *leftptr, | ||
| 51 | sgl_floating_point *rightptr, | ||
| 52 | sgl_floating_point *dstptr, | ||
| 53 | unsigned int *status) | ||
| 54 | { | ||
| 55 | register unsigned int left, right, result, extent; | ||
| 56 | register unsigned int signless_upper_left, signless_upper_right, save; | ||
| 57 | |||
| 58 | |||
| 59 | register int result_exponent, right_exponent, diff_exponent; | ||
| 60 | register int sign_save, jumpsize; | ||
| 61 | register boolean inexact = FALSE; | ||
| 62 | register boolean underflowtrap; | ||
| 63 | |||
| 64 | /* Create local copies of the numbers */ | ||
| 65 | left = *leftptr; | ||
| 66 | right = *rightptr; | ||
| 67 | |||
| 68 | /* A zero "save" helps discover equal operands (for later), * | ||
| 69 | * and is used in swapping operands (if needed). */ | ||
| 70 | Sgl_xortointp1(left,right,/*to*/save); | ||
| 71 | |||
| 72 | /* | ||
| 73 | * check first operand for NaN's or infinity | ||
| 74 | */ | ||
| 75 | if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT) | ||
| 76 | { | ||
| 77 | if (Sgl_iszero_mantissa(left)) | ||
| 78 | { | ||
| 79 | if (Sgl_isnotnan(right)) | ||
| 80 | { | ||
| 81 | if (Sgl_isinfinity(right) && save!=0) | ||
| 82 | { | ||
| 83 | /* | ||
| 84 | * invalid since operands are opposite signed infinity's | ||
| 85 | */ | ||
| 86 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 87 | Set_invalidflag(); | ||
| 88 | Sgl_makequietnan(result); | ||
| 89 | *dstptr = result; | ||
| 90 | return(NOEXCEPTION); | ||
| 91 | } | ||
| 92 | /* | ||
| 93 | * return infinity | ||
| 94 | */ | ||
| 95 | *dstptr = left; | ||
| 96 | return(NOEXCEPTION); | ||
| 97 | } | ||
| 98 | } | ||
| 99 | else | ||
| 100 | { | ||
| 101 | /* | ||
| 102 | * is NaN; signaling or quiet? | ||
| 103 | */ | ||
| 104 | if (Sgl_isone_signaling(left)) | ||
| 105 | { | ||
| 106 | /* trap if INVALIDTRAP enabled */ | ||
| 107 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 108 | /* make NaN quiet */ | ||
| 109 | Set_invalidflag(); | ||
| 110 | Sgl_set_quiet(left); | ||
| 111 | } | ||
| 112 | /* | ||
| 113 | * is second operand a signaling NaN? | ||
| 114 | */ | ||
| 115 | else if (Sgl_is_signalingnan(right)) | ||
| 116 | { | ||
| 117 | /* trap if INVALIDTRAP enabled */ | ||
| 118 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 119 | /* make NaN quiet */ | ||
| 120 | Set_invalidflag(); | ||
| 121 | Sgl_set_quiet(right); | ||
| 122 | *dstptr = right; | ||
| 123 | return(NOEXCEPTION); | ||
| 124 | } | ||
| 125 | /* | ||
| 126 | * return quiet NaN | ||
| 127 | */ | ||
| 128 | *dstptr = left; | ||
| 129 | return(NOEXCEPTION); | ||
| 130 | } | ||
| 131 | } /* End left NaN or Infinity processing */ | ||
| 132 | /* | ||
| 133 | * check second operand for NaN's or infinity | ||
| 134 | */ | ||
| 135 | if (Sgl_isinfinity_exponent(right)) | ||
| 136 | { | ||
| 137 | if (Sgl_iszero_mantissa(right)) | ||
| 138 | { | ||
| 139 | /* return infinity */ | ||
| 140 | *dstptr = right; | ||
| 141 | return(NOEXCEPTION); | ||
| 142 | } | ||
| 143 | /* | ||
| 144 | * is NaN; signaling or quiet? | ||
| 145 | */ | ||
| 146 | if (Sgl_isone_signaling(right)) | ||
| 147 | { | ||
| 148 | /* trap if INVALIDTRAP enabled */ | ||
| 149 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 150 | /* make NaN quiet */ | ||
| 151 | Set_invalidflag(); | ||
| 152 | Sgl_set_quiet(right); | ||
| 153 | } | ||
| 154 | /* | ||
| 155 | * return quiet NaN | ||
| 156 | */ | ||
| 157 | *dstptr = right; | ||
| 158 | return(NOEXCEPTION); | ||
| 159 | } /* End right NaN or Infinity processing */ | ||
| 160 | |||
| 161 | /* Invariant: Must be dealing with finite numbers */ | ||
| 162 | |||
| 163 | /* Compare operands by removing the sign */ | ||
| 164 | Sgl_copytoint_exponentmantissa(left,signless_upper_left); | ||
| 165 | Sgl_copytoint_exponentmantissa(right,signless_upper_right); | ||
| 166 | |||
| 167 | /* sign difference selects add or sub operation. */ | ||
| 168 | if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right)) | ||
| 169 | { | ||
| 170 | /* Set the left operand to the larger one by XOR swap * | ||
| 171 | * First finish the first word using "save" */ | ||
| 172 | Sgl_xorfromintp1(save,right,/*to*/right); | ||
| 173 | Sgl_xorfromintp1(save,left,/*to*/left); | ||
| 174 | result_exponent = Sgl_exponent(left); | ||
| 175 | } | ||
| 176 | /* Invariant: left is not smaller than right. */ | ||
| 177 | |||
| 178 | if((right_exponent = Sgl_exponent(right)) == 0) | ||
| 179 | { | ||
| 180 | /* Denormalized operands. First look for zeroes */ | ||
| 181 | if(Sgl_iszero_mantissa(right)) | ||
| 182 | { | ||
| 183 | /* right is zero */ | ||
| 184 | if(Sgl_iszero_exponentmantissa(left)) | ||
| 185 | { | ||
| 186 | /* Both operands are zeros */ | ||
| 187 | if(Is_rounding_mode(ROUNDMINUS)) | ||
| 188 | { | ||
| 189 | Sgl_or_signs(left,/*with*/right); | ||
| 190 | } | ||
| 191 | else | ||
| 192 | { | ||
| 193 | Sgl_and_signs(left,/*with*/right); | ||
| 194 | } | ||
| 195 | } | ||
| 196 | else | ||
| 197 | { | ||
| 198 | /* Left is not a zero and must be the result. Trapped | ||
| 199 | * underflows are signaled if left is denormalized. Result | ||
| 200 | * is always exact. */ | ||
| 201 | if( (result_exponent == 0) && Is_underflowtrap_enabled() ) | ||
| 202 | { | ||
| 203 | /* need to normalize results mantissa */ | ||
| 204 | sign_save = Sgl_signextendedsign(left); | ||
| 205 | Sgl_leftshiftby1(left); | ||
| 206 | Sgl_normalize(left,result_exponent); | ||
| 207 | Sgl_set_sign(left,/*using*/sign_save); | ||
| 208 | Sgl_setwrapped_exponent(left,result_exponent,unfl); | ||
| 209 | *dstptr = left; | ||
| 210 | return(UNDERFLOWEXCEPTION); | ||
| 211 | } | ||
| 212 | } | ||
| 213 | *dstptr = left; | ||
| 214 | return(NOEXCEPTION); | ||
| 215 | } | ||
| 216 | |||
| 217 | /* Neither are zeroes */ | ||
| 218 | Sgl_clear_sign(right); /* Exponent is already cleared */ | ||
| 219 | if(result_exponent == 0 ) | ||
| 220 | { | ||
| 221 | /* Both operands are denormalized. The result must be exact | ||
| 222 | * and is simply calculated. A sum could become normalized and a | ||
| 223 | * difference could cancel to a true zero. */ | ||
| 224 | if( (/*signed*/int) save < 0 ) | ||
| 225 | { | ||
| 226 | Sgl_subtract(left,/*minus*/right,/*into*/result); | ||
| 227 | if(Sgl_iszero_mantissa(result)) | ||
| 228 | { | ||
| 229 | if(Is_rounding_mode(ROUNDMINUS)) | ||
| 230 | { | ||
| 231 | Sgl_setone_sign(result); | ||
| 232 | } | ||
| 233 | else | ||
| 234 | { | ||
| 235 | Sgl_setzero_sign(result); | ||
| 236 | } | ||
| 237 | *dstptr = result; | ||
| 238 | return(NOEXCEPTION); | ||
| 239 | } | ||
| 240 | } | ||
| 241 | else | ||
| 242 | { | ||
| 243 | Sgl_addition(left,right,/*into*/result); | ||
| 244 | if(Sgl_isone_hidden(result)) | ||
| 245 | { | ||
| 246 | *dstptr = result; | ||
| 247 | return(NOEXCEPTION); | ||
| 248 | } | ||
| 249 | } | ||
| 250 | if(Is_underflowtrap_enabled()) | ||
| 251 | { | ||
| 252 | /* need to normalize result */ | ||
| 253 | sign_save = Sgl_signextendedsign(result); | ||
| 254 | Sgl_leftshiftby1(result); | ||
| 255 | Sgl_normalize(result,result_exponent); | ||
| 256 | Sgl_set_sign(result,/*using*/sign_save); | ||
| 257 | Sgl_setwrapped_exponent(result,result_exponent,unfl); | ||
| 258 | *dstptr = result; | ||
| 259 | return(UNDERFLOWEXCEPTION); | ||
| 260 | } | ||
| 261 | *dstptr = result; | ||
| 262 | return(NOEXCEPTION); | ||
| 263 | } | ||
| 264 | right_exponent = 1; /* Set exponent to reflect different bias | ||
| 265 | * with denomalized numbers. */ | ||
| 266 | } | ||
| 267 | else | ||
| 268 | { | ||
| 269 | Sgl_clear_signexponent_set_hidden(right); | ||
| 270 | } | ||
| 271 | Sgl_clear_exponent_set_hidden(left); | ||
| 272 | diff_exponent = result_exponent - right_exponent; | ||
| 273 | |||
| 274 | /* | ||
| 275 | * Special case alignment of operands that would force alignment | ||
| 276 | * beyond the extent of the extension. A further optimization | ||
| 277 | * could special case this but only reduces the path length for this | ||
| 278 | * infrequent case. | ||
| 279 | */ | ||
| 280 | if(diff_exponent > SGL_THRESHOLD) | ||
| 281 | { | ||
| 282 | diff_exponent = SGL_THRESHOLD; | ||
| 283 | } | ||
| 284 | |||
| 285 | /* Align right operand by shifting to right */ | ||
| 286 | Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent, | ||
| 287 | /*and lower to*/extent); | ||
| 288 | |||
| 289 | /* Treat sum and difference of the operands separately. */ | ||
| 290 | if( (/*signed*/int) save < 0 ) | ||
| 291 | { | ||
| 292 | /* | ||
| 293 | * Difference of the two operands. Their can be no overflow. A | ||
| 294 | * borrow can occur out of the hidden bit and force a post | ||
| 295 | * normalization phase. | ||
| 296 | */ | ||
| 297 | Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result); | ||
| 298 | if(Sgl_iszero_hidden(result)) | ||
| 299 | { | ||
| 300 | /* Handle normalization */ | ||
| 301 | /* A straight foward algorithm would now shift the result | ||
| 302 | * and extension left until the hidden bit becomes one. Not | ||
| 303 | * all of the extension bits need participate in the shift. | ||
| 304 | * Only the two most significant bits (round and guard) are | ||
| 305 | * needed. If only a single shift is needed then the guard | ||
| 306 | * bit becomes a significant low order bit and the extension | ||
| 307 | * must participate in the rounding. If more than a single | ||
| 308 | * shift is needed, then all bits to the right of the guard | ||
| 309 | * bit are zeros, and the guard bit may or may not be zero. */ | ||
| 310 | sign_save = Sgl_signextendedsign(result); | ||
| 311 | Sgl_leftshiftby1_withextent(result,extent,result); | ||
| 312 | |||
| 313 | /* Need to check for a zero result. The sign and exponent | ||
| 314 | * fields have already been zeroed. The more efficient test | ||
| 315 | * of the full object can be used. | ||
| 316 | */ | ||
| 317 | if(Sgl_iszero(result)) | ||
| 318 | /* Must have been "x-x" or "x+(-x)". */ | ||
| 319 | { | ||
| 320 | if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result); | ||
| 321 | *dstptr = result; | ||
| 322 | return(NOEXCEPTION); | ||
| 323 | } | ||
| 324 | result_exponent--; | ||
| 325 | /* Look to see if normalization is finished. */ | ||
| 326 | if(Sgl_isone_hidden(result)) | ||
| 327 | { | ||
| 328 | if(result_exponent==0) | ||
| 329 | { | ||
| 330 | /* Denormalized, exponent should be zero. Left operand * | ||
| 331 | * was normalized, so extent (guard, round) was zero */ | ||
| 332 | goto underflow; | ||
| 333 | } | ||
| 334 | else | ||
| 335 | { | ||
| 336 | /* No further normalization is needed. */ | ||
| 337 | Sgl_set_sign(result,/*using*/sign_save); | ||
| 338 | Ext_leftshiftby1(extent); | ||
| 339 | goto round; | ||
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 343 | /* Check for denormalized, exponent should be zero. Left * | ||
| 344 | * operand was normalized, so extent (guard, round) was zero */ | ||
| 345 | if(!(underflowtrap = Is_underflowtrap_enabled()) && | ||
| 346 | result_exponent==0) goto underflow; | ||
| 347 | |||
| 348 | /* Shift extension to complete one bit of normalization and | ||
| 349 | * update exponent. */ | ||
| 350 | Ext_leftshiftby1(extent); | ||
| 351 | |||
| 352 | /* Discover first one bit to determine shift amount. Use a | ||
| 353 | * modified binary search. We have already shifted the result | ||
| 354 | * one position right and still not found a one so the remainder | ||
| 355 | * of the extension must be zero and simplifies rounding. */ | ||
| 356 | /* Scan bytes */ | ||
| 357 | while(Sgl_iszero_hiddenhigh7mantissa(result)) | ||
| 358 | { | ||
| 359 | Sgl_leftshiftby8(result); | ||
| 360 | if((result_exponent -= 8) <= 0 && !underflowtrap) | ||
| 361 | goto underflow; | ||
| 362 | } | ||
| 363 | /* Now narrow it down to the nibble */ | ||
| 364 | if(Sgl_iszero_hiddenhigh3mantissa(result)) | ||
| 365 | { | ||
| 366 | /* The lower nibble contains the normalizing one */ | ||
| 367 | Sgl_leftshiftby4(result); | ||
| 368 | if((result_exponent -= 4) <= 0 && !underflowtrap) | ||
| 369 | goto underflow; | ||
| 370 | } | ||
| 371 | /* Select case were first bit is set (already normalized) | ||
| 372 | * otherwise select the proper shift. */ | ||
| 373 | if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7) | ||
| 374 | { | ||
| 375 | /* Already normalized */ | ||
| 376 | if(result_exponent <= 0) goto underflow; | ||
| 377 | Sgl_set_sign(result,/*using*/sign_save); | ||
| 378 | Sgl_set_exponent(result,/*using*/result_exponent); | ||
| 379 | *dstptr = result; | ||
| 380 | return(NOEXCEPTION); | ||
| 381 | } | ||
| 382 | Sgl_sethigh4bits(result,/*using*/sign_save); | ||
| 383 | switch(jumpsize) | ||
| 384 | { | ||
| 385 | case 1: | ||
| 386 | { | ||
| 387 | Sgl_leftshiftby3(result); | ||
| 388 | result_exponent -= 3; | ||
| 389 | break; | ||
| 390 | } | ||
| 391 | case 2: | ||
| 392 | case 3: | ||
| 393 | { | ||
| 394 | Sgl_leftshiftby2(result); | ||
| 395 | result_exponent -= 2; | ||
| 396 | break; | ||
| 397 | } | ||
| 398 | case 4: | ||
| 399 | case 5: | ||
| 400 | case 6: | ||
| 401 | case 7: | ||
| 402 | { | ||
| 403 | Sgl_leftshiftby1(result); | ||
| 404 | result_exponent -= 1; | ||
| 405 | break; | ||
| 406 | } | ||
| 407 | } | ||
| 408 | if(result_exponent > 0) | ||
| 409 | { | ||
| 410 | Sgl_set_exponent(result,/*using*/result_exponent); | ||
| 411 | *dstptr = result; | ||
| 412 | return(NOEXCEPTION); /* Sign bit is already set */ | ||
| 413 | } | ||
| 414 | /* Fixup potential underflows */ | ||
| 415 | underflow: | ||
| 416 | if(Is_underflowtrap_enabled()) | ||
| 417 | { | ||
| 418 | Sgl_set_sign(result,sign_save); | ||
| 419 | Sgl_setwrapped_exponent(result,result_exponent,unfl); | ||
| 420 | *dstptr = result; | ||
| 421 | /* inexact = FALSE; */ | ||
| 422 | return(UNDERFLOWEXCEPTION); | ||
| 423 | } | ||
| 424 | /* | ||
| 425 | * Since we cannot get an inexact denormalized result, | ||
| 426 | * we can now return. | ||
| 427 | */ | ||
| 428 | Sgl_right_align(result,/*by*/(1-result_exponent),extent); | ||
| 429 | Sgl_clear_signexponent(result); | ||
| 430 | Sgl_set_sign(result,sign_save); | ||
| 431 | *dstptr = result; | ||
| 432 | return(NOEXCEPTION); | ||
| 433 | } /* end if(hidden...)... */ | ||
| 434 | /* Fall through and round */ | ||
| 435 | } /* end if(save < 0)... */ | ||
| 436 | else | ||
| 437 | { | ||
| 438 | /* Add magnitudes */ | ||
| 439 | Sgl_addition(left,right,/*to*/result); | ||
| 440 | if(Sgl_isone_hiddenoverflow(result)) | ||
| 441 | { | ||
| 442 | /* Prenormalization required. */ | ||
| 443 | Sgl_rightshiftby1_withextent(result,extent,extent); | ||
| 444 | Sgl_arithrightshiftby1(result); | ||
| 445 | result_exponent++; | ||
| 446 | } /* end if hiddenoverflow... */ | ||
| 447 | } /* end else ...add magnitudes... */ | ||
| 448 | |||
| 449 | /* Round the result. If the extension is all zeros,then the result is | ||
| 450 | * exact. Otherwise round in the correct direction. No underflow is | ||
| 451 | * possible. If a postnormalization is necessary, then the mantissa is | ||
| 452 | * all zeros so no shift is needed. */ | ||
| 453 | round: | ||
| 454 | if(Ext_isnotzero(extent)) | ||
| 455 | { | ||
| 456 | inexact = TRUE; | ||
| 457 | switch(Rounding_mode()) | ||
| 458 | { | ||
| 459 | case ROUNDNEAREST: /* The default. */ | ||
| 460 | if(Ext_isone_sign(extent)) | ||
| 461 | { | ||
| 462 | /* at least 1/2 ulp */ | ||
| 463 | if(Ext_isnotzero_lower(extent) || | ||
| 464 | Sgl_isone_lowmantissa(result)) | ||
| 465 | { | ||
| 466 | /* either exactly half way and odd or more than 1/2ulp */ | ||
| 467 | Sgl_increment(result); | ||
| 468 | } | ||
| 469 | } | ||
| 470 | break; | ||
| 471 | |||
| 472 | case ROUNDPLUS: | ||
| 473 | if(Sgl_iszero_sign(result)) | ||
| 474 | { | ||
| 475 | /* Round up positive results */ | ||
| 476 | Sgl_increment(result); | ||
| 477 | } | ||
| 478 | break; | ||
| 479 | |||
| 480 | case ROUNDMINUS: | ||
| 481 | if(Sgl_isone_sign(result)) | ||
| 482 | { | ||
| 483 | /* Round down negative results */ | ||
| 484 | Sgl_increment(result); | ||
| 485 | } | ||
| 486 | |||
| 487 | case ROUNDZERO:; | ||
| 488 | /* truncate is simple */ | ||
| 489 | } /* end switch... */ | ||
| 490 | if(Sgl_isone_hiddenoverflow(result)) result_exponent++; | ||
| 491 | } | ||
| 492 | if(result_exponent == SGL_INFINITY_EXPONENT) | ||
| 493 | { | ||
| 494 | /* Overflow */ | ||
| 495 | if(Is_overflowtrap_enabled()) | ||
| 496 | { | ||
| 497 | Sgl_setwrapped_exponent(result,result_exponent,ovfl); | ||
| 498 | *dstptr = result; | ||
| 499 | if (inexact) | ||
| 500 | if (Is_inexacttrap_enabled()) | ||
| 501 | return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
| 502 | else Set_inexactflag(); | ||
| 503 | return(OVERFLOWEXCEPTION); | ||
| 504 | } | ||
| 505 | else | ||
| 506 | { | ||
| 507 | Set_overflowflag(); | ||
| 508 | inexact = TRUE; | ||
| 509 | Sgl_setoverflow(result); | ||
| 510 | } | ||
| 511 | } | ||
| 512 | else Sgl_set_exponent(result,result_exponent); | ||
| 513 | *dstptr = result; | ||
| 514 | if(inexact) | ||
| 515 | if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 516 | else Set_inexactflag(); | ||
| 517 | return(NOEXCEPTION); | ||
| 518 | } | ||
diff --git a/arch/parisc/math-emu/sfcmp.c b/arch/parisc/math-emu/sfcmp.c new file mode 100644 index 000000000000..1466fb46e4c0 --- /dev/null +++ b/arch/parisc/math-emu/sfcmp.c | |||
| @@ -0,0 +1,155 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/sfcmp.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * sgl_cmp: compare two values | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * sgl_fcmp(leftptr, rightptr, cond, status) | ||
| 32 | * | ||
| 33 | * Internal Interfaces: | ||
| 34 | * | ||
| 35 | * Theory: | ||
| 36 | * <<please update with a overview of the operation of this file>> | ||
| 37 | * | ||
| 38 | * END_DESC | ||
| 39 | */ | ||
| 40 | |||
| 41 | |||
| 42 | #include "float.h" | ||
| 43 | #include "sgl_float.h" | ||
| 44 | |||
| 45 | /* | ||
| 46 | * sgl_cmp: compare two values | ||
| 47 | */ | ||
| 48 | int | ||
| 49 | sgl_fcmp (sgl_floating_point * leftptr, sgl_floating_point * rightptr, | ||
| 50 | unsigned int cond, unsigned int *status) | ||
| 51 | |||
| 52 | /* The predicate to be tested */ | ||
| 53 | |||
| 54 | { | ||
| 55 | register unsigned int left, right; | ||
| 56 | register int xorresult; | ||
| 57 | |||
| 58 | /* Create local copies of the numbers */ | ||
| 59 | left = *leftptr; | ||
| 60 | right = *rightptr; | ||
| 61 | |||
| 62 | /* | ||
| 63 | * Test for NaN | ||
| 64 | */ | ||
| 65 | if( (Sgl_exponent(left) == SGL_INFINITY_EXPONENT) | ||
| 66 | || (Sgl_exponent(right) == SGL_INFINITY_EXPONENT) ) | ||
| 67 | { | ||
| 68 | /* Check if a NaN is involved. Signal an invalid exception when | ||
| 69 | * comparing a signaling NaN or when comparing quiet NaNs and the | ||
| 70 | * low bit of the condition is set */ | ||
| 71 | if( ( (Sgl_exponent(left) == SGL_INFINITY_EXPONENT) | ||
| 72 | && Sgl_isnotzero_mantissa(left) | ||
| 73 | && (Exception(cond) || Sgl_isone_signaling(left))) | ||
| 74 | || | ||
| 75 | ( (Sgl_exponent(right) == SGL_INFINITY_EXPONENT) | ||
| 76 | && Sgl_isnotzero_mantissa(right) | ||
| 77 | && (Exception(cond) || Sgl_isone_signaling(right)) ) ) | ||
| 78 | { | ||
| 79 | if( Is_invalidtrap_enabled() ) { | ||
| 80 | Set_status_cbit(Unordered(cond)); | ||
| 81 | return(INVALIDEXCEPTION); | ||
| 82 | } | ||
| 83 | else Set_invalidflag(); | ||
| 84 | Set_status_cbit(Unordered(cond)); | ||
| 85 | return(NOEXCEPTION); | ||
| 86 | } | ||
| 87 | /* All the exceptional conditions are handled, now special case | ||
| 88 | NaN compares */ | ||
| 89 | else if( ((Sgl_exponent(left) == SGL_INFINITY_EXPONENT) | ||
| 90 | && Sgl_isnotzero_mantissa(left)) | ||
| 91 | || | ||
| 92 | ((Sgl_exponent(right) == SGL_INFINITY_EXPONENT) | ||
| 93 | && Sgl_isnotzero_mantissa(right)) ) | ||
| 94 | { | ||
| 95 | /* NaNs always compare unordered. */ | ||
| 96 | Set_status_cbit(Unordered(cond)); | ||
| 97 | return(NOEXCEPTION); | ||
| 98 | } | ||
| 99 | /* infinities will drop down to the normal compare mechanisms */ | ||
| 100 | } | ||
| 101 | /* First compare for unequal signs => less or greater or | ||
| 102 | * special equal case */ | ||
| 103 | Sgl_xortointp1(left,right,xorresult); | ||
| 104 | if( xorresult < 0 ) | ||
| 105 | { | ||
| 106 | /* left negative => less, left positive => greater. | ||
| 107 | * equal is possible if both operands are zeros. */ | ||
| 108 | if( Sgl_iszero_exponentmantissa(left) | ||
| 109 | && Sgl_iszero_exponentmantissa(right) ) | ||
| 110 | { | ||
| 111 | Set_status_cbit(Equal(cond)); | ||
| 112 | } | ||
| 113 | else if( Sgl_isone_sign(left) ) | ||
| 114 | { | ||
| 115 | Set_status_cbit(Lessthan(cond)); | ||
| 116 | } | ||
| 117 | else | ||
| 118 | { | ||
| 119 | Set_status_cbit(Greaterthan(cond)); | ||
| 120 | } | ||
| 121 | } | ||
| 122 | /* Signs are the same. Treat negative numbers separately | ||
| 123 | * from the positives because of the reversed sense. */ | ||
| 124 | else if( Sgl_all(left) == Sgl_all(right) ) | ||
| 125 | { | ||
| 126 | Set_status_cbit(Equal(cond)); | ||
| 127 | } | ||
| 128 | else if( Sgl_iszero_sign(left) ) | ||
| 129 | { | ||
| 130 | /* Positive compare */ | ||
| 131 | if( Sgl_all(left) < Sgl_all(right) ) | ||
| 132 | { | ||
| 133 | Set_status_cbit(Lessthan(cond)); | ||
| 134 | } | ||
| 135 | else | ||
| 136 | { | ||
| 137 | Set_status_cbit(Greaterthan(cond)); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | else | ||
| 141 | { | ||
| 142 | /* Negative compare. Signed or unsigned compares | ||
| 143 | * both work the same. That distinction is only | ||
| 144 | * important when the sign bits differ. */ | ||
| 145 | if( Sgl_all(left) > Sgl_all(right) ) | ||
| 146 | { | ||
| 147 | Set_status_cbit(Lessthan(cond)); | ||
| 148 | } | ||
| 149 | else | ||
| 150 | { | ||
| 151 | Set_status_cbit(Greaterthan(cond)); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | return(NOEXCEPTION); | ||
| 155 | } | ||
diff --git a/arch/parisc/math-emu/sfdiv.c b/arch/parisc/math-emu/sfdiv.c new file mode 100644 index 000000000000..3e2a4d6daa9c --- /dev/null +++ b/arch/parisc/math-emu/sfdiv.c | |||
| @@ -0,0 +1,392 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/sfdiv.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Single Precision Floating-point Divide | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * sgl_fdiv(srcptr1,srcptr2,dstptr,status) | ||
| 32 | * | ||
| 33 | * Internal Interfaces: | ||
| 34 | * | ||
| 35 | * Theory: | ||
| 36 | * <<please update with a overview of the operation of this file>> | ||
| 37 | * | ||
| 38 | * END_DESC | ||
| 39 | */ | ||
| 40 | |||
| 41 | |||
| 42 | #include "float.h" | ||
| 43 | #include "sgl_float.h" | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Single Precision Floating-point Divide | ||
| 47 | */ | ||
| 48 | |||
| 49 | int | ||
| 50 | sgl_fdiv (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2, | ||
| 51 | sgl_floating_point * dstptr, unsigned int *status) | ||
| 52 | { | ||
| 53 | register unsigned int opnd1, opnd2, opnd3, result; | ||
| 54 | register int dest_exponent, count; | ||
| 55 | register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; | ||
| 56 | boolean is_tiny; | ||
| 57 | |||
| 58 | opnd1 = *srcptr1; | ||
| 59 | opnd2 = *srcptr2; | ||
| 60 | /* | ||
| 61 | * set sign bit of result | ||
| 62 | */ | ||
| 63 | if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result); | ||
| 64 | else Sgl_setzero(result); | ||
| 65 | /* | ||
| 66 | * check first operand for NaN's or infinity | ||
| 67 | */ | ||
| 68 | if (Sgl_isinfinity_exponent(opnd1)) { | ||
| 69 | if (Sgl_iszero_mantissa(opnd1)) { | ||
| 70 | if (Sgl_isnotnan(opnd2)) { | ||
| 71 | if (Sgl_isinfinity(opnd2)) { | ||
| 72 | /* | ||
| 73 | * invalid since both operands | ||
| 74 | * are infinity | ||
| 75 | */ | ||
| 76 | if (Is_invalidtrap_enabled()) | ||
| 77 | return(INVALIDEXCEPTION); | ||
| 78 | Set_invalidflag(); | ||
| 79 | Sgl_makequietnan(result); | ||
| 80 | *dstptr = result; | ||
| 81 | return(NOEXCEPTION); | ||
| 82 | } | ||
| 83 | /* | ||
| 84 | * return infinity | ||
| 85 | */ | ||
| 86 | Sgl_setinfinity_exponentmantissa(result); | ||
| 87 | *dstptr = result; | ||
| 88 | return(NOEXCEPTION); | ||
| 89 | } | ||
| 90 | } | ||
| 91 | else { | ||
| 92 | /* | ||
| 93 | * is NaN; signaling or quiet? | ||
| 94 | */ | ||
| 95 | if (Sgl_isone_signaling(opnd1)) { | ||
| 96 | /* trap if INVALIDTRAP enabled */ | ||
| 97 | if (Is_invalidtrap_enabled()) | ||
| 98 | return(INVALIDEXCEPTION); | ||
| 99 | /* make NaN quiet */ | ||
| 100 | Set_invalidflag(); | ||
| 101 | Sgl_set_quiet(opnd1); | ||
| 102 | } | ||
| 103 | /* | ||
| 104 | * is second operand a signaling NaN? | ||
| 105 | */ | ||
| 106 | else if (Sgl_is_signalingnan(opnd2)) { | ||
| 107 | /* trap if INVALIDTRAP enabled */ | ||
| 108 | if (Is_invalidtrap_enabled()) | ||
| 109 | return(INVALIDEXCEPTION); | ||
| 110 | /* make NaN quiet */ | ||
| 111 | Set_invalidflag(); | ||
| 112 | Sgl_set_quiet(opnd2); | ||
| 113 | *dstptr = opnd2; | ||
| 114 | return(NOEXCEPTION); | ||
| 115 | } | ||
| 116 | /* | ||
| 117 | * return quiet NaN | ||
| 118 | */ | ||
| 119 | *dstptr = opnd1; | ||
| 120 | return(NOEXCEPTION); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | /* | ||
| 124 | * check second operand for NaN's or infinity | ||
| 125 | */ | ||
| 126 | if (Sgl_isinfinity_exponent(opnd2)) { | ||
| 127 | if (Sgl_iszero_mantissa(opnd2)) { | ||
| 128 | /* | ||
| 129 | * return zero | ||
| 130 | */ | ||
| 131 | Sgl_setzero_exponentmantissa(result); | ||
| 132 | *dstptr = result; | ||
| 133 | return(NOEXCEPTION); | ||
| 134 | } | ||
| 135 | /* | ||
| 136 | * is NaN; signaling or quiet? | ||
| 137 | */ | ||
| 138 | if (Sgl_isone_signaling(opnd2)) { | ||
| 139 | /* trap if INVALIDTRAP enabled */ | ||
| 140 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 141 | /* make NaN quiet */ | ||
| 142 | Set_invalidflag(); | ||
| 143 | Sgl_set_quiet(opnd2); | ||
| 144 | } | ||
| 145 | /* | ||
| 146 | * return quiet NaN | ||
| 147 | */ | ||
| 148 | *dstptr = opnd2; | ||
| 149 | return(NOEXCEPTION); | ||
| 150 | } | ||
| 151 | /* | ||
| 152 | * check for division by zero | ||
| 153 | */ | ||
| 154 | if (Sgl_iszero_exponentmantissa(opnd2)) { | ||
| 155 | if (Sgl_iszero_exponentmantissa(opnd1)) { | ||
| 156 | /* invalid since both operands are zero */ | ||
| 157 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 158 | Set_invalidflag(); | ||
| 159 | Sgl_makequietnan(result); | ||
| 160 | *dstptr = result; | ||
| 161 | return(NOEXCEPTION); | ||
| 162 | } | ||
| 163 | if (Is_divisionbyzerotrap_enabled()) | ||
| 164 | return(DIVISIONBYZEROEXCEPTION); | ||
| 165 | Set_divisionbyzeroflag(); | ||
| 166 | Sgl_setinfinity_exponentmantissa(result); | ||
| 167 | *dstptr = result; | ||
| 168 | return(NOEXCEPTION); | ||
| 169 | } | ||
| 170 | /* | ||
| 171 | * Generate exponent | ||
| 172 | */ | ||
| 173 | dest_exponent = Sgl_exponent(opnd1) - Sgl_exponent(opnd2) + SGL_BIAS; | ||
| 174 | |||
| 175 | /* | ||
| 176 | * Generate mantissa | ||
| 177 | */ | ||
| 178 | if (Sgl_isnotzero_exponent(opnd1)) { | ||
| 179 | /* set hidden bit */ | ||
| 180 | Sgl_clear_signexponent_set_hidden(opnd1); | ||
| 181 | } | ||
| 182 | else { | ||
| 183 | /* check for zero */ | ||
| 184 | if (Sgl_iszero_mantissa(opnd1)) { | ||
| 185 | Sgl_setzero_exponentmantissa(result); | ||
| 186 | *dstptr = result; | ||
| 187 | return(NOEXCEPTION); | ||
| 188 | } | ||
| 189 | /* is denormalized; want to normalize */ | ||
| 190 | Sgl_clear_signexponent(opnd1); | ||
| 191 | Sgl_leftshiftby1(opnd1); | ||
| 192 | Sgl_normalize(opnd1,dest_exponent); | ||
| 193 | } | ||
| 194 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
| 195 | if (Sgl_isnotzero_exponent(opnd2)) { | ||
| 196 | Sgl_clear_signexponent_set_hidden(opnd2); | ||
| 197 | } | ||
| 198 | else { | ||
| 199 | /* is denormalized; want to normalize */ | ||
| 200 | Sgl_clear_signexponent(opnd2); | ||
| 201 | Sgl_leftshiftby1(opnd2); | ||
| 202 | while(Sgl_iszero_hiddenhigh7mantissa(opnd2)) { | ||
| 203 | Sgl_leftshiftby8(opnd2); | ||
| 204 | dest_exponent += 8; | ||
| 205 | } | ||
| 206 | if(Sgl_iszero_hiddenhigh3mantissa(opnd2)) { | ||
| 207 | Sgl_leftshiftby4(opnd2); | ||
| 208 | dest_exponent += 4; | ||
| 209 | } | ||
| 210 | while(Sgl_iszero_hidden(opnd2)) { | ||
| 211 | Sgl_leftshiftby1(opnd2); | ||
| 212 | dest_exponent += 1; | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | /* Divide the source mantissas */ | ||
| 217 | |||
| 218 | /* | ||
| 219 | * A non_restoring divide algorithm is used. | ||
| 220 | */ | ||
| 221 | Sgl_subtract(opnd1,opnd2,opnd1); | ||
| 222 | Sgl_setzero(opnd3); | ||
| 223 | for (count=1;count<=SGL_P && Sgl_all(opnd1);count++) { | ||
| 224 | Sgl_leftshiftby1(opnd1); | ||
| 225 | Sgl_leftshiftby1(opnd3); | ||
| 226 | if (Sgl_iszero_sign(opnd1)) { | ||
| 227 | Sgl_setone_lowmantissa(opnd3); | ||
| 228 | Sgl_subtract(opnd1,opnd2,opnd1); | ||
| 229 | } | ||
| 230 | else Sgl_addition(opnd1,opnd2,opnd1); | ||
| 231 | } | ||
| 232 | if (count <= SGL_P) { | ||
| 233 | Sgl_leftshiftby1(opnd3); | ||
| 234 | Sgl_setone_lowmantissa(opnd3); | ||
| 235 | Sgl_leftshift(opnd3,SGL_P-count); | ||
| 236 | if (Sgl_iszero_hidden(opnd3)) { | ||
| 237 | Sgl_leftshiftby1(opnd3); | ||
| 238 | dest_exponent--; | ||
| 239 | } | ||
| 240 | } | ||
| 241 | else { | ||
| 242 | if (Sgl_iszero_hidden(opnd3)) { | ||
| 243 | /* need to get one more bit of result */ | ||
| 244 | Sgl_leftshiftby1(opnd1); | ||
| 245 | Sgl_leftshiftby1(opnd3); | ||
| 246 | if (Sgl_iszero_sign(opnd1)) { | ||
| 247 | Sgl_setone_lowmantissa(opnd3); | ||
| 248 | Sgl_subtract(opnd1,opnd2,opnd1); | ||
| 249 | } | ||
| 250 | else Sgl_addition(opnd1,opnd2,opnd1); | ||
| 251 | dest_exponent--; | ||
| 252 | } | ||
| 253 | if (Sgl_iszero_sign(opnd1)) guardbit = TRUE; | ||
| 254 | stickybit = Sgl_all(opnd1); | ||
| 255 | } | ||
| 256 | inexact = guardbit | stickybit; | ||
| 257 | |||
| 258 | /* | ||
| 259 | * round result | ||
| 260 | */ | ||
| 261 | if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) { | ||
| 262 | Sgl_clear_signexponent(opnd3); | ||
| 263 | switch (Rounding_mode()) { | ||
| 264 | case ROUNDPLUS: | ||
| 265 | if (Sgl_iszero_sign(result)) | ||
| 266 | Sgl_increment_mantissa(opnd3); | ||
| 267 | break; | ||
| 268 | case ROUNDMINUS: | ||
| 269 | if (Sgl_isone_sign(result)) | ||
| 270 | Sgl_increment_mantissa(opnd3); | ||
| 271 | break; | ||
| 272 | case ROUNDNEAREST: | ||
| 273 | if (guardbit) { | ||
| 274 | if (stickybit || Sgl_isone_lowmantissa(opnd3)) | ||
| 275 | Sgl_increment_mantissa(opnd3); | ||
| 276 | } | ||
| 277 | } | ||
| 278 | if (Sgl_isone_hidden(opnd3)) dest_exponent++; | ||
| 279 | } | ||
| 280 | Sgl_set_mantissa(result,opnd3); | ||
| 281 | |||
| 282 | /* | ||
| 283 | * Test for overflow | ||
| 284 | */ | ||
| 285 | if (dest_exponent >= SGL_INFINITY_EXPONENT) { | ||
| 286 | /* trap if OVERFLOWTRAP enabled */ | ||
| 287 | if (Is_overflowtrap_enabled()) { | ||
| 288 | /* | ||
| 289 | * Adjust bias of result | ||
| 290 | */ | ||
| 291 | Sgl_setwrapped_exponent(result,dest_exponent,ovfl); | ||
| 292 | *dstptr = result; | ||
| 293 | if (inexact) | ||
| 294 | if (Is_inexacttrap_enabled()) | ||
| 295 | return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
| 296 | else Set_inexactflag(); | ||
| 297 | return(OVERFLOWEXCEPTION); | ||
| 298 | } | ||
| 299 | Set_overflowflag(); | ||
| 300 | /* set result to infinity or largest number */ | ||
| 301 | Sgl_setoverflow(result); | ||
| 302 | inexact = TRUE; | ||
| 303 | } | ||
| 304 | /* | ||
| 305 | * Test for underflow | ||
| 306 | */ | ||
| 307 | else if (dest_exponent <= 0) { | ||
| 308 | /* trap if UNDERFLOWTRAP enabled */ | ||
| 309 | if (Is_underflowtrap_enabled()) { | ||
| 310 | /* | ||
| 311 | * Adjust bias of result | ||
| 312 | */ | ||
| 313 | Sgl_setwrapped_exponent(result,dest_exponent,unfl); | ||
| 314 | *dstptr = result; | ||
| 315 | if (inexact) | ||
| 316 | if (Is_inexacttrap_enabled()) | ||
| 317 | return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
| 318 | else Set_inexactflag(); | ||
| 319 | return(UNDERFLOWEXCEPTION); | ||
| 320 | } | ||
| 321 | |||
| 322 | /* Determine if should set underflow flag */ | ||
| 323 | is_tiny = TRUE; | ||
| 324 | if (dest_exponent == 0 && inexact) { | ||
| 325 | switch (Rounding_mode()) { | ||
| 326 | case ROUNDPLUS: | ||
| 327 | if (Sgl_iszero_sign(result)) { | ||
| 328 | Sgl_increment(opnd3); | ||
| 329 | if (Sgl_isone_hiddenoverflow(opnd3)) | ||
| 330 | is_tiny = FALSE; | ||
| 331 | Sgl_decrement(opnd3); | ||
| 332 | } | ||
| 333 | break; | ||
| 334 | case ROUNDMINUS: | ||
| 335 | if (Sgl_isone_sign(result)) { | ||
| 336 | Sgl_increment(opnd3); | ||
| 337 | if (Sgl_isone_hiddenoverflow(opnd3)) | ||
| 338 | is_tiny = FALSE; | ||
| 339 | Sgl_decrement(opnd3); | ||
| 340 | } | ||
| 341 | break; | ||
| 342 | case ROUNDNEAREST: | ||
| 343 | if (guardbit && (stickybit || | ||
| 344 | Sgl_isone_lowmantissa(opnd3))) { | ||
| 345 | Sgl_increment(opnd3); | ||
| 346 | if (Sgl_isone_hiddenoverflow(opnd3)) | ||
| 347 | is_tiny = FALSE; | ||
| 348 | Sgl_decrement(opnd3); | ||
| 349 | } | ||
| 350 | break; | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | /* | ||
| 355 | * denormalize result or set to signed zero | ||
| 356 | */ | ||
| 357 | stickybit = inexact; | ||
| 358 | Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact); | ||
| 359 | |||
| 360 | /* return rounded number */ | ||
| 361 | if (inexact) { | ||
| 362 | switch (Rounding_mode()) { | ||
| 363 | case ROUNDPLUS: | ||
| 364 | if (Sgl_iszero_sign(result)) { | ||
| 365 | Sgl_increment(opnd3); | ||
| 366 | } | ||
| 367 | break; | ||
| 368 | case ROUNDMINUS: | ||
| 369 | if (Sgl_isone_sign(result)) { | ||
| 370 | Sgl_increment(opnd3); | ||
| 371 | } | ||
| 372 | break; | ||
| 373 | case ROUNDNEAREST: | ||
| 374 | if (guardbit && (stickybit || | ||
| 375 | Sgl_isone_lowmantissa(opnd3))) { | ||
| 376 | Sgl_increment(opnd3); | ||
| 377 | } | ||
| 378 | break; | ||
| 379 | } | ||
| 380 | if (is_tiny) Set_underflowflag(); | ||
| 381 | } | ||
| 382 | Sgl_set_exponentmantissa(result,opnd3); | ||
| 383 | } | ||
| 384 | else Sgl_set_exponent(result,dest_exponent); | ||
| 385 | *dstptr = result; | ||
| 386 | /* check for inexact */ | ||
| 387 | if (inexact) { | ||
| 388 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 389 | else Set_inexactflag(); | ||
| 390 | } | ||
| 391 | return(NOEXCEPTION); | ||
| 392 | } | ||
diff --git a/arch/parisc/math-emu/sfmpy.c b/arch/parisc/math-emu/sfmpy.c new file mode 100644 index 000000000000..afa406983335 --- /dev/null +++ b/arch/parisc/math-emu/sfmpy.c | |||
| @@ -0,0 +1,380 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/sfmpy.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Single Precision Floating-point Multiply | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * sgl_fmpy(srcptr1,srcptr2,dstptr,status) | ||
| 32 | * | ||
| 33 | * Internal Interfaces: | ||
| 34 | * | ||
| 35 | * Theory: | ||
| 36 | * <<please update with a overview of the operation of this file>> | ||
| 37 | * | ||
| 38 | * END_DESC | ||
| 39 | */ | ||
| 40 | |||
| 41 | |||
| 42 | #include "float.h" | ||
| 43 | #include "sgl_float.h" | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Single Precision Floating-point Multiply | ||
| 47 | */ | ||
| 48 | |||
| 49 | int | ||
| 50 | sgl_fmpy( | ||
| 51 | sgl_floating_point *srcptr1, | ||
| 52 | sgl_floating_point *srcptr2, | ||
| 53 | sgl_floating_point *dstptr, | ||
| 54 | unsigned int *status) | ||
| 55 | { | ||
| 56 | register unsigned int opnd1, opnd2, opnd3, result; | ||
| 57 | register int dest_exponent, count; | ||
| 58 | register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; | ||
| 59 | boolean is_tiny; | ||
| 60 | |||
| 61 | opnd1 = *srcptr1; | ||
| 62 | opnd2 = *srcptr2; | ||
| 63 | /* | ||
| 64 | * set sign bit of result | ||
| 65 | */ | ||
| 66 | if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result); | ||
| 67 | else Sgl_setzero(result); | ||
| 68 | /* | ||
| 69 | * check first operand for NaN's or infinity | ||
| 70 | */ | ||
| 71 | if (Sgl_isinfinity_exponent(opnd1)) { | ||
| 72 | if (Sgl_iszero_mantissa(opnd1)) { | ||
| 73 | if (Sgl_isnotnan(opnd2)) { | ||
| 74 | if (Sgl_iszero_exponentmantissa(opnd2)) { | ||
| 75 | /* | ||
| 76 | * invalid since operands are infinity | ||
| 77 | * and zero | ||
| 78 | */ | ||
| 79 | if (Is_invalidtrap_enabled()) | ||
| 80 | return(INVALIDEXCEPTION); | ||
| 81 | Set_invalidflag(); | ||
| 82 | Sgl_makequietnan(result); | ||
| 83 | *dstptr = result; | ||
| 84 | return(NOEXCEPTION); | ||
| 85 | } | ||
| 86 | /* | ||
| 87 | * return infinity | ||
| 88 | */ | ||
| 89 | Sgl_setinfinity_exponentmantissa(result); | ||
| 90 | *dstptr = result; | ||
| 91 | return(NOEXCEPTION); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | else { | ||
| 95 | /* | ||
| 96 | * is NaN; signaling or quiet? | ||
| 97 | */ | ||
| 98 | if (Sgl_isone_signaling(opnd1)) { | ||
| 99 | /* trap if INVALIDTRAP enabled */ | ||
| 100 | if (Is_invalidtrap_enabled()) | ||
| 101 | return(INVALIDEXCEPTION); | ||
| 102 | /* make NaN quiet */ | ||
| 103 | Set_invalidflag(); | ||
| 104 | Sgl_set_quiet(opnd1); | ||
| 105 | } | ||
| 106 | /* | ||
| 107 | * is second operand a signaling NaN? | ||
| 108 | */ | ||
| 109 | else if (Sgl_is_signalingnan(opnd2)) { | ||
| 110 | /* trap if INVALIDTRAP enabled */ | ||
| 111 | if (Is_invalidtrap_enabled()) | ||
| 112 | return(INVALIDEXCEPTION); | ||
| 113 | /* make NaN quiet */ | ||
| 114 | Set_invalidflag(); | ||
| 115 | Sgl_set_quiet(opnd2); | ||
| 116 | *dstptr = opnd2; | ||
| 117 | return(NOEXCEPTION); | ||
| 118 | } | ||
| 119 | /* | ||
| 120 | * return quiet NaN | ||
| 121 | */ | ||
| 122 | *dstptr = opnd1; | ||
| 123 | return(NOEXCEPTION); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | /* | ||
| 127 | * check second operand for NaN's or infinity | ||
| 128 | */ | ||
| 129 | if (Sgl_isinfinity_exponent(opnd2)) { | ||
| 130 | if (Sgl_iszero_mantissa(opnd2)) { | ||
| 131 | if (Sgl_iszero_exponentmantissa(opnd1)) { | ||
| 132 | /* invalid since operands are zero & infinity */ | ||
| 133 | if (Is_invalidtrap_enabled()) | ||
| 134 | return(INVALIDEXCEPTION); | ||
| 135 | Set_invalidflag(); | ||
| 136 | Sgl_makequietnan(opnd2); | ||
| 137 | *dstptr = opnd2; | ||
| 138 | return(NOEXCEPTION); | ||
| 139 | } | ||
| 140 | /* | ||
| 141 | * return infinity | ||
| 142 | */ | ||
| 143 | Sgl_setinfinity_exponentmantissa(result); | ||
| 144 | *dstptr = result; | ||
| 145 | return(NOEXCEPTION); | ||
| 146 | } | ||
| 147 | /* | ||
| 148 | * is NaN; signaling or quiet? | ||
| 149 | */ | ||
| 150 | if (Sgl_isone_signaling(opnd2)) { | ||
| 151 | /* trap if INVALIDTRAP enabled */ | ||
| 152 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 153 | |||
| 154 | /* make NaN quiet */ | ||
| 155 | Set_invalidflag(); | ||
| 156 | Sgl_set_quiet(opnd2); | ||
| 157 | } | ||
| 158 | /* | ||
| 159 | * return quiet NaN | ||
| 160 | */ | ||
| 161 | *dstptr = opnd2; | ||
| 162 | return(NOEXCEPTION); | ||
| 163 | } | ||
| 164 | /* | ||
| 165 | * Generate exponent | ||
| 166 | */ | ||
| 167 | dest_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS; | ||
| 168 | |||
| 169 | /* | ||
| 170 | * Generate mantissa | ||
| 171 | */ | ||
| 172 | if (Sgl_isnotzero_exponent(opnd1)) { | ||
| 173 | /* set hidden bit */ | ||
| 174 | Sgl_clear_signexponent_set_hidden(opnd1); | ||
| 175 | } | ||
| 176 | else { | ||
| 177 | /* check for zero */ | ||
| 178 | if (Sgl_iszero_mantissa(opnd1)) { | ||
| 179 | Sgl_setzero_exponentmantissa(result); | ||
| 180 | *dstptr = result; | ||
| 181 | return(NOEXCEPTION); | ||
| 182 | } | ||
| 183 | /* is denormalized, adjust exponent */ | ||
| 184 | Sgl_clear_signexponent(opnd1); | ||
| 185 | Sgl_leftshiftby1(opnd1); | ||
| 186 | Sgl_normalize(opnd1,dest_exponent); | ||
| 187 | } | ||
| 188 | /* opnd2 needs to have hidden bit set with msb in hidden bit */ | ||
| 189 | if (Sgl_isnotzero_exponent(opnd2)) { | ||
| 190 | Sgl_clear_signexponent_set_hidden(opnd2); | ||
| 191 | } | ||
| 192 | else { | ||
| 193 | /* check for zero */ | ||
| 194 | if (Sgl_iszero_mantissa(opnd2)) { | ||
| 195 | Sgl_setzero_exponentmantissa(result); | ||
| 196 | *dstptr = result; | ||
| 197 | return(NOEXCEPTION); | ||
| 198 | } | ||
| 199 | /* is denormalized; want to normalize */ | ||
| 200 | Sgl_clear_signexponent(opnd2); | ||
| 201 | Sgl_leftshiftby1(opnd2); | ||
| 202 | Sgl_normalize(opnd2,dest_exponent); | ||
| 203 | } | ||
| 204 | |||
| 205 | /* Multiply two source mantissas together */ | ||
| 206 | |||
| 207 | Sgl_leftshiftby4(opnd2); /* make room for guard bits */ | ||
| 208 | Sgl_setzero(opnd3); | ||
| 209 | /* | ||
| 210 | * Four bits at a time are inspected in each loop, and a | ||
| 211 | * simple shift and add multiply algorithm is used. | ||
| 212 | */ | ||
| 213 | for (count=1;count<SGL_P;count+=4) { | ||
| 214 | stickybit |= Slow4(opnd3); | ||
| 215 | Sgl_rightshiftby4(opnd3); | ||
| 216 | if (Sbit28(opnd1)) Sall(opnd3) += (Sall(opnd2) << 3); | ||
| 217 | if (Sbit29(opnd1)) Sall(opnd3) += (Sall(opnd2) << 2); | ||
| 218 | if (Sbit30(opnd1)) Sall(opnd3) += (Sall(opnd2) << 1); | ||
| 219 | if (Sbit31(opnd1)) Sall(opnd3) += Sall(opnd2); | ||
| 220 | Sgl_rightshiftby4(opnd1); | ||
| 221 | } | ||
| 222 | /* make sure result is left-justified */ | ||
| 223 | if (Sgl_iszero_sign(opnd3)) { | ||
| 224 | Sgl_leftshiftby1(opnd3); | ||
| 225 | } | ||
| 226 | else { | ||
| 227 | /* result mantissa >= 2. */ | ||
| 228 | dest_exponent++; | ||
| 229 | } | ||
| 230 | /* check for denormalized result */ | ||
| 231 | while (Sgl_iszero_sign(opnd3)) { | ||
| 232 | Sgl_leftshiftby1(opnd3); | ||
| 233 | dest_exponent--; | ||
| 234 | } | ||
| 235 | /* | ||
| 236 | * check for guard, sticky and inexact bits | ||
| 237 | */ | ||
| 238 | stickybit |= Sgl_all(opnd3) << (SGL_BITLENGTH - SGL_EXP_LENGTH + 1); | ||
| 239 | guardbit = Sbit24(opnd3); | ||
| 240 | inexact = guardbit | stickybit; | ||
| 241 | |||
| 242 | /* re-align mantissa */ | ||
| 243 | Sgl_rightshiftby8(opnd3); | ||
| 244 | |||
| 245 | /* | ||
| 246 | * round result | ||
| 247 | */ | ||
| 248 | if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) { | ||
| 249 | Sgl_clear_signexponent(opnd3); | ||
| 250 | switch (Rounding_mode()) { | ||
| 251 | case ROUNDPLUS: | ||
| 252 | if (Sgl_iszero_sign(result)) | ||
| 253 | Sgl_increment(opnd3); | ||
| 254 | break; | ||
| 255 | case ROUNDMINUS: | ||
| 256 | if (Sgl_isone_sign(result)) | ||
| 257 | Sgl_increment(opnd3); | ||
| 258 | break; | ||
| 259 | case ROUNDNEAREST: | ||
| 260 | if (guardbit) { | ||
| 261 | if (stickybit || Sgl_isone_lowmantissa(opnd3)) | ||
| 262 | Sgl_increment(opnd3); | ||
| 263 | } | ||
| 264 | } | ||
| 265 | if (Sgl_isone_hidden(opnd3)) dest_exponent++; | ||
| 266 | } | ||
| 267 | Sgl_set_mantissa(result,opnd3); | ||
| 268 | |||
| 269 | /* | ||
| 270 | * Test for overflow | ||
| 271 | */ | ||
| 272 | if (dest_exponent >= SGL_INFINITY_EXPONENT) { | ||
| 273 | /* trap if OVERFLOWTRAP enabled */ | ||
| 274 | if (Is_overflowtrap_enabled()) { | ||
| 275 | /* | ||
| 276 | * Adjust bias of result | ||
| 277 | */ | ||
| 278 | Sgl_setwrapped_exponent(result,dest_exponent,ovfl); | ||
| 279 | *dstptr = result; | ||
| 280 | if (inexact) | ||
| 281 | if (Is_inexacttrap_enabled()) | ||
| 282 | return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
| 283 | else Set_inexactflag(); | ||
| 284 | return(OVERFLOWEXCEPTION); | ||
| 285 | } | ||
| 286 | inexact = TRUE; | ||
| 287 | Set_overflowflag(); | ||
| 288 | /* set result to infinity or largest number */ | ||
| 289 | Sgl_setoverflow(result); | ||
| 290 | } | ||
| 291 | /* | ||
| 292 | * Test for underflow | ||
| 293 | */ | ||
| 294 | else if (dest_exponent <= 0) { | ||
| 295 | /* trap if UNDERFLOWTRAP enabled */ | ||
| 296 | if (Is_underflowtrap_enabled()) { | ||
| 297 | /* | ||
| 298 | * Adjust bias of result | ||
| 299 | */ | ||
| 300 | Sgl_setwrapped_exponent(result,dest_exponent,unfl); | ||
| 301 | *dstptr = result; | ||
| 302 | if (inexact) | ||
| 303 | if (Is_inexacttrap_enabled()) | ||
| 304 | return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
| 305 | else Set_inexactflag(); | ||
| 306 | return(UNDERFLOWEXCEPTION); | ||
| 307 | } | ||
| 308 | |||
| 309 | /* Determine if should set underflow flag */ | ||
| 310 | is_tiny = TRUE; | ||
| 311 | if (dest_exponent == 0 && inexact) { | ||
| 312 | switch (Rounding_mode()) { | ||
| 313 | case ROUNDPLUS: | ||
| 314 | if (Sgl_iszero_sign(result)) { | ||
| 315 | Sgl_increment(opnd3); | ||
| 316 | if (Sgl_isone_hiddenoverflow(opnd3)) | ||
| 317 | is_tiny = FALSE; | ||
| 318 | Sgl_decrement(opnd3); | ||
| 319 | } | ||
| 320 | break; | ||
| 321 | case ROUNDMINUS: | ||
| 322 | if (Sgl_isone_sign(result)) { | ||
| 323 | Sgl_increment(opnd3); | ||
| 324 | if (Sgl_isone_hiddenoverflow(opnd3)) | ||
| 325 | is_tiny = FALSE; | ||
| 326 | Sgl_decrement(opnd3); | ||
| 327 | } | ||
| 328 | break; | ||
| 329 | case ROUNDNEAREST: | ||
| 330 | if (guardbit && (stickybit || | ||
| 331 | Sgl_isone_lowmantissa(opnd3))) { | ||
| 332 | Sgl_increment(opnd3); | ||
| 333 | if (Sgl_isone_hiddenoverflow(opnd3)) | ||
| 334 | is_tiny = FALSE; | ||
| 335 | Sgl_decrement(opnd3); | ||
| 336 | } | ||
| 337 | break; | ||
| 338 | } | ||
| 339 | } | ||
| 340 | |||
| 341 | /* | ||
| 342 | * denormalize result or set to signed zero | ||
| 343 | */ | ||
| 344 | stickybit = inexact; | ||
| 345 | Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact); | ||
| 346 | |||
| 347 | /* return zero or smallest number */ | ||
| 348 | if (inexact) { | ||
| 349 | switch (Rounding_mode()) { | ||
| 350 | case ROUNDPLUS: | ||
| 351 | if (Sgl_iszero_sign(result)) { | ||
| 352 | Sgl_increment(opnd3); | ||
| 353 | } | ||
| 354 | break; | ||
| 355 | case ROUNDMINUS: | ||
| 356 | if (Sgl_isone_sign(result)) { | ||
| 357 | Sgl_increment(opnd3); | ||
| 358 | } | ||
| 359 | break; | ||
| 360 | case ROUNDNEAREST: | ||
| 361 | if (guardbit && (stickybit || | ||
| 362 | Sgl_isone_lowmantissa(opnd3))) { | ||
| 363 | Sgl_increment(opnd3); | ||
| 364 | } | ||
| 365 | break; | ||
| 366 | } | ||
| 367 | if (is_tiny) Set_underflowflag(); | ||
| 368 | } | ||
| 369 | Sgl_set_exponentmantissa(result,opnd3); | ||
| 370 | } | ||
| 371 | else Sgl_set_exponent(result,dest_exponent); | ||
| 372 | *dstptr = result; | ||
| 373 | |||
| 374 | /* check for inexact */ | ||
| 375 | if (inexact) { | ||
| 376 | if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 377 | else Set_inexactflag(); | ||
| 378 | } | ||
| 379 | return(NOEXCEPTION); | ||
| 380 | } | ||
diff --git a/arch/parisc/math-emu/sfrem.c b/arch/parisc/math-emu/sfrem.c new file mode 100644 index 000000000000..3a1b7a34d87a --- /dev/null +++ b/arch/parisc/math-emu/sfrem.c | |||
| @@ -0,0 +1,290 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/sfrem.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Single Precision Floating-point Remainder | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * sgl_frem(srcptr1,srcptr2,dstptr,status) | ||
| 32 | * | ||
| 33 | * Internal Interfaces: | ||
| 34 | * | ||
| 35 | * Theory: | ||
| 36 | * <<please update with a overview of the operation of this file>> | ||
| 37 | * | ||
| 38 | * END_DESC | ||
| 39 | */ | ||
| 40 | |||
| 41 | |||
| 42 | |||
| 43 | #include "float.h" | ||
| 44 | #include "sgl_float.h" | ||
| 45 | |||
| 46 | /* | ||
| 47 | * Single Precision Floating-point Remainder | ||
| 48 | */ | ||
| 49 | |||
| 50 | int | ||
| 51 | sgl_frem (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2, | ||
| 52 | sgl_floating_point * dstptr, unsigned int *status) | ||
| 53 | { | ||
| 54 | register unsigned int opnd1, opnd2, result; | ||
| 55 | register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount; | ||
| 56 | register boolean roundup = FALSE; | ||
| 57 | |||
| 58 | opnd1 = *srcptr1; | ||
| 59 | opnd2 = *srcptr2; | ||
| 60 | /* | ||
| 61 | * check first operand for NaN's or infinity | ||
| 62 | */ | ||
| 63 | if ((opnd1_exponent = Sgl_exponent(opnd1)) == SGL_INFINITY_EXPONENT) { | ||
| 64 | if (Sgl_iszero_mantissa(opnd1)) { | ||
| 65 | if (Sgl_isnotnan(opnd2)) { | ||
| 66 | /* invalid since first operand is infinity */ | ||
| 67 | if (Is_invalidtrap_enabled()) | ||
| 68 | return(INVALIDEXCEPTION); | ||
| 69 | Set_invalidflag(); | ||
| 70 | Sgl_makequietnan(result); | ||
| 71 | *dstptr = result; | ||
| 72 | return(NOEXCEPTION); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | else { | ||
| 76 | /* | ||
| 77 | * is NaN; signaling or quiet? | ||
| 78 | */ | ||
| 79 | if (Sgl_isone_signaling(opnd1)) { | ||
| 80 | /* trap if INVALIDTRAP enabled */ | ||
| 81 | if (Is_invalidtrap_enabled()) | ||
| 82 | return(INVALIDEXCEPTION); | ||
| 83 | /* make NaN quiet */ | ||
| 84 | Set_invalidflag(); | ||
| 85 | Sgl_set_quiet(opnd1); | ||
| 86 | } | ||
| 87 | /* | ||
| 88 | * is second operand a signaling NaN? | ||
| 89 | */ | ||
| 90 | else if (Sgl_is_signalingnan(opnd2)) { | ||
| 91 | /* trap if INVALIDTRAP enabled */ | ||
| 92 | if (Is_invalidtrap_enabled()) | ||
| 93 | return(INVALIDEXCEPTION); | ||
| 94 | /* make NaN quiet */ | ||
| 95 | Set_invalidflag(); | ||
| 96 | Sgl_set_quiet(opnd2); | ||
| 97 | *dstptr = opnd2; | ||
| 98 | return(NOEXCEPTION); | ||
| 99 | } | ||
| 100 | /* | ||
| 101 | * return quiet NaN | ||
| 102 | */ | ||
| 103 | *dstptr = opnd1; | ||
| 104 | return(NOEXCEPTION); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | /* | ||
| 108 | * check second operand for NaN's or infinity | ||
| 109 | */ | ||
| 110 | if ((opnd2_exponent = Sgl_exponent(opnd2)) == SGL_INFINITY_EXPONENT) { | ||
| 111 | if (Sgl_iszero_mantissa(opnd2)) { | ||
| 112 | /* | ||
| 113 | * return first operand | ||
| 114 | */ | ||
| 115 | *dstptr = opnd1; | ||
| 116 | return(NOEXCEPTION); | ||
| 117 | } | ||
| 118 | /* | ||
| 119 | * is NaN; signaling or quiet? | ||
| 120 | */ | ||
| 121 | if (Sgl_isone_signaling(opnd2)) { | ||
| 122 | /* trap if INVALIDTRAP enabled */ | ||
| 123 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 124 | /* make NaN quiet */ | ||
| 125 | Set_invalidflag(); | ||
| 126 | Sgl_set_quiet(opnd2); | ||
| 127 | } | ||
| 128 | /* | ||
| 129 | * return quiet NaN | ||
| 130 | */ | ||
| 131 | *dstptr = opnd2; | ||
| 132 | return(NOEXCEPTION); | ||
| 133 | } | ||
| 134 | /* | ||
| 135 | * check second operand for zero | ||
| 136 | */ | ||
| 137 | if (Sgl_iszero_exponentmantissa(opnd2)) { | ||
| 138 | /* invalid since second operand is zero */ | ||
| 139 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 140 | Set_invalidflag(); | ||
| 141 | Sgl_makequietnan(result); | ||
| 142 | *dstptr = result; | ||
| 143 | return(NOEXCEPTION); | ||
| 144 | } | ||
| 145 | |||
| 146 | /* | ||
| 147 | * get sign of result | ||
| 148 | */ | ||
| 149 | result = opnd1; | ||
| 150 | |||
| 151 | /* | ||
| 152 | * check for denormalized operands | ||
| 153 | */ | ||
| 154 | if (opnd1_exponent == 0) { | ||
| 155 | /* check for zero */ | ||
| 156 | if (Sgl_iszero_mantissa(opnd1)) { | ||
| 157 | *dstptr = opnd1; | ||
| 158 | return(NOEXCEPTION); | ||
| 159 | } | ||
| 160 | /* normalize, then continue */ | ||
| 161 | opnd1_exponent = 1; | ||
| 162 | Sgl_normalize(opnd1,opnd1_exponent); | ||
| 163 | } | ||
| 164 | else { | ||
| 165 | Sgl_clear_signexponent_set_hidden(opnd1); | ||
| 166 | } | ||
| 167 | if (opnd2_exponent == 0) { | ||
| 168 | /* normalize, then continue */ | ||
| 169 | opnd2_exponent = 1; | ||
| 170 | Sgl_normalize(opnd2,opnd2_exponent); | ||
| 171 | } | ||
| 172 | else { | ||
| 173 | Sgl_clear_signexponent_set_hidden(opnd2); | ||
| 174 | } | ||
| 175 | |||
| 176 | /* find result exponent and divide step loop count */ | ||
| 177 | dest_exponent = opnd2_exponent - 1; | ||
| 178 | stepcount = opnd1_exponent - opnd2_exponent; | ||
| 179 | |||
| 180 | /* | ||
| 181 | * check for opnd1/opnd2 < 1 | ||
| 182 | */ | ||
| 183 | if (stepcount < 0) { | ||
| 184 | /* | ||
| 185 | * check for opnd1/opnd2 > 1/2 | ||
| 186 | * | ||
| 187 | * In this case n will round to 1, so | ||
| 188 | * r = opnd1 - opnd2 | ||
| 189 | */ | ||
| 190 | if (stepcount == -1 && Sgl_isgreaterthan(opnd1,opnd2)) { | ||
| 191 | Sgl_all(result) = ~Sgl_all(result); /* set sign */ | ||
| 192 | /* align opnd2 with opnd1 */ | ||
| 193 | Sgl_leftshiftby1(opnd2); | ||
| 194 | Sgl_subtract(opnd2,opnd1,opnd2); | ||
| 195 | /* now normalize */ | ||
| 196 | while (Sgl_iszero_hidden(opnd2)) { | ||
| 197 | Sgl_leftshiftby1(opnd2); | ||
| 198 | dest_exponent--; | ||
| 199 | } | ||
| 200 | Sgl_set_exponentmantissa(result,opnd2); | ||
| 201 | goto testforunderflow; | ||
| 202 | } | ||
| 203 | /* | ||
| 204 | * opnd1/opnd2 <= 1/2 | ||
| 205 | * | ||
| 206 | * In this case n will round to zero, so | ||
| 207 | * r = opnd1 | ||
| 208 | */ | ||
| 209 | Sgl_set_exponentmantissa(result,opnd1); | ||
| 210 | dest_exponent = opnd1_exponent; | ||
| 211 | goto testforunderflow; | ||
| 212 | } | ||
| 213 | |||
| 214 | /* | ||
| 215 | * Generate result | ||
| 216 | * | ||
| 217 | * Do iterative subtract until remainder is less than operand 2. | ||
| 218 | */ | ||
| 219 | while (stepcount-- > 0 && Sgl_all(opnd1)) { | ||
| 220 | if (Sgl_isnotlessthan(opnd1,opnd2)) | ||
| 221 | Sgl_subtract(opnd1,opnd2,opnd1); | ||
| 222 | Sgl_leftshiftby1(opnd1); | ||
| 223 | } | ||
| 224 | /* | ||
| 225 | * Do last subtract, then determine which way to round if remainder | ||
| 226 | * is exactly 1/2 of opnd2 | ||
| 227 | */ | ||
| 228 | if (Sgl_isnotlessthan(opnd1,opnd2)) { | ||
| 229 | Sgl_subtract(opnd1,opnd2,opnd1); | ||
| 230 | roundup = TRUE; | ||
| 231 | } | ||
| 232 | if (stepcount > 0 || Sgl_iszero(opnd1)) { | ||
| 233 | /* division is exact, remainder is zero */ | ||
| 234 | Sgl_setzero_exponentmantissa(result); | ||
| 235 | *dstptr = result; | ||
| 236 | return(NOEXCEPTION); | ||
| 237 | } | ||
| 238 | |||
| 239 | /* | ||
| 240 | * Check for cases where opnd1/opnd2 < n | ||
| 241 | * | ||
| 242 | * In this case the result's sign will be opposite that of | ||
| 243 | * opnd1. The mantissa also needs some correction. | ||
| 244 | */ | ||
| 245 | Sgl_leftshiftby1(opnd1); | ||
| 246 | if (Sgl_isgreaterthan(opnd1,opnd2)) { | ||
| 247 | Sgl_invert_sign(result); | ||
| 248 | Sgl_subtract((opnd2<<1),opnd1,opnd1); | ||
| 249 | } | ||
| 250 | /* check for remainder being exactly 1/2 of opnd2 */ | ||
| 251 | else if (Sgl_isequal(opnd1,opnd2) && roundup) { | ||
| 252 | Sgl_invert_sign(result); | ||
| 253 | } | ||
| 254 | |||
| 255 | /* normalize result's mantissa */ | ||
| 256 | while (Sgl_iszero_hidden(opnd1)) { | ||
| 257 | dest_exponent--; | ||
| 258 | Sgl_leftshiftby1(opnd1); | ||
| 259 | } | ||
| 260 | Sgl_set_exponentmantissa(result,opnd1); | ||
| 261 | |||
| 262 | /* | ||
| 263 | * Test for underflow | ||
| 264 | */ | ||
| 265 | testforunderflow: | ||
| 266 | if (dest_exponent <= 0) { | ||
| 267 | /* trap if UNDERFLOWTRAP enabled */ | ||
| 268 | if (Is_underflowtrap_enabled()) { | ||
| 269 | /* | ||
| 270 | * Adjust bias of result | ||
| 271 | */ | ||
| 272 | Sgl_setwrapped_exponent(result,dest_exponent,unfl); | ||
| 273 | *dstptr = result; | ||
| 274 | /* frem is always exact */ | ||
| 275 | return(UNDERFLOWEXCEPTION); | ||
| 276 | } | ||
| 277 | /* | ||
| 278 | * denormalize result or set to signed zero | ||
| 279 | */ | ||
| 280 | if (dest_exponent >= (1 - SGL_P)) { | ||
| 281 | Sgl_rightshift_exponentmantissa(result,1-dest_exponent); | ||
| 282 | } | ||
| 283 | else { | ||
| 284 | Sgl_setzero_exponentmantissa(result); | ||
| 285 | } | ||
| 286 | } | ||
| 287 | else Sgl_set_exponent(result,dest_exponent); | ||
| 288 | *dstptr = result; | ||
| 289 | return(NOEXCEPTION); | ||
| 290 | } | ||
diff --git a/arch/parisc/math-emu/sfsqrt.c b/arch/parisc/math-emu/sfsqrt.c new file mode 100644 index 000000000000..cd3f6db1f6fb --- /dev/null +++ b/arch/parisc/math-emu/sfsqrt.c | |||
| @@ -0,0 +1,187 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/sfsqrt.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Single Floating-point Square Root | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * sgl_fsqrt(srcptr,nullptr,dstptr,status) | ||
| 32 | * | ||
| 33 | * Internal Interfaces: | ||
| 34 | * | ||
| 35 | * Theory: | ||
| 36 | * <<please update with a overview of the operation of this file>> | ||
| 37 | * | ||
| 38 | * END_DESC | ||
| 39 | */ | ||
| 40 | |||
| 41 | |||
| 42 | #include "float.h" | ||
| 43 | #include "sgl_float.h" | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Single Floating-point Square Root | ||
| 47 | */ | ||
| 48 | |||
| 49 | /*ARGSUSED*/ | ||
| 50 | unsigned int | ||
| 51 | sgl_fsqrt( | ||
| 52 | sgl_floating_point *srcptr, | ||
| 53 | unsigned int *nullptr, | ||
| 54 | sgl_floating_point *dstptr, | ||
| 55 | unsigned int *status) | ||
| 56 | { | ||
| 57 | register unsigned int src, result; | ||
| 58 | register int src_exponent; | ||
| 59 | register unsigned int newbit, sum; | ||
| 60 | register boolean guardbit = FALSE, even_exponent; | ||
| 61 | |||
| 62 | src = *srcptr; | ||
| 63 | /* | ||
| 64 | * check source operand for NaN or infinity | ||
| 65 | */ | ||
| 66 | if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) { | ||
| 67 | /* | ||
| 68 | * is signaling NaN? | ||
| 69 | */ | ||
| 70 | if (Sgl_isone_signaling(src)) { | ||
| 71 | /* trap if INVALIDTRAP enabled */ | ||
| 72 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 73 | /* make NaN quiet */ | ||
| 74 | Set_invalidflag(); | ||
| 75 | Sgl_set_quiet(src); | ||
| 76 | } | ||
| 77 | /* | ||
| 78 | * Return quiet NaN or positive infinity. | ||
| 79 | * Fall thru to negative test if negative infinity. | ||
| 80 | */ | ||
| 81 | if (Sgl_iszero_sign(src) || Sgl_isnotzero_mantissa(src)) { | ||
| 82 | *dstptr = src; | ||
| 83 | return(NOEXCEPTION); | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | /* | ||
| 88 | * check for zero source operand | ||
| 89 | */ | ||
| 90 | if (Sgl_iszero_exponentmantissa(src)) { | ||
| 91 | *dstptr = src; | ||
| 92 | return(NOEXCEPTION); | ||
| 93 | } | ||
| 94 | |||
| 95 | /* | ||
| 96 | * check for negative source operand | ||
| 97 | */ | ||
| 98 | if (Sgl_isone_sign(src)) { | ||
| 99 | /* trap if INVALIDTRAP enabled */ | ||
| 100 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 101 | /* make NaN quiet */ | ||
| 102 | Set_invalidflag(); | ||
| 103 | Sgl_makequietnan(src); | ||
| 104 | *dstptr = src; | ||
| 105 | return(NOEXCEPTION); | ||
| 106 | } | ||
| 107 | |||
| 108 | /* | ||
| 109 | * Generate result | ||
| 110 | */ | ||
| 111 | if (src_exponent > 0) { | ||
| 112 | even_exponent = Sgl_hidden(src); | ||
| 113 | Sgl_clear_signexponent_set_hidden(src); | ||
| 114 | } | ||
| 115 | else { | ||
| 116 | /* normalize operand */ | ||
| 117 | Sgl_clear_signexponent(src); | ||
| 118 | src_exponent++; | ||
| 119 | Sgl_normalize(src,src_exponent); | ||
| 120 | even_exponent = src_exponent & 1; | ||
| 121 | } | ||
| 122 | if (even_exponent) { | ||
| 123 | /* exponent is even */ | ||
| 124 | /* Add comment here. Explain why odd exponent needs correction */ | ||
| 125 | Sgl_leftshiftby1(src); | ||
| 126 | } | ||
| 127 | /* | ||
| 128 | * Add comment here. Explain following algorithm. | ||
| 129 | * | ||
| 130 | * Trust me, it works. | ||
| 131 | * | ||
| 132 | */ | ||
| 133 | Sgl_setzero(result); | ||
| 134 | newbit = 1 << SGL_P; | ||
| 135 | while (newbit && Sgl_isnotzero(src)) { | ||
| 136 | Sgl_addition(result,newbit,sum); | ||
| 137 | if(sum <= Sgl_all(src)) { | ||
| 138 | /* update result */ | ||
| 139 | Sgl_addition(result,(newbit<<1),result); | ||
| 140 | Sgl_subtract(src,sum,src); | ||
| 141 | } | ||
| 142 | Sgl_rightshiftby1(newbit); | ||
| 143 | Sgl_leftshiftby1(src); | ||
| 144 | } | ||
| 145 | /* correct exponent for pre-shift */ | ||
| 146 | if (even_exponent) { | ||
| 147 | Sgl_rightshiftby1(result); | ||
| 148 | } | ||
| 149 | |||
| 150 | /* check for inexact */ | ||
| 151 | if (Sgl_isnotzero(src)) { | ||
| 152 | if (!even_exponent && Sgl_islessthan(result,src)) | ||
| 153 | Sgl_increment(result); | ||
| 154 | guardbit = Sgl_lowmantissa(result); | ||
| 155 | Sgl_rightshiftby1(result); | ||
| 156 | |||
| 157 | /* now round result */ | ||
| 158 | switch (Rounding_mode()) { | ||
| 159 | case ROUNDPLUS: | ||
| 160 | Sgl_increment(result); | ||
| 161 | break; | ||
| 162 | case ROUNDNEAREST: | ||
| 163 | /* stickybit is always true, so guardbit | ||
| 164 | * is enough to determine rounding */ | ||
| 165 | if (guardbit) { | ||
| 166 | Sgl_increment(result); | ||
| 167 | } | ||
| 168 | break; | ||
| 169 | } | ||
| 170 | /* increment result exponent by 1 if mantissa overflowed */ | ||
| 171 | if (Sgl_isone_hiddenoverflow(result)) src_exponent+=2; | ||
| 172 | |||
| 173 | if (Is_inexacttrap_enabled()) { | ||
| 174 | Sgl_set_exponent(result, | ||
| 175 | ((src_exponent-SGL_BIAS)>>1)+SGL_BIAS); | ||
| 176 | *dstptr = result; | ||
| 177 | return(INEXACTEXCEPTION); | ||
| 178 | } | ||
| 179 | else Set_inexactflag(); | ||
| 180 | } | ||
| 181 | else { | ||
| 182 | Sgl_rightshiftby1(result); | ||
| 183 | } | ||
| 184 | Sgl_set_exponent(result,((src_exponent-SGL_BIAS)>>1)+SGL_BIAS); | ||
| 185 | *dstptr = result; | ||
| 186 | return(NOEXCEPTION); | ||
| 187 | } | ||
diff --git a/arch/parisc/math-emu/sfsub.c b/arch/parisc/math-emu/sfsub.c new file mode 100644 index 000000000000..24eef61c8e3b --- /dev/null +++ b/arch/parisc/math-emu/sfsub.c | |||
| @@ -0,0 +1,521 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | /* | ||
| 22 | * BEGIN_DESC | ||
| 23 | * | ||
| 24 | * File: | ||
| 25 | * @(#) pa/spmath/sfsub.c $Revision: 1.1 $ | ||
| 26 | * | ||
| 27 | * Purpose: | ||
| 28 | * Single_subtract: subtract two single precision values. | ||
| 29 | * | ||
| 30 | * External Interfaces: | ||
| 31 | * sgl_fsub(leftptr, rightptr, dstptr, status) | ||
| 32 | * | ||
| 33 | * Internal Interfaces: | ||
| 34 | * | ||
| 35 | * Theory: | ||
| 36 | * <<please update with a overview of the operation of this file>> | ||
| 37 | * | ||
| 38 | * END_DESC | ||
| 39 | */ | ||
| 40 | |||
| 41 | |||
| 42 | #include "float.h" | ||
| 43 | #include "sgl_float.h" | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Single_subtract: subtract two single precision values. | ||
| 47 | */ | ||
| 48 | int | ||
| 49 | sgl_fsub( | ||
| 50 | sgl_floating_point *leftptr, | ||
| 51 | sgl_floating_point *rightptr, | ||
| 52 | sgl_floating_point *dstptr, | ||
| 53 | unsigned int *status) | ||
| 54 | { | ||
| 55 | register unsigned int left, right, result, extent; | ||
| 56 | register unsigned int signless_upper_left, signless_upper_right, save; | ||
| 57 | |||
| 58 | register int result_exponent, right_exponent, diff_exponent; | ||
| 59 | register int sign_save, jumpsize; | ||
| 60 | register boolean inexact = FALSE, underflowtrap; | ||
| 61 | |||
| 62 | /* Create local copies of the numbers */ | ||
| 63 | left = *leftptr; | ||
| 64 | right = *rightptr; | ||
| 65 | |||
| 66 | /* A zero "save" helps discover equal operands (for later), * | ||
| 67 | * and is used in swapping operands (if needed). */ | ||
| 68 | Sgl_xortointp1(left,right,/*to*/save); | ||
| 69 | |||
| 70 | /* | ||
| 71 | * check first operand for NaN's or infinity | ||
| 72 | */ | ||
| 73 | if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT) | ||
| 74 | { | ||
| 75 | if (Sgl_iszero_mantissa(left)) | ||
| 76 | { | ||
| 77 | if (Sgl_isnotnan(right)) | ||
| 78 | { | ||
| 79 | if (Sgl_isinfinity(right) && save==0) | ||
| 80 | { | ||
| 81 | /* | ||
| 82 | * invalid since operands are same signed infinity's | ||
| 83 | */ | ||
| 84 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 85 | Set_invalidflag(); | ||
| 86 | Sgl_makequietnan(result); | ||
| 87 | *dstptr = result; | ||
| 88 | return(NOEXCEPTION); | ||
| 89 | } | ||
| 90 | /* | ||
| 91 | * return infinity | ||
| 92 | */ | ||
| 93 | *dstptr = left; | ||
| 94 | return(NOEXCEPTION); | ||
| 95 | } | ||
| 96 | } | ||
| 97 | else | ||
| 98 | { | ||
| 99 | /* | ||
| 100 | * is NaN; signaling or quiet? | ||
| 101 | */ | ||
| 102 | if (Sgl_isone_signaling(left)) | ||
| 103 | { | ||
| 104 | /* trap if INVALIDTRAP enabled */ | ||
| 105 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 106 | /* make NaN quiet */ | ||
| 107 | Set_invalidflag(); | ||
| 108 | Sgl_set_quiet(left); | ||
| 109 | } | ||
| 110 | /* | ||
| 111 | * is second operand a signaling NaN? | ||
| 112 | */ | ||
| 113 | else if (Sgl_is_signalingnan(right)) | ||
| 114 | { | ||
| 115 | /* trap if INVALIDTRAP enabled */ | ||
| 116 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 117 | /* make NaN quiet */ | ||
| 118 | Set_invalidflag(); | ||
| 119 | Sgl_set_quiet(right); | ||
| 120 | *dstptr = right; | ||
| 121 | return(NOEXCEPTION); | ||
| 122 | } | ||
| 123 | /* | ||
| 124 | * return quiet NaN | ||
| 125 | */ | ||
| 126 | *dstptr = left; | ||
| 127 | return(NOEXCEPTION); | ||
| 128 | } | ||
| 129 | } /* End left NaN or Infinity processing */ | ||
| 130 | /* | ||
| 131 | * check second operand for NaN's or infinity | ||
| 132 | */ | ||
| 133 | if (Sgl_isinfinity_exponent(right)) | ||
| 134 | { | ||
| 135 | if (Sgl_iszero_mantissa(right)) | ||
| 136 | { | ||
| 137 | /* return infinity */ | ||
| 138 | Sgl_invert_sign(right); | ||
| 139 | *dstptr = right; | ||
| 140 | return(NOEXCEPTION); | ||
| 141 | } | ||
| 142 | /* | ||
| 143 | * is NaN; signaling or quiet? | ||
| 144 | */ | ||
| 145 | if (Sgl_isone_signaling(right)) | ||
| 146 | { | ||
| 147 | /* trap if INVALIDTRAP enabled */ | ||
| 148 | if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); | ||
| 149 | /* make NaN quiet */ | ||
| 150 | Set_invalidflag(); | ||
| 151 | Sgl_set_quiet(right); | ||
| 152 | } | ||
| 153 | /* | ||
| 154 | * return quiet NaN | ||
| 155 | */ | ||
| 156 | *dstptr = right; | ||
| 157 | return(NOEXCEPTION); | ||
| 158 | } /* End right NaN or Infinity processing */ | ||
| 159 | |||
| 160 | /* Invariant: Must be dealing with finite numbers */ | ||
| 161 | |||
| 162 | /* Compare operands by removing the sign */ | ||
| 163 | Sgl_copytoint_exponentmantissa(left,signless_upper_left); | ||
| 164 | Sgl_copytoint_exponentmantissa(right,signless_upper_right); | ||
| 165 | |||
| 166 | /* sign difference selects sub or add operation. */ | ||
| 167 | if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right)) | ||
| 168 | { | ||
| 169 | /* Set the left operand to the larger one by XOR swap * | ||
| 170 | * First finish the first word using "save" */ | ||
| 171 | Sgl_xorfromintp1(save,right,/*to*/right); | ||
| 172 | Sgl_xorfromintp1(save,left,/*to*/left); | ||
| 173 | result_exponent = Sgl_exponent(left); | ||
| 174 | Sgl_invert_sign(left); | ||
| 175 | } | ||
| 176 | /* Invariant: left is not smaller than right. */ | ||
| 177 | |||
| 178 | if((right_exponent = Sgl_exponent(right)) == 0) | ||
| 179 | { | ||
| 180 | /* Denormalized operands. First look for zeroes */ | ||
| 181 | if(Sgl_iszero_mantissa(right)) | ||
| 182 | { | ||
| 183 | /* right is zero */ | ||
| 184 | if(Sgl_iszero_exponentmantissa(left)) | ||
| 185 | { | ||
| 186 | /* Both operands are zeros */ | ||
| 187 | Sgl_invert_sign(right); | ||
| 188 | if(Is_rounding_mode(ROUNDMINUS)) | ||
| 189 | { | ||
| 190 | Sgl_or_signs(left,/*with*/right); | ||
| 191 | } | ||
| 192 | else | ||
| 193 | { | ||
| 194 | Sgl_and_signs(left,/*with*/right); | ||
| 195 | } | ||
| 196 | } | ||
| 197 | else | ||
| 198 | { | ||
| 199 | /* Left is not a zero and must be the result. Trapped | ||
| 200 | * underflows are signaled if left is denormalized. Result | ||
| 201 | * is always exact. */ | ||
| 202 | if( (result_exponent == 0) && Is_underflowtrap_enabled() ) | ||
| 203 | { | ||
| 204 | /* need to normalize results mantissa */ | ||
| 205 | sign_save = Sgl_signextendedsign(left); | ||
| 206 | Sgl_leftshiftby1(left); | ||
| 207 | Sgl_normalize(left,result_exponent); | ||
| 208 | Sgl_set_sign(left,/*using*/sign_save); | ||
| 209 | Sgl_setwrapped_exponent(left,result_exponent,unfl); | ||
| 210 | *dstptr = left; | ||
| 211 | /* inexact = FALSE */ | ||
| 212 | return(UNDERFLOWEXCEPTION); | ||
| 213 | } | ||
| 214 | } | ||
| 215 | *dstptr = left; | ||
| 216 | return(NOEXCEPTION); | ||
| 217 | } | ||
| 218 | |||
| 219 | /* Neither are zeroes */ | ||
| 220 | Sgl_clear_sign(right); /* Exponent is already cleared */ | ||
| 221 | if(result_exponent == 0 ) | ||
| 222 | { | ||
| 223 | /* Both operands are denormalized. The result must be exact | ||
| 224 | * and is simply calculated. A sum could become normalized and a | ||
| 225 | * difference could cancel to a true zero. */ | ||
| 226 | if( (/*signed*/int) save >= 0 ) | ||
| 227 | { | ||
| 228 | Sgl_subtract(left,/*minus*/right,/*into*/result); | ||
| 229 | if(Sgl_iszero_mantissa(result)) | ||
| 230 | { | ||
| 231 | if(Is_rounding_mode(ROUNDMINUS)) | ||
| 232 | { | ||
| 233 | Sgl_setone_sign(result); | ||
| 234 | } | ||
| 235 | else | ||
| 236 | { | ||
| 237 | Sgl_setzero_sign(result); | ||
| 238 | } | ||
| 239 | *dstptr = result; | ||
| 240 | return(NOEXCEPTION); | ||
| 241 | } | ||
| 242 | } | ||
| 243 | else | ||
| 244 | { | ||
| 245 | Sgl_addition(left,right,/*into*/result); | ||
| 246 | if(Sgl_isone_hidden(result)) | ||
| 247 | { | ||
| 248 | *dstptr = result; | ||
| 249 | return(NOEXCEPTION); | ||
| 250 | } | ||
| 251 | } | ||
| 252 | if(Is_underflowtrap_enabled()) | ||
| 253 | { | ||
| 254 | /* need to normalize result */ | ||
| 255 | sign_save = Sgl_signextendedsign(result); | ||
| 256 | Sgl_leftshiftby1(result); | ||
| 257 | Sgl_normalize(result,result_exponent); | ||
| 258 | Sgl_set_sign(result,/*using*/sign_save); | ||
| 259 | Sgl_setwrapped_exponent(result,result_exponent,unfl); | ||
| 260 | *dstptr = result; | ||
| 261 | /* inexact = FALSE */ | ||
| 262 | return(UNDERFLOWEXCEPTION); | ||
| 263 | } | ||
| 264 | *dstptr = result; | ||
| 265 | return(NOEXCEPTION); | ||
| 266 | } | ||
| 267 | right_exponent = 1; /* Set exponent to reflect different bias | ||
| 268 | * with denomalized numbers. */ | ||
| 269 | } | ||
| 270 | else | ||
| 271 | { | ||
| 272 | Sgl_clear_signexponent_set_hidden(right); | ||
| 273 | } | ||
| 274 | Sgl_clear_exponent_set_hidden(left); | ||
| 275 | diff_exponent = result_exponent - right_exponent; | ||
| 276 | |||
| 277 | /* | ||
| 278 | * Special case alignment of operands that would force alignment | ||
| 279 | * beyond the extent of the extension. A further optimization | ||
| 280 | * could special case this but only reduces the path length for this | ||
| 281 | * infrequent case. | ||
| 282 | */ | ||
| 283 | if(diff_exponent > SGL_THRESHOLD) | ||
| 284 | { | ||
| 285 | diff_exponent = SGL_THRESHOLD; | ||
| 286 | } | ||
| 287 | |||
| 288 | /* Align right operand by shifting to right */ | ||
| 289 | Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent, | ||
| 290 | /*and lower to*/extent); | ||
| 291 | |||
| 292 | /* Treat sum and difference of the operands separately. */ | ||
| 293 | if( (/*signed*/int) save >= 0 ) | ||
| 294 | { | ||
| 295 | /* | ||
| 296 | * Difference of the two operands. Their can be no overflow. A | ||
| 297 | * borrow can occur out of the hidden bit and force a post | ||
| 298 | * normalization phase. | ||
| 299 | */ | ||
| 300 | Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result); | ||
| 301 | if(Sgl_iszero_hidden(result)) | ||
| 302 | { | ||
| 303 | /* Handle normalization */ | ||
| 304 | /* A straight foward algorithm would now shift the result | ||
| 305 | * and extension left until the hidden bit becomes one. Not | ||
| 306 | * all of the extension bits need participate in the shift. | ||
| 307 | * Only the two most significant bits (round and guard) are | ||
| 308 | * needed. If only a single shift is needed then the guard | ||
| 309 | * bit becomes a significant low order bit and the extension | ||
| 310 | * must participate in the rounding. If more than a single | ||
| 311 | * shift is needed, then all bits to the right of the guard | ||
| 312 | * bit are zeros, and the guard bit may or may not be zero. */ | ||
| 313 | sign_save = Sgl_signextendedsign(result); | ||
| 314 | Sgl_leftshiftby1_withextent(result,extent,result); | ||
| 315 | |||
| 316 | /* Need to check for a zero result. The sign and exponent | ||
| 317 | * fields have already been zeroed. The more efficient test | ||
| 318 | * of the full object can be used. | ||
| 319 | */ | ||
| 320 | if(Sgl_iszero(result)) | ||
| 321 | /* Must have been "x-x" or "x+(-x)". */ | ||
| 322 | { | ||
| 323 | if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result); | ||
| 324 | *dstptr = result; | ||
| 325 | return(NOEXCEPTION); | ||
| 326 | } | ||
| 327 | result_exponent--; | ||
| 328 | /* Look to see if normalization is finished. */ | ||
| 329 | if(Sgl_isone_hidden(result)) | ||
| 330 | { | ||
| 331 | if(result_exponent==0) | ||
| 332 | { | ||
| 333 | /* Denormalized, exponent should be zero. Left operand * | ||
| 334 | * was normalized, so extent (guard, round) was zero */ | ||
| 335 | goto underflow; | ||
| 336 | } | ||
| 337 | else | ||
| 338 | { | ||
| 339 | /* No further normalization is needed. */ | ||
| 340 | Sgl_set_sign(result,/*using*/sign_save); | ||
| 341 | Ext_leftshiftby1(extent); | ||
| 342 | goto round; | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | /* Check for denormalized, exponent should be zero. Left * | ||
| 347 | * operand was normalized, so extent (guard, round) was zero */ | ||
| 348 | if(!(underflowtrap = Is_underflowtrap_enabled()) && | ||
| 349 | result_exponent==0) goto underflow; | ||
| 350 | |||
| 351 | /* Shift extension to complete one bit of normalization and | ||
| 352 | * update exponent. */ | ||
| 353 | Ext_leftshiftby1(extent); | ||
| 354 | |||
| 355 | /* Discover first one bit to determine shift amount. Use a | ||
| 356 | * modified binary search. We have already shifted the result | ||
| 357 | * one position right and still not found a one so the remainder | ||
| 358 | * of the extension must be zero and simplifies rounding. */ | ||
| 359 | /* Scan bytes */ | ||
| 360 | while(Sgl_iszero_hiddenhigh7mantissa(result)) | ||
| 361 | { | ||
| 362 | Sgl_leftshiftby8(result); | ||
| 363 | if((result_exponent -= 8) <= 0 && !underflowtrap) | ||
| 364 | goto underflow; | ||
| 365 | } | ||
| 366 | /* Now narrow it down to the nibble */ | ||
| 367 | if(Sgl_iszero_hiddenhigh3mantissa(result)) | ||
| 368 | { | ||
| 369 | /* The lower nibble contains the normalizing one */ | ||
| 370 | Sgl_leftshiftby4(result); | ||
| 371 | if((result_exponent -= 4) <= 0 && !underflowtrap) | ||
| 372 | goto underflow; | ||
| 373 | } | ||
| 374 | /* Select case were first bit is set (already normalized) | ||
| 375 | * otherwise select the proper shift. */ | ||
| 376 | if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7) | ||
| 377 | { | ||
| 378 | /* Already normalized */ | ||
| 379 | if(result_exponent <= 0) goto underflow; | ||
| 380 | Sgl_set_sign(result,/*using*/sign_save); | ||
| 381 | Sgl_set_exponent(result,/*using*/result_exponent); | ||
| 382 | *dstptr = result; | ||
| 383 | return(NOEXCEPTION); | ||
| 384 | } | ||
| 385 | Sgl_sethigh4bits(result,/*using*/sign_save); | ||
| 386 | switch(jumpsize) | ||
| 387 | { | ||
| 388 | case 1: | ||
| 389 | { | ||
| 390 | Sgl_leftshiftby3(result); | ||
| 391 | result_exponent -= 3; | ||
| 392 | break; | ||
| 393 | } | ||
| 394 | case 2: | ||
| 395 | case 3: | ||
| 396 | { | ||
| 397 | Sgl_leftshiftby2(result); | ||
| 398 | result_exponent -= 2; | ||
| 399 | break; | ||
| 400 | } | ||
| 401 | case 4: | ||
| 402 | case 5: | ||
| 403 | case 6: | ||
| 404 | case 7: | ||
| 405 | { | ||
| 406 | Sgl_leftshiftby1(result); | ||
| 407 | result_exponent -= 1; | ||
| 408 | break; | ||
| 409 | } | ||
| 410 | } | ||
| 411 | if(result_exponent > 0) | ||
| 412 | { | ||
| 413 | Sgl_set_exponent(result,/*using*/result_exponent); | ||
| 414 | *dstptr = result; /* Sign bit is already set */ | ||
| 415 | return(NOEXCEPTION); | ||
| 416 | } | ||
| 417 | /* Fixup potential underflows */ | ||
| 418 | underflow: | ||
| 419 | if(Is_underflowtrap_enabled()) | ||
| 420 | { | ||
| 421 | Sgl_set_sign(result,sign_save); | ||
| 422 | Sgl_setwrapped_exponent(result,result_exponent,unfl); | ||
| 423 | *dstptr = result; | ||
| 424 | /* inexact = FALSE */ | ||
| 425 | return(UNDERFLOWEXCEPTION); | ||
| 426 | } | ||
| 427 | /* | ||
| 428 | * Since we cannot get an inexact denormalized result, | ||
| 429 | * we can now return. | ||
| 430 | */ | ||
| 431 | Sgl_right_align(result,/*by*/(1-result_exponent),extent); | ||
| 432 | Sgl_clear_signexponent(result); | ||
| 433 | Sgl_set_sign(result,sign_save); | ||
| 434 | *dstptr = result; | ||
| 435 | return(NOEXCEPTION); | ||
| 436 | } /* end if(hidden...)... */ | ||
| 437 | /* Fall through and round */ | ||
| 438 | } /* end if(save >= 0)... */ | ||
| 439 | else | ||
| 440 | { | ||
| 441 | /* Add magnitudes */ | ||
| 442 | Sgl_addition(left,right,/*to*/result); | ||
| 443 | if(Sgl_isone_hiddenoverflow(result)) | ||
| 444 | { | ||
| 445 | /* Prenormalization required. */ | ||
| 446 | Sgl_rightshiftby1_withextent(result,extent,extent); | ||
| 447 | Sgl_arithrightshiftby1(result); | ||
| 448 | result_exponent++; | ||
| 449 | } /* end if hiddenoverflow... */ | ||
| 450 | } /* end else ...sub magnitudes... */ | ||
| 451 | |||
| 452 | /* Round the result. If the extension is all zeros,then the result is | ||
| 453 | * exact. Otherwise round in the correct direction. No underflow is | ||
| 454 | * possible. If a postnormalization is necessary, then the mantissa is | ||
| 455 | * all zeros so no shift is needed. */ | ||
| 456 | round: | ||
| 457 | if(Ext_isnotzero(extent)) | ||
| 458 | { | ||
| 459 | inexact = TRUE; | ||
| 460 | switch(Rounding_mode()) | ||
| 461 | { | ||
| 462 | case ROUNDNEAREST: /* The default. */ | ||
| 463 | if(Ext_isone_sign(extent)) | ||
| 464 | { | ||
| 465 | /* at least 1/2 ulp */ | ||
| 466 | if(Ext_isnotzero_lower(extent) || | ||
| 467 | Sgl_isone_lowmantissa(result)) | ||
| 468 | { | ||
| 469 | /* either exactly half way and odd or more than 1/2ulp */ | ||
| 470 | Sgl_increment(result); | ||
| 471 | } | ||
| 472 | } | ||
| 473 | break; | ||
| 474 | |||
| 475 | case ROUNDPLUS: | ||
| 476 | if(Sgl_iszero_sign(result)) | ||
| 477 | { | ||
| 478 | /* Round up positive results */ | ||
| 479 | Sgl_increment(result); | ||
| 480 | } | ||
| 481 | break; | ||
| 482 | |||
| 483 | case ROUNDMINUS: | ||
| 484 | if(Sgl_isone_sign(result)) | ||
| 485 | { | ||
| 486 | /* Round down negative results */ | ||
| 487 | Sgl_increment(result); | ||
| 488 | } | ||
| 489 | |||
| 490 | case ROUNDZERO:; | ||
| 491 | /* truncate is simple */ | ||
| 492 | } /* end switch... */ | ||
| 493 | if(Sgl_isone_hiddenoverflow(result)) result_exponent++; | ||
| 494 | } | ||
| 495 | if(result_exponent == SGL_INFINITY_EXPONENT) | ||
| 496 | { | ||
| 497 | /* Overflow */ | ||
| 498 | if(Is_overflowtrap_enabled()) | ||
| 499 | { | ||
| 500 | Sgl_setwrapped_exponent(result,result_exponent,ovfl); | ||
| 501 | *dstptr = result; | ||
| 502 | if (inexact) | ||
| 503 | if (Is_inexacttrap_enabled()) | ||
| 504 | return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); | ||
| 505 | else Set_inexactflag(); | ||
| 506 | return(OVERFLOWEXCEPTION); | ||
| 507 | } | ||
| 508 | else | ||
| 509 | { | ||
| 510 | Set_overflowflag(); | ||
| 511 | inexact = TRUE; | ||
| 512 | Sgl_setoverflow(result); | ||
| 513 | } | ||
| 514 | } | ||
| 515 | else Sgl_set_exponent(result,result_exponent); | ||
| 516 | *dstptr = result; | ||
| 517 | if(inexact) | ||
| 518 | if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); | ||
| 519 | else Set_inexactflag(); | ||
| 520 | return(NOEXCEPTION); | ||
| 521 | } | ||
diff --git a/arch/parisc/math-emu/sgl_float.h b/arch/parisc/math-emu/sgl_float.h new file mode 100644 index 000000000000..82519a5c2ba5 --- /dev/null +++ b/arch/parisc/math-emu/sgl_float.h | |||
| @@ -0,0 +1,486 @@ | |||
| 1 | /* | ||
| 2 | * Linux/PA-RISC Project (http://www.parisc-linux.org/) | ||
| 3 | * | ||
| 4 | * Floating-point emulation code | ||
| 5 | * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 10 | * any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifdef __NO_PA_HDRS | ||
| 23 | PA header file -- do not include this header file for non-PA builds. | ||
| 24 | #endif | ||
| 25 | |||
| 26 | /* 32-bit word grabing functions */ | ||
| 27 | #define Sgl_firstword(value) Sall(value) | ||
| 28 | #define Sgl_secondword(value) dummy_location | ||
| 29 | #define Sgl_thirdword(value) dummy_location | ||
| 30 | #define Sgl_fourthword(value) dummy_location | ||
| 31 | |||
| 32 | #define Sgl_sign(object) Ssign(object) | ||
| 33 | #define Sgl_exponent(object) Sexponent(object) | ||
| 34 | #define Sgl_signexponent(object) Ssignexponent(object) | ||
| 35 | #define Sgl_mantissa(object) Smantissa(object) | ||
| 36 | #define Sgl_exponentmantissa(object) Sexponentmantissa(object) | ||
| 37 | #define Sgl_all(object) Sall(object) | ||
| 38 | |||
| 39 | /* sgl_and_signs ands the sign bits of each argument and puts the result | ||
| 40 | * into the first argument. sgl_or_signs ors those same sign bits */ | ||
| 41 | #define Sgl_and_signs( src1dst, src2) \ | ||
| 42 | Sall(src1dst) = (Sall(src2)|~((unsigned int)1<<31)) & Sall(src1dst) | ||
| 43 | #define Sgl_or_signs( src1dst, src2) \ | ||
| 44 | Sall(src1dst) = (Sall(src2)&((unsigned int)1<<31)) | Sall(src1dst) | ||
| 45 | |||
| 46 | /* The hidden bit is always the low bit of the exponent */ | ||
| 47 | #define Sgl_clear_exponent_set_hidden(srcdst) Deposit_sexponent(srcdst,1) | ||
| 48 | #define Sgl_clear_signexponent_set_hidden(srcdst) \ | ||
| 49 | Deposit_ssignexponent(srcdst,1) | ||
| 50 | #define Sgl_clear_sign(srcdst) Sall(srcdst) &= ~((unsigned int)1<<31) | ||
| 51 | #define Sgl_clear_signexponent(srcdst) Sall(srcdst) &= 0x007fffff | ||
| 52 | |||
| 53 | /* varamount must be less than 32 for the next three functions */ | ||
| 54 | #define Sgl_rightshift(srcdst, varamount) \ | ||
| 55 | Sall(srcdst) >>= varamount | ||
| 56 | #define Sgl_leftshift(srcdst, varamount) \ | ||
| 57 | Sall(srcdst) <<= varamount | ||
| 58 | #define Sgl_rightshift_exponentmantissa(srcdst, varamount) \ | ||
| 59 | Sall(srcdst) = \ | ||
| 60 | (Sexponentmantissa(srcdst) >> varamount) | \ | ||
| 61 | (Sall(srcdst) & ((unsigned int)1<<31)) | ||
| 62 | |||
| 63 | #define Sgl_leftshiftby1_withextent(left,right,result) \ | ||
| 64 | Shiftdouble(Sall(left),Extall(right),31,Sall(result)) | ||
| 65 | |||
| 66 | #define Sgl_rightshiftby1_withextent(left,right,dst) \ | ||
| 67 | Shiftdouble(Sall(left),Extall(right),1,Extall(right)) | ||
| 68 | #define Sgl_arithrightshiftby1(srcdst) \ | ||
| 69 | Sall(srcdst) = (int)Sall(srcdst) >> 1 | ||
| 70 | |||
| 71 | /* Sign extend the sign bit with an integer destination */ | ||
| 72 | #define Sgl_signextendedsign(value) Ssignedsign(value) | ||
| 73 | |||
| 74 | #define Sgl_isone_hidden(sgl_value) (Shidden(sgl_value)) | ||
| 75 | #define Sgl_increment(sgl_value) Sall(sgl_value) += 1 | ||
| 76 | #define Sgl_increment_mantissa(sgl_value) \ | ||
| 77 | Deposit_smantissa(sgl_value,sgl_value+1) | ||
| 78 | #define Sgl_decrement(sgl_value) Sall(sgl_value) -= 1 | ||
| 79 | |||
| 80 | #define Sgl_isone_sign(sgl_value) (Is_ssign(sgl_value)!=0) | ||
| 81 | #define Sgl_isone_hiddenoverflow(sgl_value) \ | ||
| 82 | (Is_shiddenoverflow(sgl_value)!=0) | ||
| 83 | #define Sgl_isone_lowmantissa(sgl_value) (Is_slow(sgl_value)!=0) | ||
| 84 | #define Sgl_isone_signaling(sgl_value) (Is_ssignaling(sgl_value)!=0) | ||
| 85 | #define Sgl_is_signalingnan(sgl_value) (Ssignalingnan(sgl_value)==0x1ff) | ||
| 86 | #define Sgl_isnotzero(sgl_value) (Sall(sgl_value)!=0) | ||
| 87 | #define Sgl_isnotzero_hiddenhigh7mantissa(sgl_value) \ | ||
| 88 | (Shiddenhigh7mantissa(sgl_value)!=0) | ||
| 89 | #define Sgl_isnotzero_low4(sgl_value) (Slow4(sgl_value)!=0) | ||
| 90 | #define Sgl_isnotzero_exponent(sgl_value) (Sexponent(sgl_value)!=0) | ||
| 91 | #define Sgl_isnotzero_mantissa(sgl_value) (Smantissa(sgl_value)!=0) | ||
| 92 | #define Sgl_isnotzero_exponentmantissa(sgl_value) \ | ||
| 93 | (Sexponentmantissa(sgl_value)!=0) | ||
| 94 | #define Sgl_iszero(sgl_value) (Sall(sgl_value)==0) | ||
| 95 | #define Sgl_iszero_signaling(sgl_value) (Is_ssignaling(sgl_value)==0) | ||
| 96 | #define Sgl_iszero_hidden(sgl_value) (Is_shidden(sgl_value)==0) | ||
| 97 | #define Sgl_iszero_hiddenoverflow(sgl_value) \ | ||
| 98 | (Is_shiddenoverflow(sgl_value)==0) | ||
| 99 | #define Sgl_iszero_hiddenhigh3mantissa(sgl_value) \ | ||
| 100 | (Shiddenhigh3mantissa(sgl_value)==0) | ||
| 101 | #define Sgl_iszero_hiddenhigh7mantissa(sgl_value) \ | ||
| 102 | (Shiddenhigh7mantissa(sgl_value)==0) | ||
| 103 | #define Sgl_iszero_sign(sgl_value) (Is_ssign(sgl_value)==0) | ||
| 104 | #define Sgl_iszero_exponent(sgl_value) (Sexponent(sgl_value)==0) | ||
| 105 | #define Sgl_iszero_mantissa(sgl_value) (Smantissa(sgl_value)==0) | ||
| 106 | #define Sgl_iszero_exponentmantissa(sgl_value) \ | ||
| 107 | (Sexponentmantissa(sgl_value)==0) | ||
| 108 | #define Sgl_isinfinity_exponent(sgl_value) \ | ||
| 109 | (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT) | ||
| 110 | #define Sgl_isnotinfinity_exponent(sgl_value) \ | ||
| 111 | (Sgl_exponent(sgl_value)!=SGL_INFINITY_EXPONENT) | ||
| 112 | #define Sgl_isinfinity(sgl_value) \ | ||
| 113 | (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT && \ | ||
| 114 | Sgl_mantissa(sgl_value)==0) | ||
| 115 | #define Sgl_isnan(sgl_value) \ | ||
| 116 | (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT && \ | ||
| 117 | Sgl_mantissa(sgl_value)!=0) | ||
| 118 | #define Sgl_isnotnan(sgl_value) \ | ||
| 119 | (Sgl_exponent(sgl_value)!=SGL_INFINITY_EXPONENT || \ | ||
| 120 | Sgl_mantissa(sgl_value)==0) | ||
| 121 | #define Sgl_islessthan(sgl_op1,sgl_op2) \ | ||
| 122 | (Sall(sgl_op1) < Sall(sgl_op2)) | ||
| 123 | #define Sgl_isgreaterthan(sgl_op1,sgl_op2) \ | ||
| 124 | (Sall(sgl_op1) > Sall(sgl_op2)) | ||
| 125 | #define Sgl_isnotlessthan(sgl_op1,sgl_op2) \ | ||
| 126 | (Sall(sgl_op1) >= Sall(sgl_op2)) | ||
| 127 | #define Sgl_isequal(sgl_op1,sgl_op2) \ | ||
| 128 | (Sall(sgl_op1) == Sall(sgl_op2)) | ||
| 129 | |||
| 130 | #define Sgl_leftshiftby8(sgl_value) \ | ||
| 131 | Sall(sgl_value) <<= 8 | ||
| 132 | #define Sgl_leftshiftby4(sgl_value) \ | ||
| 133 | Sall(sgl_value) <<= 4 | ||
| 134 | #define Sgl_leftshiftby3(sgl_value) \ | ||
| 135 | Sall(sgl_value) <<= 3 | ||
| 136 | #define Sgl_leftshiftby2(sgl_value) \ | ||
| 137 | Sall(sgl_value) <<= 2 | ||
| 138 | #define Sgl_leftshiftby1(sgl_value) \ | ||
| 139 | Sall(sgl_value) <<= 1 | ||
| 140 | #define Sgl_rightshiftby1(sgl_value) \ | ||
| 141 | Sall(sgl_value) >>= 1 | ||
| 142 | #define Sgl_rightshiftby4(sgl_value) \ | ||
| 143 | Sall(sgl_value) >>= 4 | ||
| 144 | #define Sgl_rightshiftby8(sgl_value) \ | ||
| 145 | Sall(sgl_value) >>= 8 | ||
| 146 | |||
| 147 | #define Sgl_ismagnitudeless(signlessleft,signlessright) \ | ||
| 148 | /* unsigned int signlessleft, signlessright; */ \ | ||
| 149 | (signlessleft < signlessright) | ||
| 150 | |||
| 151 | |||
| 152 | #define Sgl_copytoint_exponentmantissa(source,dest) \ | ||
| 153 | dest = Sexponentmantissa(source) | ||
| 154 | |||
| 155 | /* A quiet NaN has the high mantissa bit clear and at least on other (in this | ||
| 156 | * case the adjacent bit) bit set. */ | ||
| 157 | #define Sgl_set_quiet(sgl_value) Deposit_shigh2mantissa(sgl_value,1) | ||
| 158 | #define Sgl_set_exponent(sgl_value,exp) Deposit_sexponent(sgl_value,exp) | ||
| 159 | |||
| 160 | #define Sgl_set_mantissa(dest,value) Deposit_smantissa(dest,value) | ||
| 161 | #define Sgl_set_exponentmantissa(dest,value) \ | ||
| 162 | Deposit_sexponentmantissa(dest,value) | ||
| 163 | |||
| 164 | /* An infinity is represented with the max exponent and a zero mantissa */ | ||
| 165 | #define Sgl_setinfinity_exponent(sgl_value) \ | ||
| 166 | Deposit_sexponent(sgl_value,SGL_INFINITY_EXPONENT) | ||
| 167 | #define Sgl_setinfinity_exponentmantissa(sgl_value) \ | ||
| 168 | Deposit_sexponentmantissa(sgl_value, \ | ||
| 169 | (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH)))) | ||
| 170 | #define Sgl_setinfinitypositive(sgl_value) \ | ||
| 171 | Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) | ||
| 172 | #define Sgl_setinfinitynegative(sgl_value) \ | ||
| 173 | Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) \ | ||
| 174 | | ((unsigned int)1<<31) | ||
| 175 | #define Sgl_setinfinity(sgl_value,sign) \ | ||
| 176 | Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) | \ | ||
| 177 | ((unsigned int)sign << 31) | ||
| 178 | #define Sgl_sethigh4bits(sgl_value, extsign) \ | ||
| 179 | Deposit_shigh4(sgl_value,extsign) | ||
| 180 | #define Sgl_set_sign(sgl_value,sign) Deposit_ssign(sgl_value,sign) | ||
| 181 | #define Sgl_invert_sign(sgl_value) \ | ||
| 182 | Deposit_ssign(sgl_value,~Ssign(sgl_value)) | ||
| 183 | #define Sgl_setone_sign(sgl_value) Deposit_ssign(sgl_value,1) | ||
| 184 | #define Sgl_setone_lowmantissa(sgl_value) Deposit_slow(sgl_value,1) | ||
| 185 | #define Sgl_setzero_sign(sgl_value) Sall(sgl_value) &= 0x7fffffff | ||
| 186 | #define Sgl_setzero_exponent(sgl_value) Sall(sgl_value) &= 0x807fffff | ||
| 187 | #define Sgl_setzero_mantissa(sgl_value) Sall(sgl_value) &= 0xff800000 | ||
| 188 | #define Sgl_setzero_exponentmantissa(sgl_value) Sall(sgl_value) &= 0x80000000 | ||
| 189 | #define Sgl_setzero(sgl_value) Sall(sgl_value) = 0 | ||
| 190 | #define Sgl_setnegativezero(sgl_value) Sall(sgl_value) = (unsigned int)1 << 31 | ||
| 191 | |||
| 192 | /* Use following macro for both overflow & underflow conditions */ | ||
| 193 | #define ovfl - | ||
| 194 | #define unfl + | ||
| 195 | #define Sgl_setwrapped_exponent(sgl_value,exponent,op) \ | ||
| 196 | Deposit_sexponent(sgl_value,(exponent op SGL_WRAP)) | ||
| 197 | |||
| 198 | #define Sgl_setlargestpositive(sgl_value) \ | ||
| 199 | Sall(sgl_value) = ((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \ | ||
| 200 | | ((1<<(32-(1+SGL_EXP_LENGTH))) - 1 ) | ||
| 201 | #define Sgl_setlargestnegative(sgl_value) \ | ||
| 202 | Sall(sgl_value) = ((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \ | ||
| 203 | | ((1<<(32-(1+SGL_EXP_LENGTH))) - 1 ) \ | ||
| 204 | | ((unsigned int)1<<31) | ||
| 205 | |||
| 206 | #define Sgl_setnegativeinfinity(sgl_value) \ | ||
| 207 | Sall(sgl_value) = \ | ||
| 208 | ((1<<SGL_EXP_LENGTH) | SGL_INFINITY_EXPONENT) << (32-(1+SGL_EXP_LENGTH)) | ||
| 209 | #define Sgl_setlargest(sgl_value,sign) \ | ||
| 210 | Sall(sgl_value) = (unsigned int)sign << 31 | \ | ||
| 211 | (((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \ | ||
| 212 | | ((1 << (32-(1+SGL_EXP_LENGTH))) - 1 )) | ||
| 213 | #define Sgl_setlargest_exponentmantissa(sgl_value) \ | ||
| 214 | Sall(sgl_value) = Sall(sgl_value) & ((unsigned int)1<<31) | \ | ||
| 215 | (((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH))) \ | ||
| 216 | | ((1 << (32-(1+SGL_EXP_LENGTH))) - 1 )) | ||
| 217 | |||
| 218 | /* The high bit is always zero so arithmetic or logical shifts will work. */ | ||
| 219 | #define Sgl_right_align(srcdst,shift,extent) \ | ||
| 220 | /* sgl_floating_point srcdst; int shift; extension extent */ \ | ||
| 221 | if (shift < 32) { \ | ||
| 222 | Extall(extent) = Sall(srcdst) << (32-(shift)); \ | ||
| 223 | Sall(srcdst) >>= shift; \ | ||
| 224 | } \ | ||
| 225 | else { \ | ||
| 226 | Extall(extent) = Sall(srcdst); \ | ||
| 227 | Sall(srcdst) = 0; \ | ||
| 228 | } | ||
| 229 | #define Sgl_hiddenhigh3mantissa(sgl_value) Shiddenhigh3mantissa(sgl_value) | ||
| 230 | #define Sgl_hidden(sgl_value) Shidden(sgl_value) | ||
| 231 | #define Sgl_lowmantissa(sgl_value) Slow(sgl_value) | ||
| 232 | |||
| 233 | /* The left argument is never smaller than the right argument */ | ||
| 234 | #define Sgl_subtract(sgl_left,sgl_right,sgl_result) \ | ||
| 235 | Sall(sgl_result) = Sall(sgl_left) - Sall(sgl_right) | ||
| 236 | |||
| 237 | /* Subtract right augmented with extension from left augmented with zeros and | ||
| 238 | * store into result and extension. */ | ||
| 239 | #define Sgl_subtract_withextension(left,right,extent,result) \ | ||
| 240 | /* sgl_floating_point left,right,result; extension extent */ \ | ||
| 241 | Sgl_subtract(left,right,result); \ | ||
| 242 | if((Extall(extent) = 0-Extall(extent))) \ | ||
| 243 | Sall(result) = Sall(result)-1 | ||
| 244 | |||
| 245 | #define Sgl_addition(sgl_left,sgl_right,sgl_result) \ | ||
| 246 | Sall(sgl_result) = Sall(sgl_left) + Sall(sgl_right) | ||
| 247 | |||
| 248 | #define Sgl_xortointp1(left,right,result) \ | ||
| 249 | result = Sall(left) XOR Sall(right); | ||
| 250 | |||
| 251 | #define Sgl_xorfromintp1(left,right,result) \ | ||
| 252 | Sall(result) = left XOR Sall(right) | ||
| 253 | |||
| 254 | /* Need to Initialize */ | ||
| 255 | #define Sgl_makequietnan(dest) \ | ||
| 256 | Sall(dest) = ((SGL_EMAX+SGL_BIAS)+1)<< (32-(1+SGL_EXP_LENGTH)) \ | ||
| 257 | | (1<<(32-(1+SGL_EXP_LENGTH+2))) | ||
| 258 | #define Sgl_makesignalingnan(dest) \ | ||
| 259 | Sall(dest) = ((SGL_EMAX+SGL_BIAS)+1)<< (32-(1+SGL_EXP_LENGTH)) \ | ||
| 260 | | (1<<(32-(1+SGL_EXP_LENGTH+1))) | ||
| 261 | |||
| 262 | #define Sgl_normalize(sgl_opnd,exponent) \ | ||
| 263 | while(Sgl_iszero_hiddenhigh7mantissa(sgl_opnd)) { \ | ||
| 264 | Sgl_leftshiftby8(sgl_opnd); \ | ||
| 265 | exponent -= 8; \ | ||
| 266 | } \ | ||
| 267 | if(Sgl_iszero_hiddenhigh3mantissa(sgl_opnd)) { \ | ||
| 268 | Sgl_leftshiftby4(sgl_opnd); \ | ||
| 269 | exponent -= 4; \ | ||
| 270 | } \ | ||
| 271 | while(Sgl_iszero_hidden(sgl_opnd)) { \ | ||
| 272 | Sgl_leftshiftby1(sgl_opnd); \ | ||
| 273 | exponent -= 1; \ | ||
| 274 | } | ||
| 275 | |||
| 276 | #define Sgl_setoverflow(sgl_opnd) \ | ||
| 277 | /* set result to infinity or largest number */ \ | ||
| 278 | switch (Rounding_mode()) { \ | ||
| 279 | case ROUNDPLUS: \ | ||
| 280 | if (Sgl_isone_sign(sgl_opnd)) { \ | ||
| 281 | Sgl_setlargestnegative(sgl_opnd); \ | ||
| 282 | } \ | ||
| 283 | else { \ | ||
| 284 | Sgl_setinfinitypositive(sgl_opnd); \ | ||
| 285 | } \ | ||
| 286 | break; \ | ||
| 287 | case ROUNDMINUS: \ | ||
| 288 | if (Sgl_iszero_sign(sgl_opnd)) { \ | ||
| 289 | Sgl_setlargestpositive(sgl_opnd); \ | ||
| 290 | } \ | ||
| 291 | else { \ | ||
| 292 | Sgl_setinfinitynegative(sgl_opnd); \ | ||
| 293 | } \ | ||
| 294 | break; \ | ||
| 295 | case ROUNDNEAREST: \ | ||
| 296 | Sgl_setinfinity_exponentmantissa(sgl_opnd); \ | ||
| 297 | break; \ | ||
| 298 | case ROUNDZERO: \ | ||
| 299 | Sgl_setlargest_exponentmantissa(sgl_opnd); \ | ||
| 300 | } | ||
| 301 | |||
| 302 | #define Sgl_denormalize(opnd,exponent,guard,sticky,inexact) \ | ||
| 303 | Sgl_clear_signexponent_set_hidden(opnd); \ | ||
| 304 | if (exponent >= (1 - SGL_P)) { \ | ||
| 305 | guard = (Sall(opnd) >> -exponent) & 1; \ | ||
| 306 | if (exponent < 0) sticky |= Sall(opnd) << (32+exponent); \ | ||
| 307 | inexact = guard | sticky; \ | ||
| 308 | Sall(opnd) >>= (1-exponent); \ | ||
| 309 | } \ | ||
| 310 | else { \ | ||
| 311 | guard = 0; \ | ||
| 312 | sticky |= Sall(opnd); \ | ||
| 313 | inexact = sticky; \ | ||
| 314 | Sgl_setzero(opnd); \ | ||
| 315 | } | ||
| 316 | |||
| 317 | /* | ||
| 318 | * The fused multiply add instructions requires a single extended format, | ||
| 319 | * with 48 bits of mantissa. | ||
| 320 | */ | ||
| 321 | #define SGLEXT_THRESHOLD 48 | ||
| 322 | |||
| 323 | #define Sglext_setzero(valA,valB) \ | ||
| 324 | Sextallp1(valA) = 0; Sextallp2(valB) = 0 | ||
| 325 | |||
| 326 | #define Sglext_isnotzero_mantissap2(valB) (Sextallp2(valB)!=0) | ||
| 327 | #define Sglext_isone_lowp1(val) (Sextlowp1(val)!=0) | ||
| 328 | #define Sglext_isone_highp2(val) (Sexthighp2(val)!=0) | ||
| 329 | #define Sglext_isnotzero_low31p2(val) (Sextlow31p2(val)!=0) | ||
| 330 | #define Sglext_iszero(valA,valB) (Sextallp1(valA)==0 && Sextallp2(valB)==0) | ||
| 331 | |||
| 332 | #define Sgl_copytoptr(src,destptr) *destptr = src | ||
| 333 | #define Sgl_copyfromptr(srcptr,dest) dest = *srcptr | ||
| 334 | #define Sglext_copy(srca,srcb,desta,destb) \ | ||
| 335 | Sextallp1(desta) = Sextallp1(srca); \ | ||
| 336 | Sextallp2(destb) = Sextallp2(srcb) | ||
| 337 | #define Sgl_copyto_sglext(src1,dest1,dest2) \ | ||
| 338 | Sextallp1(dest1) = Sall(src1); Sextallp2(dest2) = 0 | ||
| 339 | |||
| 340 | #define Sglext_swap_lower(leftp2,rightp2) \ | ||
| 341 | Sextallp2(leftp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2); \ | ||
| 342 | Sextallp2(rightp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2); \ | ||
| 343 | Sextallp2(leftp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2) | ||
| 344 | |||
| 345 | #define Sglext_setone_lowmantissap2(value) Deposit_dlowp2(value,1) | ||
| 346 | |||
| 347 | /* The high bit is always zero so arithmetic or logical shifts will work. */ | ||
| 348 | #define Sglext_right_align(srcdstA,srcdstB,shift) \ | ||
| 349 | {int shiftamt, sticky; \ | ||
| 350 | shiftamt = shift % 32; \ | ||
| 351 | sticky = 0; \ | ||
| 352 | switch (shift/32) { \ | ||
| 353 | case 0: if (shiftamt > 0) { \ | ||
| 354 | sticky = Sextallp2(srcdstB) << 32 - (shiftamt); \ | ||
| 355 | Variable_shift_double(Sextallp1(srcdstA), \ | ||
| 356 | Sextallp2(srcdstB),shiftamt,Sextallp2(srcdstB)); \ | ||
| 357 | Sextallp1(srcdstA) >>= shiftamt; \ | ||
| 358 | } \ | ||
| 359 | break; \ | ||
| 360 | case 1: if (shiftamt > 0) { \ | ||
| 361 | sticky = (Sextallp1(srcdstA) << 32 - (shiftamt)) | \ | ||
| 362 | Sextallp2(srcdstB); \ | ||
| 363 | } \ | ||
| 364 | else { \ | ||
| 365 | sticky = Sextallp2(srcdstB); \ | ||
| 366 | } \ | ||
| 367 | Sextallp2(srcdstB) = Sextallp1(srcdstA) >> shiftamt; \ | ||
| 368 | Sextallp1(srcdstA) = 0; \ | ||
| 369 | break; \ | ||
| 370 | } \ | ||
| 371 | if (sticky) Sglext_setone_lowmantissap2(srcdstB); \ | ||
| 372 | } | ||
| 373 | |||
| 374 | /* The left argument is never smaller than the right argument */ | ||
| 375 | #define Sglext_subtract(lefta,leftb,righta,rightb,resulta,resultb) \ | ||
| 376 | if( Sextallp2(rightb) > Sextallp2(leftb) ) Sextallp1(lefta)--; \ | ||
| 377 | Sextallp2(resultb) = Sextallp2(leftb) - Sextallp2(rightb); \ | ||
| 378 | Sextallp1(resulta) = Sextallp1(lefta) - Sextallp1(righta) | ||
| 379 | |||
| 380 | #define Sglext_addition(lefta,leftb,righta,rightb,resulta,resultb) \ | ||
| 381 | /* If the sum of the low words is less than either source, then \ | ||
| 382 | * an overflow into the next word occurred. */ \ | ||
| 383 | if ((Sextallp2(resultb) = Sextallp2(leftb)+Sextallp2(rightb)) < \ | ||
| 384 | Sextallp2(rightb)) \ | ||
| 385 | Sextallp1(resulta) = Sextallp1(lefta)+Sextallp1(righta)+1; \ | ||
| 386 | else Sextallp1(resulta) = Sextallp1(lefta)+Sextallp1(righta) | ||
| 387 | |||
| 388 | |||
| 389 | #define Sglext_arithrightshiftby1(srcdstA,srcdstB) \ | ||
| 390 | Shiftdouble(Sextallp1(srcdstA),Sextallp2(srcdstB),1,Sextallp2(srcdstB)); \ | ||
| 391 | Sextallp1(srcdstA) = (int)Sextallp1(srcdstA) >> 1 | ||
| 392 | |||
| 393 | #define Sglext_leftshiftby8(valA,valB) \ | ||
| 394 | Shiftdouble(Sextallp1(valA),Sextallp2(valB),24,Sextallp1(valA)); \ | ||
| 395 | Sextallp2(valB) <<= 8 | ||
| 396 | #define Sglext_leftshiftby4(valA,valB) \ | ||
| 397 | Shiftdouble(Sextallp1(valA),Sextallp2(valB),28,Sextallp1(valA)); \ | ||
| 398 | Sextallp2(valB) <<= 4 | ||
| 399 | #define Sglext_leftshiftby3(valA,valB) \ | ||
| 400 | Shiftdouble(Sextallp1(valA),Sextallp2(valB),29,Sextallp1(valA)); \ | ||
| 401 | Sextallp2(valB) <<= 3 | ||
| 402 | #define Sglext_leftshiftby2(valA,valB) \ | ||
| 403 | Shiftdouble(Sextallp1(valA),Sextallp2(valB),30,Sextallp1(valA)); \ | ||
| 404 | Sextallp2(valB) <<= 2 | ||
| 405 | #define Sglext_leftshiftby1(valA,valB) \ | ||
| 406 | Shiftdouble(Sextallp1(valA),Sextallp2(valB),31,Sextallp1(valA)); \ | ||
| 407 | Sextallp2(valB) <<= 1 | ||
| 408 | |||
| 409 | #define Sglext_rightshiftby4(valueA,valueB) \ | ||
| 410 | Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),4,Sextallp2(valueB)); \ | ||
| 411 | Sextallp1(valueA) >>= 4 | ||
| 412 | #define Sglext_rightshiftby3(valueA,valueB) \ | ||
| 413 | Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),3,Sextallp2(valueB)); \ | ||
| 414 | Sextallp1(valueA) >>= 3 | ||
| 415 | #define Sglext_rightshiftby1(valueA,valueB) \ | ||
| 416 | Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),1,Sextallp2(valueB)); \ | ||
| 417 | Sextallp1(valueA) >>= 1 | ||
| 418 | |||
| 419 | #define Sglext_xortointp1(left,right,result) Sgl_xortointp1(left,right,result) | ||
| 420 | #define Sglext_xorfromintp1(left,right,result) \ | ||
| 421 | Sgl_xorfromintp1(left,right,result) | ||
| 422 | #define Sglext_copytoint_exponentmantissa(src,dest) \ | ||
| 423 | Sgl_copytoint_exponentmantissa(src,dest) | ||
| 424 | #define Sglext_ismagnitudeless(signlessleft,signlessright) \ | ||
| 425 | Sgl_ismagnitudeless(signlessleft,signlessright) | ||
| 426 | |||
| 427 | #define Sglext_set_sign(dbl_value,sign) Sgl_set_sign(dbl_value,sign) | ||
| 428 | #define Sglext_clear_signexponent_set_hidden(srcdst) \ | ||
| 429 | Sgl_clear_signexponent_set_hidden(srcdst) | ||
| 430 | #define Sglext_clear_signexponent(srcdst) Sgl_clear_signexponent(srcdst) | ||
| 431 | #define Sglext_clear_sign(srcdst) Sgl_clear_sign(srcdst) | ||
| 432 | #define Sglext_isone_hidden(dbl_value) Sgl_isone_hidden(dbl_value) | ||
| 433 | |||
| 434 | #define Sglext_denormalize(opndp1,opndp2,exponent,is_tiny) \ | ||
| 435 | {int sticky; \ | ||
| 436 | is_tiny = TRUE; \ | ||
| 437 | if (exponent == 0 && Sextallp2(opndp2)) { \ | ||
| 438 | switch (Rounding_mode()) { \ | ||
| 439 | case ROUNDPLUS: \ | ||
| 440 | if (Sgl_iszero_sign(opndp1)) \ | ||
| 441 | if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \ | ||
| 442 | is_tiny = FALSE; \ | ||
| 443 | break; \ | ||
| 444 | case ROUNDMINUS: \ | ||
| 445 | if (Sgl_isone_sign(opndp1)) { \ | ||
| 446 | if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \ | ||
| 447 | is_tiny = FALSE; \ | ||
| 448 | } \ | ||
| 449 | break; \ | ||
| 450 | case ROUNDNEAREST: \ | ||
| 451 | if (Sglext_isone_highp2(opndp2) && \ | ||
| 452 | (Sglext_isone_lowp1(opndp1) || \ | ||
| 453 | Sglext_isnotzero_low31p2(opndp2))) \ | ||
| 454 | if (Sgl_isone_hiddenoverflow(opndp1 + 1)) \ | ||
| 455 | is_tiny = FALSE; \ | ||
| 456 | break; \ | ||
| 457 | } \ | ||
| 458 | } \ | ||
| 459 | Sglext_clear_signexponent_set_hidden(opndp1); \ | ||
| 460 | if (exponent >= (1-DBL_P)) { \ | ||
| 461 | if (exponent >= -31) { \ | ||
| 462 | if (exponent > -31) { \ | ||
| 463 | sticky = Sextallp2(opndp2) << 31+exponent; \ | ||
| 464 | Variable_shift_double(opndp1,opndp2,1-exponent,opndp2); \ | ||
| 465 | Sextallp1(opndp1) >>= 1-exponent; \ | ||
| 466 | } \ | ||
| 467 | else { \ | ||
| 468 | sticky = Sextallp2(opndp2); \ | ||
| 469 | Sextallp2(opndp2) = Sextallp1(opndp1); \ | ||
| 470 | Sextallp1(opndp1) = 0; \ | ||
| 471 | } \ | ||
| 472 | } \ | ||
| 473 | else { \ | ||
| 474 | sticky = (Sextallp1(opndp1) << 31+exponent) | \ | ||
| 475 | Sextallp2(opndp2); \ | ||
| 476 | Sextallp2(opndp2) = Sextallp1(opndp1) >> -31-exponent; \ | ||
| 477 | Sextallp1(opndp1) = 0; \ | ||
| 478 | } \ | ||
| 479 | } \ | ||
| 480 | else { \ | ||
| 481 | sticky = Sextallp1(opndp1) | Sextallp2(opndp2); \ | ||
| 482 | Sglext_setzero(opndp1,opndp2); \ | ||
| 483 | } \ | ||
| 484 | if (sticky) Sglext_setone_lowmantissap2(opndp2); \ | ||
| 485 | exponent = 0; \ | ||
| 486 | } | ||
