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 41struct ieee754dp_konst { 42 unsigned mantlo:32; 43 unsigned manthi:20; 44 unsigned bexp:11; 45 unsigned sign:1; 46}; 47struct ieee754sp_konst { 48 unsigned mant:23; 49 unsigned bexp:8; 50 unsigned sign:1; 51}; 52 53typedef 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 64typedef union _ieee754sp { 65 struct ieee754sp_konst parts; 66 float f; 67 u32 bits; 68} ieee754sp; 69#endif 70 71#ifdef __BIG_ENDIAN 72struct ieee754dp_konst { 73 unsigned sign:1; 74 unsigned bexp:11; 75 unsigned manthi:20; 76 unsigned mantlo:32; 77}; 78 79typedef 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 90struct ieee754sp_konst { 91 unsigned sign:1; 92 unsigned bexp:8; 93 unsigned mant:23; 94}; 95 96typedef 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*/ 106int ieee754sp_finite(ieee754sp x); 107int ieee754sp_class(ieee754sp x); 108 109ieee754sp ieee754sp_abs(ieee754sp x); 110ieee754sp ieee754sp_neg(ieee754sp x); 111ieee754sp ieee754sp_scalb(ieee754sp x, int); 112ieee754sp ieee754sp_logb(ieee754sp x); 113 114/* x with sign of y */ 115ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y); 116 117ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y); 118ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y); 119ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y); 120ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y); 121 122ieee754sp ieee754sp_fint(int x); 123ieee754sp ieee754sp_funs(unsigned x); 124ieee754sp ieee754sp_flong(s64 x); 125ieee754sp ieee754sp_fulong(u64 x); 126ieee754sp ieee754sp_fdp(ieee754dp x); 127 128int ieee754sp_tint(ieee754sp x); 129unsigned int ieee754sp_tuns(ieee754sp x); 130s64 ieee754sp_tlong(ieee754sp x); 131u64 ieee754sp_tulong(ieee754sp x); 132 133int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop, int sig); 134/* 135 * basic sp math 136 */ 137ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip); 138ieee754sp ieee754sp_frexp(ieee754sp x, int *exp); 139ieee754sp ieee754sp_ldexp(ieee754sp x, int exp); 140 141ieee754sp ieee754sp_ceil(ieee754sp x); 142ieee754sp ieee754sp_floor(ieee754sp x); 143ieee754sp ieee754sp_trunc(ieee754sp x); 144 145ieee754sp ieee754sp_sqrt(ieee754sp x); 146 147/* 148 * double precision (often aka double) 149*/ 150int ieee754dp_finite(ieee754dp x); 151int ieee754dp_class(ieee754dp x); 152 153/* x with sign of y */ 154ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y); 155 156ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y); 157ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y); 158ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y); 159ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y); 160 161ieee754dp ieee754dp_abs(ieee754dp x); 162ieee754dp ieee754dp_neg(ieee754dp x); 163ieee754dp ieee754dp_scalb(ieee754dp x, int); 164 165/* return exponent as integer in floating point format 166 */ 167ieee754dp ieee754dp_logb(ieee754dp x); 168 169ieee754dp ieee754dp_fint(int x); 170ieee754dp ieee754dp_funs(unsigned x); 171ieee754dp ieee754dp_flong(s64 x); 172ieee754dp ieee754dp_fulong(u64 x); 173ieee754dp ieee754dp_fsp(ieee754sp x); 174 175ieee754dp ieee754dp_ceil(ieee754dp x); 176ieee754dp ieee754dp_floor(ieee754dp x); 177ieee754dp ieee754dp_trunc(ieee754dp x); 178 179int ieee754dp_tint(ieee754dp x); 180unsigned int ieee754dp_tuns(ieee754dp x); 181s64 ieee754dp_tlong(ieee754dp x); 182u64 ieee754dp_tulong(ieee754dp x); 183 184int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop, int sig); 185/* 186 * basic sp math 187 */ 188ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip); 189ieee754dp ieee754dp_frexp(ieee754dp x, int *exp); 190ieee754dp ieee754dp_ldexp(ieee754dp x, int exp); 191 192ieee754dp ieee754dp_ceil(ieee754dp x); 193ieee754dp ieee754dp_floor(ieee754dp x); 194ieee754dp ieee754dp_trunc(ieee754dp x); 195 196ieee754dp 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*/ 236static inline int ieee754sp_eq(ieee754sp x, ieee754sp y) 237{ 238 return ieee754sp_cmp(x, y, IEEE754_CEQ, 0); 239} 240 241static 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 247static inline int ieee754sp_lt(ieee754sp x, ieee754sp y) 248{ 249 return ieee754sp_cmp(x, y, IEEE754_CLT, 0); 250} 251 252static inline int ieee754sp_le(ieee754sp x, ieee754sp y) 253{ 254 return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0); 255} 256 257static inline int ieee754sp_gt(ieee754sp x, ieee754sp y) 258{ 259 return ieee754sp_cmp(x, y, IEEE754_CGT, 0); 260} 261 262 263static inline int ieee754sp_ge(ieee754sp x, ieee754sp y) 264{ 265 return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0); 266} 267 268static inline int ieee754dp_eq(ieee754dp x, ieee754dp y) 269{ 270 return ieee754dp_cmp(x, y, IEEE754_CEQ, 0); 271} 272 273static 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 279static inline int ieee754dp_lt(ieee754dp x, ieee754dp y) 280{ 281 return ieee754dp_cmp(x, y, IEEE754_CLT, 0); 282} 283 284static inline int ieee754dp_le(ieee754dp x, ieee754dp y) 285{ 286 return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0); 287} 288 289static inline int ieee754dp_gt(ieee754dp x, ieee754dp y) 290{ 291 return ieee754dp_cmp(x, y, IEEE754_CGT, 0); 292} 293 294static 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 */ 303ieee754dp ieee754dp_fstr(const char *s, char **endp); 304char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af); 305 306 307/* 308 * The control status register 309 */ 310struct _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 334static inline unsigned ieee754_getrm(void) 335{ 336 return (ieee754_csr.rm); 337} 338static inline unsigned ieee754_setrm(unsigned rm) 339{ 340 return (ieee754_csr.rm = rm); 341} 342 343/* 344 * get current exceptions 345 */ 346static inline unsigned ieee754_getcx(void) 347{ 348 return (ieee754_csr.cx); 349} 350 351/* test for current exception condition 352 */ 353static inline int ieee754_cxtest(unsigned n) 354{ 355 return (ieee754_csr.cx & n); 356} 357 358/* 359 * get sticky exceptions 360 */ 361static inline unsigned ieee754_getsx(void) 362{ 363 return (ieee754_csr.sx); 364} 365 366/* clear sticky conditions 367*/ 368static inline unsigned ieee754_clrsx(void) 369{ 370 return (ieee754_csr.sx = 0); 371} 372 373/* test for sticky exception condition 374 */ 375static inline int ieee754_sxtest(unsigned n) 376{ 377 return (ieee754_csr.sx & n); 378} 379 380/* debugging */ 381ieee754sp ieee754sp_dump(char *s, ieee754sp x); 382ieee754dp 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 402extern const struct ieee754dp_konst __ieee754dp_spcvals[]; 403extern 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 */ 443struct 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 465extern 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