1 /* 2 * MIPS floating point support 3 * Copyright (C) 1994-2000 Algorithmics Ltd. 4 * 5 * This program is free software; you can distribute it and/or modify it 6 * under the terms of the GNU General Public License (Version 2) as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * for more details. 13 * 14 * You should have received a copy of the GNU General Public License along 15 * with this program; if not, write to the Free Software Foundation, Inc., 16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 17 * 18 * Nov 7, 2000 19 * Modification to allow integration with Linux kernel 20 * 21 * Kevin D. Kissell, kevink@mips.com and Carsten Langgard, carstenl@mips.com 22 * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. 23 */ 24 #ifndef __ARCH_MIPS_MATH_EMU_IEEE754_H 25 #define __ARCH_MIPS_MATH_EMU_IEEE754_H 26 27 #include <asm/byteorder.h> 28 #include <linux/types.h> 29 #include <linux/sched.h> 30 31 /* 32 * Not very pretty, but the Linux kernel's normal va_list definition 33 * does not allow it to be used as a structure element, as it is here. 34 */ 35 #ifndef _STDARG_H 36 #include <stdarg.h> 37 #endif 38 39 #ifdef __LITTLE_ENDIAN 40 struct ieee754dp_konst { 41 unsigned mantlo:32; 42 unsigned manthi:20; 43 unsigned bexp:11; 44 unsigned sign:1; 45 }; 46 struct ieee754sp_konst { 47 unsigned mant:23; 48 unsigned bexp:8; 49 unsigned sign:1; 50 }; 51 52 typedef union _ieee754dp { 53 struct ieee754dp_konst oparts; 54 struct { 55 u64 mant:52; 56 unsigned int bexp:11; 57 unsigned int sign:1; 58 } parts; 59 u64 bits; 60 double d; 61 } ieee754dp; 62 63 typedef union _ieee754sp { 64 struct ieee754sp_konst parts; 65 float f; 66 u32 bits; 67 } ieee754sp; 68 #endif 69 70 #ifdef __BIG_ENDIAN 71 struct ieee754dp_konst { 72 unsigned sign:1; 73 unsigned bexp:11; 74 unsigned manthi:20; 75 unsigned mantlo:32; 76 }; 77 78 typedef union _ieee754dp { 79 struct ieee754dp_konst oparts; 80 struct { 81 unsigned int sign:1; 82 unsigned int bexp:11; 83 u64 mant:52; 84 } parts; 85 double d; 86 u64 bits; 87 } ieee754dp; 88 89 struct ieee754sp_konst { 90 unsigned sign:1; 91 unsigned bexp:8; 92 unsigned mant:23; 93 }; 94 95 typedef union _ieee754sp { 96 struct ieee754sp_konst parts; 97 float f; 98 u32 bits; 99 } ieee754sp; 100 #endif 101 102 /* 103 * single precision (often aka float) 104 */ 105 int ieee754sp_finite(ieee754sp x); 106 int ieee754sp_class(ieee754sp x); 107 108 ieee754sp ieee754sp_abs(ieee754sp x); 109 ieee754sp ieee754sp_neg(ieee754sp x); 110 ieee754sp ieee754sp_scalb(ieee754sp x, int); 111 ieee754sp ieee754sp_logb(ieee754sp x); 112 113 /* x with sign of y */ 114 ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y); 115 116 ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y); 117 ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y); 118 ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y); 119 ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y); 120 121 ieee754sp ieee754sp_fint(int x); 122 ieee754sp ieee754sp_funs(unsigned x); 123 ieee754sp ieee754sp_flong(s64 x); 124 ieee754sp ieee754sp_fulong(u64 x); 125 ieee754sp ieee754sp_fdp(ieee754dp x); 126 127 int ieee754sp_tint(ieee754sp x); 128 unsigned int ieee754sp_tuns(ieee754sp x); 129 s64 ieee754sp_tlong(ieee754sp x); 130 u64 ieee754sp_tulong(ieee754sp x); 131 132 int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop, int sig); 133 /* 134 * basic sp math 135 */ 136 ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip); 137 ieee754sp ieee754sp_frexp(ieee754sp x, int *exp); 138 ieee754sp ieee754sp_ldexp(ieee754sp x, int exp); 139 140 ieee754sp ieee754sp_ceil(ieee754sp x); 141 ieee754sp ieee754sp_floor(ieee754sp x); 142 ieee754sp ieee754sp_trunc(ieee754sp x); 143 144 ieee754sp ieee754sp_sqrt(ieee754sp x); 145 146 /* 147 * double precision (often aka double) 148 */ 149 int ieee754dp_finite(ieee754dp x); 150 int ieee754dp_class(ieee754dp x); 151 152 /* x with sign of y */ 153 ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y); 154 155 ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y); 156 ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y); 157 ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y); 158 ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y); 159 160 ieee754dp ieee754dp_abs(ieee754dp x); 161 ieee754dp ieee754dp_neg(ieee754dp x); 162 ieee754dp ieee754dp_scalb(ieee754dp x, int); 163 164 /* return exponent as integer in floating point format 165 */ 166 ieee754dp ieee754dp_logb(ieee754dp x); 167 168 ieee754dp ieee754dp_fint(int x); 169 ieee754dp ieee754dp_funs(unsigned x); 170 ieee754dp ieee754dp_flong(s64 x); 171 ieee754dp ieee754dp_fulong(u64 x); 172 ieee754dp ieee754dp_fsp(ieee754sp x); 173 174 ieee754dp ieee754dp_ceil(ieee754dp x); 175 ieee754dp ieee754dp_floor(ieee754dp x); 176 ieee754dp ieee754dp_trunc(ieee754dp x); 177 178 int ieee754dp_tint(ieee754dp x); 179 unsigned int ieee754dp_tuns(ieee754dp x); 180 s64 ieee754dp_tlong(ieee754dp x); 181 u64 ieee754dp_tulong(ieee754dp x); 182 183 int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop, int sig); 184 /* 185 * basic sp math 186 */ 187 ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip); 188 ieee754dp ieee754dp_frexp(ieee754dp x, int *exp); 189 ieee754dp ieee754dp_ldexp(ieee754dp x, int exp); 190 191 ieee754dp ieee754dp_ceil(ieee754dp x); 192 ieee754dp ieee754dp_floor(ieee754dp x); 193 ieee754dp ieee754dp_trunc(ieee754dp x); 194 195 ieee754dp ieee754dp_sqrt(ieee754dp x); 196 197 198 199 /* 5 types of floating point number 200 */ 201 #define IEEE754_CLASS_NORM 0x00 202 #define IEEE754_CLASS_ZERO 0x01 203 #define IEEE754_CLASS_DNORM 0x02 204 #define IEEE754_CLASS_INF 0x03 205 #define IEEE754_CLASS_SNAN 0x04 206 #define IEEE754_CLASS_QNAN 0x05 207 208 /* exception numbers */ 209 #define IEEE754_INEXACT 0x01 210 #define IEEE754_UNDERFLOW 0x02 211 #define IEEE754_OVERFLOW 0x04 212 #define IEEE754_ZERO_DIVIDE 0x08 213 #define IEEE754_INVALID_OPERATION 0x10 214 215 /* cmp operators 216 */ 217 #define IEEE754_CLT 0x01 218 #define IEEE754_CEQ 0x02 219 #define IEEE754_CGT 0x04 220 #define IEEE754_CUN 0x08 221 222 /* rounding mode 223 */ 224 #define IEEE754_RN 0 /* round to nearest */ 225 #define IEEE754_RZ 1 /* round toward zero */ 226 #define IEEE754_RD 2 /* round toward -Infinity */ 227 #define IEEE754_RU 3 /* round toward +Infinity */ 228 229 /* other naming */ 230 #define IEEE754_RM IEEE754_RD 231 #define IEEE754_RP IEEE754_RU 232 233 /* "normal" comparisons 234 */ 235 static inline int ieee754sp_eq(ieee754sp x, ieee754sp y) 236 { 237 return ieee754sp_cmp(x, y, IEEE754_CEQ, 0); 238 } 239 240 static inline int ieee754sp_ne(ieee754sp x, ieee754sp y) 241 { 242 return ieee754sp_cmp(x, y, 243 IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0); 244 } 245 246 static inline int ieee754sp_lt(ieee754sp x, ieee754sp y) 247 { 248 return ieee754sp_cmp(x, y, IEEE754_CLT, 0); 249 } 250 251 static inline int ieee754sp_le(ieee754sp x, ieee754sp y) 252 { 253 return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0); 254 } 255 256 static inline int ieee754sp_gt(ieee754sp x, ieee754sp y) 257 { 258 return ieee754sp_cmp(x, y, IEEE754_CGT, 0); 259 } 260 261 262 static inline int ieee754sp_ge(ieee754sp x, ieee754sp y) 263 { 264 return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0); 265 } 266 267 static inline int ieee754dp_eq(ieee754dp x, ieee754dp y) 268 { 269 return ieee754dp_cmp(x, y, IEEE754_CEQ, 0); 270 } 271 272 static inline int ieee754dp_ne(ieee754dp x, ieee754dp y) 273 { 274 return ieee754dp_cmp(x, y, 275 IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0); 276 } 277 278 static inline int ieee754dp_lt(ieee754dp x, ieee754dp y) 279 { 280 return ieee754dp_cmp(x, y, IEEE754_CLT, 0); 281 } 282 283 static inline int ieee754dp_le(ieee754dp x, ieee754dp y) 284 { 285 return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0); 286 } 287 288 static inline int ieee754dp_gt(ieee754dp x, ieee754dp y) 289 { 290 return ieee754dp_cmp(x, y, IEEE754_CGT, 0); 291 } 292 293 static inline int ieee754dp_ge(ieee754dp x, ieee754dp y) 294 { 295 return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0); 296 } 297 298 299 /* 300 * Like strtod 301 */ 302 ieee754dp ieee754dp_fstr(const char *s, char **endp); 303 char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af); 304 305 306 /* 307 * The control status register 308 */ 309 struct _ieee754_csr { 310 #ifdef __BIG_ENDIAN 311 unsigned pad0:7; 312 unsigned nod:1; /* set 1 for no denormalised numbers */ 313 unsigned c:1; /* condition */ 314 unsigned pad1:5; 315 unsigned cx:6; /* exceptions this operation */ 316 unsigned mx:5; /* exception enable mask */ 317 unsigned sx:5; /* exceptions total */ 318 unsigned rm:2; /* current rounding mode */ 319 #endif 320 #ifdef __LITTLE_ENDIAN 321 unsigned rm:2; /* current rounding mode */ 322 unsigned sx:5; /* exceptions total */ 323 unsigned mx:5; /* exception enable mask */ 324 unsigned cx:6; /* exceptions this operation */ 325 unsigned pad1:5; 326 unsigned c:1; /* condition */ 327 unsigned nod:1; /* set 1 for no denormalised numbers */ 328 unsigned pad0:7; 329 #endif 330 }; 331 #define ieee754_csr (*(struct _ieee754_csr *)(¤t->thread.fpu.fcr31)) 332 333 static inline unsigned ieee754_getrm(void) 334 { 335 return (ieee754_csr.rm); 336 } 337 static inline unsigned ieee754_setrm(unsigned rm) 338 { 339 return (ieee754_csr.rm = rm); 340 } 341 342 /* 343 * get current exceptions 344 */ 345 static inline unsigned ieee754_getcx(void) 346 { 347 return (ieee754_csr.cx); 348 } 349 350 /* test for current exception condition 351 */ 352 static inline int ieee754_cxtest(unsigned n) 353 { 354 return (ieee754_csr.cx & n); 355 } 356 357 /* 358 * get sticky exceptions 359 */ 360 static inline unsigned ieee754_getsx(void) 361 { 362 return (ieee754_csr.sx); 363 } 364 365 /* clear sticky conditions 366 */ 367 static inline unsigned ieee754_clrsx(void) 368 { 369 return (ieee754_csr.sx = 0); 370 } 371 372 /* test for sticky exception condition 373 */ 374 static inline int ieee754_sxtest(unsigned n) 375 { 376 return (ieee754_csr.sx & n); 377 } 378 379 /* debugging */ 380 ieee754sp ieee754sp_dump(char *s, ieee754sp x); 381 ieee754dp ieee754dp_dump(char *s, ieee754dp x); 382 383 #define IEEE754_SPCVAL_PZERO 0 384 #define IEEE754_SPCVAL_NZERO 1 385 #define IEEE754_SPCVAL_PONE 2 386 #define IEEE754_SPCVAL_NONE 3 387 #define IEEE754_SPCVAL_PTEN 4 388 #define IEEE754_SPCVAL_NTEN 5 389 #define IEEE754_SPCVAL_PINFINITY 6 390 #define IEEE754_SPCVAL_NINFINITY 7 391 #define IEEE754_SPCVAL_INDEF 8 392 #define IEEE754_SPCVAL_PMAX 9 /* +max norm */ 393 #define IEEE754_SPCVAL_NMAX 10 /* -max norm */ 394 #define IEEE754_SPCVAL_PMIN 11 /* +min norm */ 395 #define IEEE754_SPCVAL_NMIN 12 /* +min norm */ 396 #define IEEE754_SPCVAL_PMIND 13 /* +min denorm */ 397 #define IEEE754_SPCVAL_NMIND 14 /* +min denorm */ 398 #define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */ 399 #define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */ 400 401 extern const struct ieee754dp_konst __ieee754dp_spcvals[]; 402 extern const struct ieee754sp_konst __ieee754sp_spcvals[]; 403 #define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals) 404 #define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals) 405 406 /* 407 * Return infinity with given sign 408 */ 409 #define ieee754dp_inf(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)]) 410 #define ieee754dp_zero(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)]) 411 #define ieee754dp_one(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)]) 412 #define ieee754dp_ten(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)]) 413 #define ieee754dp_indef() (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF]) 414 #define ieee754dp_max(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)]) 415 #define ieee754dp_min(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)]) 416 #define ieee754dp_mind(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)]) 417 #define ieee754dp_1e31() (ieee754dp_spcvals[IEEE754_SPCVAL_P1E31]) 418 #define ieee754dp_1e63() (ieee754dp_spcvals[IEEE754_SPCVAL_P1E63]) 419 420 #define ieee754sp_inf(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)]) 421 #define ieee754sp_zero(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)]) 422 #define ieee754sp_one(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)]) 423 #define ieee754sp_ten(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)]) 424 #define ieee754sp_indef() (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF]) 425 #define ieee754sp_max(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)]) 426 #define ieee754sp_min(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)]) 427 #define ieee754sp_mind(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)]) 428 #define ieee754sp_1e31() (ieee754sp_spcvals[IEEE754_SPCVAL_P1E31]) 429 #define ieee754sp_1e63() (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63]) 430 431 /* 432 * Indefinite integer value 433 */ 434 #define ieee754si_indef() INT_MAX 435 #ifdef LONG_LONG_MAX 436 #define ieee754di_indef() LONG_LONG_MAX 437 #else 438 #define ieee754di_indef() ((s64)(~0ULL>>1)) 439 #endif 440 441 /* IEEE exception context, passed to handler */ 442 struct ieee754xctx { 443 const char *op; /* operation name */ 444 int rt; /* result type */ 445 union { 446 ieee754sp sp; /* single precision */ 447 ieee754dp dp; /* double precision */ 448 #ifdef IEEE854_XP 449 ieee754xp xp; /* extended precision */ 450 #endif 451 int si; /* standard signed integer (32bits) */ 452 s64 di; /* extended signed integer (64bits) */ 453 } rv; /* default result format implied by op */ 454 va_list ap; 455 }; 456 457 /* result types for xctx.rt */ 458 #define IEEE754_RT_SP 0 459 #define IEEE754_RT_DP 1 460 #define IEEE754_RT_XP 2 461 #define IEEE754_RT_SI 3 462 #define IEEE754_RT_DI 4 463 464 extern void ieee754_xcpt(struct ieee754xctx *xcp); 465 466 /* compat */ 467 #define ieee754dp_fix(x) ieee754dp_tint(x) 468 #define ieee754sp_fix(x) ieee754sp_tint(x) 469 470 #endif /* __ARCH_MIPS_MATH_EMU_IEEE754_H */ 471