|
|
1.1 ! root 1: /* ! 2: * FPU op helpers ! 3: * ! 4: * Copyright (c) 2003-2005 Fabrice Bellard ! 5: * ! 6: * This library is free software; you can redistribute it and/or ! 7: * modify it under the terms of the GNU Lesser General Public ! 8: * License as published by the Free Software Foundation; either ! 9: * version 2 of the License, or (at your option) any later version. ! 10: * ! 11: * This library is distributed in the hope that it will be useful, ! 12: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 14: * Lesser General Public License for more details. ! 15: * ! 16: * You should have received a copy of the GNU Lesser General Public ! 17: * License along with this library; if not, see <http://www.gnu.org/licenses/>. ! 18: */ ! 19: ! 20: #include "cpu.h" ! 21: #include "helper.h" ! 22: ! 23: #define QT0 (env->qt0) ! 24: #define QT1 (env->qt1) ! 25: ! 26: static void check_ieee_exceptions(CPUState *env) ! 27: { ! 28: target_ulong status; ! 29: ! 30: status = get_float_exception_flags(&env->fp_status); ! 31: if (status) { ! 32: /* Copy IEEE 754 flags into FSR */ ! 33: if (status & float_flag_invalid) { ! 34: env->fsr |= FSR_NVC; ! 35: } ! 36: if (status & float_flag_overflow) { ! 37: env->fsr |= FSR_OFC; ! 38: } ! 39: if (status & float_flag_underflow) { ! 40: env->fsr |= FSR_UFC; ! 41: } ! 42: if (status & float_flag_divbyzero) { ! 43: env->fsr |= FSR_DZC; ! 44: } ! 45: if (status & float_flag_inexact) { ! 46: env->fsr |= FSR_NXC; ! 47: } ! 48: ! 49: if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) { ! 50: /* Unmasked exception, generate a trap */ ! 51: env->fsr |= FSR_FTT_IEEE_EXCP; ! 52: helper_raise_exception(env, TT_FP_EXCP); ! 53: } else { ! 54: /* Accumulate exceptions */ ! 55: env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5; ! 56: } ! 57: } ! 58: } ! 59: ! 60: static inline void clear_float_exceptions(CPUState *env) ! 61: { ! 62: set_float_exception_flags(0, &env->fp_status); ! 63: } ! 64: ! 65: #define F_HELPER(name, p) void helper_f##name##p(CPUState *env) ! 66: ! 67: #define F_BINOP(name) \ ! 68: float32 helper_f ## name ## s (CPUState *env, float32 src1, \ ! 69: float32 src2) \ ! 70: { \ ! 71: float32 ret; \ ! 72: clear_float_exceptions(env); \ ! 73: ret = float32_ ## name (src1, src2, &env->fp_status); \ ! 74: check_ieee_exceptions(env); \ ! 75: return ret; \ ! 76: } \ ! 77: float64 helper_f ## name ## d (CPUState * env, float64 src1,\ ! 78: float64 src2) \ ! 79: { \ ! 80: float64 ret; \ ! 81: clear_float_exceptions(env); \ ! 82: ret = float64_ ## name (src1, src2, &env->fp_status); \ ! 83: check_ieee_exceptions(env); \ ! 84: return ret; \ ! 85: } \ ! 86: F_HELPER(name, q) \ ! 87: { \ ! 88: clear_float_exceptions(env); \ ! 89: QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \ ! 90: check_ieee_exceptions(env); \ ! 91: } ! 92: ! 93: F_BINOP(add); ! 94: F_BINOP(sub); ! 95: F_BINOP(mul); ! 96: F_BINOP(div); ! 97: #undef F_BINOP ! 98: ! 99: float64 helper_fsmuld(CPUState *env, float32 src1, float32 src2) ! 100: { ! 101: float64 ret; ! 102: clear_float_exceptions(env); ! 103: ret = float64_mul(float32_to_float64(src1, &env->fp_status), ! 104: float32_to_float64(src2, &env->fp_status), ! 105: &env->fp_status); ! 106: check_ieee_exceptions(env); ! 107: return ret; ! 108: } ! 109: ! 110: void helper_fdmulq(CPUState *env, float64 src1, float64 src2) ! 111: { ! 112: clear_float_exceptions(env); ! 113: QT0 = float128_mul(float64_to_float128(src1, &env->fp_status), ! 114: float64_to_float128(src2, &env->fp_status), ! 115: &env->fp_status); ! 116: check_ieee_exceptions(env); ! 117: } ! 118: ! 119: float32 helper_fnegs(float32 src) ! 120: { ! 121: return float32_chs(src); ! 122: } ! 123: ! 124: #ifdef TARGET_SPARC64 ! 125: float64 helper_fnegd(float64 src) ! 126: { ! 127: return float64_chs(src); ! 128: } ! 129: ! 130: F_HELPER(neg, q) ! 131: { ! 132: QT0 = float128_chs(QT1); ! 133: } ! 134: #endif ! 135: ! 136: /* Integer to float conversion. */ ! 137: float32 helper_fitos(CPUState *env, int32_t src) ! 138: { ! 139: /* Inexact error possible converting int to float. */ ! 140: float32 ret; ! 141: clear_float_exceptions(env); ! 142: ret = int32_to_float32(src, &env->fp_status); ! 143: check_ieee_exceptions(env); ! 144: return ret; ! 145: } ! 146: ! 147: float64 helper_fitod(CPUState *env, int32_t src) ! 148: { ! 149: /* No possible exceptions converting int to double. */ ! 150: return int32_to_float64(src, &env->fp_status); ! 151: } ! 152: ! 153: void helper_fitoq(CPUState *env, int32_t src) ! 154: { ! 155: /* No possible exceptions converting int to long double. */ ! 156: QT0 = int32_to_float128(src, &env->fp_status); ! 157: } ! 158: ! 159: #ifdef TARGET_SPARC64 ! 160: float32 helper_fxtos(CPUState *env, int64_t src) ! 161: { ! 162: float32 ret; ! 163: clear_float_exceptions(env); ! 164: ret = int64_to_float32(src, &env->fp_status); ! 165: check_ieee_exceptions(env); ! 166: return ret; ! 167: } ! 168: ! 169: float64 helper_fxtod(CPUState *env, int64_t src) ! 170: { ! 171: float64 ret; ! 172: clear_float_exceptions(env); ! 173: ret = int64_to_float64(src, &env->fp_status); ! 174: check_ieee_exceptions(env); ! 175: return ret; ! 176: } ! 177: ! 178: void helper_fxtoq(CPUState *env, int64_t src) ! 179: { ! 180: /* No possible exceptions converting long long to long double. */ ! 181: QT0 = int64_to_float128(src, &env->fp_status); ! 182: } ! 183: #endif ! 184: #undef F_HELPER ! 185: ! 186: /* floating point conversion */ ! 187: float32 helper_fdtos(CPUState *env, float64 src) ! 188: { ! 189: float32 ret; ! 190: clear_float_exceptions(env); ! 191: ret = float64_to_float32(src, &env->fp_status); ! 192: check_ieee_exceptions(env); ! 193: return ret; ! 194: } ! 195: ! 196: float64 helper_fstod(CPUState *env, float32 src) ! 197: { ! 198: float64 ret; ! 199: clear_float_exceptions(env); ! 200: ret = float32_to_float64(src, &env->fp_status); ! 201: check_ieee_exceptions(env); ! 202: return ret; ! 203: } ! 204: ! 205: float32 helper_fqtos(CPUState *env) ! 206: { ! 207: float32 ret; ! 208: clear_float_exceptions(env); ! 209: ret = float128_to_float32(QT1, &env->fp_status); ! 210: check_ieee_exceptions(env); ! 211: return ret; ! 212: } ! 213: ! 214: void helper_fstoq(CPUState *env, float32 src) ! 215: { ! 216: clear_float_exceptions(env); ! 217: QT0 = float32_to_float128(src, &env->fp_status); ! 218: check_ieee_exceptions(env); ! 219: } ! 220: ! 221: float64 helper_fqtod(CPUState *env) ! 222: { ! 223: float64 ret; ! 224: clear_float_exceptions(env); ! 225: ret = float128_to_float64(QT1, &env->fp_status); ! 226: check_ieee_exceptions(env); ! 227: return ret; ! 228: } ! 229: ! 230: void helper_fdtoq(CPUState *env, float64 src) ! 231: { ! 232: clear_float_exceptions(env); ! 233: QT0 = float64_to_float128(src, &env->fp_status); ! 234: check_ieee_exceptions(env); ! 235: } ! 236: ! 237: /* Float to integer conversion. */ ! 238: int32_t helper_fstoi(CPUState *env, float32 src) ! 239: { ! 240: int32_t ret; ! 241: clear_float_exceptions(env); ! 242: ret = float32_to_int32_round_to_zero(src, &env->fp_status); ! 243: check_ieee_exceptions(env); ! 244: return ret; ! 245: } ! 246: ! 247: int32_t helper_fdtoi(CPUState *env, float64 src) ! 248: { ! 249: int32_t ret; ! 250: clear_float_exceptions(env); ! 251: ret = float64_to_int32_round_to_zero(src, &env->fp_status); ! 252: check_ieee_exceptions(env); ! 253: return ret; ! 254: } ! 255: ! 256: int32_t helper_fqtoi(CPUState *env) ! 257: { ! 258: int32_t ret; ! 259: clear_float_exceptions(env); ! 260: ret = float128_to_int32_round_to_zero(QT1, &env->fp_status); ! 261: check_ieee_exceptions(env); ! 262: return ret; ! 263: } ! 264: ! 265: #ifdef TARGET_SPARC64 ! 266: int64_t helper_fstox(CPUState *env, float32 src) ! 267: { ! 268: int64_t ret; ! 269: clear_float_exceptions(env); ! 270: ret = float32_to_int64_round_to_zero(src, &env->fp_status); ! 271: check_ieee_exceptions(env); ! 272: return ret; ! 273: } ! 274: ! 275: int64_t helper_fdtox(CPUState *env, float64 src) ! 276: { ! 277: int64_t ret; ! 278: clear_float_exceptions(env); ! 279: ret = float64_to_int64_round_to_zero(src, &env->fp_status); ! 280: check_ieee_exceptions(env); ! 281: return ret; ! 282: } ! 283: ! 284: int64_t helper_fqtox(CPUState *env) ! 285: { ! 286: int64_t ret; ! 287: clear_float_exceptions(env); ! 288: ret = float128_to_int64_round_to_zero(QT1, &env->fp_status); ! 289: check_ieee_exceptions(env); ! 290: return ret; ! 291: } ! 292: #endif ! 293: ! 294: float32 helper_fabss(float32 src) ! 295: { ! 296: return float32_abs(src); ! 297: } ! 298: ! 299: #ifdef TARGET_SPARC64 ! 300: float64 helper_fabsd(float64 src) ! 301: { ! 302: return float64_abs(src); ! 303: } ! 304: ! 305: void helper_fabsq(CPUState *env) ! 306: { ! 307: QT0 = float128_abs(QT1); ! 308: } ! 309: #endif ! 310: ! 311: float32 helper_fsqrts(CPUState *env, float32 src) ! 312: { ! 313: float32 ret; ! 314: clear_float_exceptions(env); ! 315: ret = float32_sqrt(src, &env->fp_status); ! 316: check_ieee_exceptions(env); ! 317: return ret; ! 318: } ! 319: ! 320: float64 helper_fsqrtd(CPUState *env, float64 src) ! 321: { ! 322: float64 ret; ! 323: clear_float_exceptions(env); ! 324: ret = float64_sqrt(src, &env->fp_status); ! 325: check_ieee_exceptions(env); ! 326: return ret; ! 327: } ! 328: ! 329: void helper_fsqrtq(CPUState *env) ! 330: { ! 331: clear_float_exceptions(env); ! 332: QT0 = float128_sqrt(QT1, &env->fp_status); ! 333: check_ieee_exceptions(env); ! 334: } ! 335: ! 336: #define GEN_FCMP(name, size, reg1, reg2, FS, E) \ ! 337: void glue(helper_, name) (CPUState *env) \ ! 338: { \ ! 339: env->fsr &= FSR_FTT_NMASK; \ ! 340: if (E && (glue(size, _is_any_nan)(reg1) || \ ! 341: glue(size, _is_any_nan)(reg2)) && \ ! 342: (env->fsr & FSR_NVM)) { \ ! 343: env->fsr |= FSR_NVC; \ ! 344: env->fsr |= FSR_FTT_IEEE_EXCP; \ ! 345: helper_raise_exception(env, TT_FP_EXCP); \ ! 346: } \ ! 347: switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \ ! 348: case float_relation_unordered: \ ! 349: if ((env->fsr & FSR_NVM)) { \ ! 350: env->fsr |= FSR_NVC; \ ! 351: env->fsr |= FSR_FTT_IEEE_EXCP; \ ! 352: helper_raise_exception(env, TT_FP_EXCP); \ ! 353: } else { \ ! 354: env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ ! 355: env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \ ! 356: env->fsr |= FSR_NVA; \ ! 357: } \ ! 358: break; \ ! 359: case float_relation_less: \ ! 360: env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ ! 361: env->fsr |= FSR_FCC0 << FS; \ ! 362: break; \ ! 363: case float_relation_greater: \ ! 364: env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ ! 365: env->fsr |= FSR_FCC1 << FS; \ ! 366: break; \ ! 367: default: \ ! 368: env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ ! 369: break; \ ! 370: } \ ! 371: } ! 372: #define GEN_FCMP_T(name, size, FS, E) \ ! 373: void glue(helper_, name)(CPUState *env, size src1, size src2) \ ! 374: { \ ! 375: env->fsr &= FSR_FTT_NMASK; \ ! 376: if (E && (glue(size, _is_any_nan)(src1) || \ ! 377: glue(size, _is_any_nan)(src2)) && \ ! 378: (env->fsr & FSR_NVM)) { \ ! 379: env->fsr |= FSR_NVC; \ ! 380: env->fsr |= FSR_FTT_IEEE_EXCP; \ ! 381: helper_raise_exception(env, TT_FP_EXCP); \ ! 382: } \ ! 383: switch (glue(size, _compare) (src1, src2, &env->fp_status)) { \ ! 384: case float_relation_unordered: \ ! 385: if ((env->fsr & FSR_NVM)) { \ ! 386: env->fsr |= FSR_NVC; \ ! 387: env->fsr |= FSR_FTT_IEEE_EXCP; \ ! 388: helper_raise_exception(env, TT_FP_EXCP); \ ! 389: } else { \ ! 390: env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ ! 391: env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \ ! 392: env->fsr |= FSR_NVA; \ ! 393: } \ ! 394: break; \ ! 395: case float_relation_less: \ ! 396: env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ ! 397: env->fsr |= FSR_FCC0 << FS; \ ! 398: break; \ ! 399: case float_relation_greater: \ ! 400: env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ ! 401: env->fsr |= FSR_FCC1 << FS; \ ! 402: break; \ ! 403: default: \ ! 404: env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \ ! 405: break; \ ! 406: } \ ! 407: } ! 408: ! 409: GEN_FCMP_T(fcmps, float32, 0, 0); ! 410: GEN_FCMP_T(fcmpd, float64, 0, 0); ! 411: ! 412: GEN_FCMP_T(fcmpes, float32, 0, 1); ! 413: GEN_FCMP_T(fcmped, float64, 0, 1); ! 414: ! 415: GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0); ! 416: GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1); ! 417: ! 418: #ifdef TARGET_SPARC64 ! 419: GEN_FCMP_T(fcmps_fcc1, float32, 22, 0); ! 420: GEN_FCMP_T(fcmpd_fcc1, float64, 22, 0); ! 421: GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0); ! 422: ! 423: GEN_FCMP_T(fcmps_fcc2, float32, 24, 0); ! 424: GEN_FCMP_T(fcmpd_fcc2, float64, 24, 0); ! 425: GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0); ! 426: ! 427: GEN_FCMP_T(fcmps_fcc3, float32, 26, 0); ! 428: GEN_FCMP_T(fcmpd_fcc3, float64, 26, 0); ! 429: GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0); ! 430: ! 431: GEN_FCMP_T(fcmpes_fcc1, float32, 22, 1); ! 432: GEN_FCMP_T(fcmped_fcc1, float64, 22, 1); ! 433: GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1); ! 434: ! 435: GEN_FCMP_T(fcmpes_fcc2, float32, 24, 1); ! 436: GEN_FCMP_T(fcmped_fcc2, float64, 24, 1); ! 437: GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1); ! 438: ! 439: GEN_FCMP_T(fcmpes_fcc3, float32, 26, 1); ! 440: GEN_FCMP_T(fcmped_fcc3, float64, 26, 1); ! 441: GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1); ! 442: #endif ! 443: #undef GEN_FCMP_T ! 444: #undef GEN_FCMP ! 445: ! 446: static inline void set_fsr(CPUState *env) ! 447: { ! 448: int rnd_mode; ! 449: ! 450: switch (env->fsr & FSR_RD_MASK) { ! 451: case FSR_RD_NEAREST: ! 452: rnd_mode = float_round_nearest_even; ! 453: break; ! 454: default: ! 455: case FSR_RD_ZERO: ! 456: rnd_mode = float_round_to_zero; ! 457: break; ! 458: case FSR_RD_POS: ! 459: rnd_mode = float_round_up; ! 460: break; ! 461: case FSR_RD_NEG: ! 462: rnd_mode = float_round_down; ! 463: break; ! 464: } ! 465: set_float_rounding_mode(rnd_mode, &env->fp_status); ! 466: } ! 467: ! 468: void helper_ldfsr(CPUState *env, uint32_t new_fsr) ! 469: { ! 470: env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK); ! 471: set_fsr(env); ! 472: } ! 473: ! 474: #ifdef TARGET_SPARC64 ! 475: void helper_ldxfsr(CPUState *env, uint64_t new_fsr) ! 476: { ! 477: env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK); ! 478: set_fsr(env); ! 479: } ! 480: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.