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