|
|
1.1 ! root 1: /* $Id: sparc-fpu.c,v 1.3 2007/01/14 16:32:16 fredette Exp $ */ ! 2: ! 3: /* ic/sparc/sparc-fpu.c - SPARC floating-point unit implementation */ ! 4: ! 5: /* ! 6: * Copyright (c) 2005 Matt Fredette ! 7: * All rights reserved. ! 8: * ! 9: * Redistribution and use in source and binary forms, with or without ! 10: * modification, are permitted provided that the following conditions ! 11: * are met: ! 12: * 1. Redistributions of source code must retain the above copyright ! 13: * notice, this list of conditions and the following disclaimer. ! 14: * 2. Redistributions in binary form must reproduce the above copyright ! 15: * notice, this list of conditions and the following disclaimer in the ! 16: * documentation and/or other materials provided with the distribution. ! 17: * 3. All advertising materials mentioning features or use of this software ! 18: * must display the following acknowledgement: ! 19: * This product includes software developed by Matt Fredette. ! 20: * 4. The name of the author may not be used to endorse or promote products ! 21: * derived from this software without specific prior written permission. ! 22: * ! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR ! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ! 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, ! 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ! 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ! 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ! 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ! 33: * POSSIBILITY OF SUCH DAMAGE. ! 34: */ ! 35: ! 36: #include <tme/common.h> ! 37: _TME_RCSID("$Id: sparc-fpu.c,v 1.3 2007/01/14 16:32:16 fredette Exp $"); ! 38: ! 39: /* includes: */ ! 40: #include "sparc-impl.h" ! 41: ! 42: /* macros: */ ! 43: ! 44: /* these invoke an IEEE 754 operation: */ ! 45: #define _TME_SPARC_FPU_BEGIN \ ! 46: do { \ ! 47: /* at this point, the only possible trap must be \ ! 48: TME_SPARC_FSR_FTT_IEEE754_exception, so we can \ ! 49: clear CEXC: */ \ ! 50: ic->tme_sparc_fpu_fsr &= ~TME_SPARC_FSR_CEXC; \ ! 51: } while (/* CONSTCOND */ 0) ! 52: #define _TME_SPARC_FPU_OP(func, x) \ ! 53: do { \ ! 54: if (__tme_predict_false((func) == NULL)) { \ ! 55: if (ic->tme_sparc_fpu_incomplete_abort) { \ ! 56: abort(); \ ! 57: } \ ! 58: tme_sparc_fpu_exception(ic, TME_SPARC_FSR_FTT_unimplemented_FPop);\ ! 59: } \ ! 60: _TME_SPARC_FPU_BEGIN; \ ! 61: (*(func)) x; \ ! 62: } while (/* CONSTCOND */ 0) ! 63: #define _TME_SPARC_FPU_OP_MONADIC(func, src, dst) \ ! 64: _TME_SPARC_FPU_OP(ic->tme_sparc_fpu_ieee754_ops->func, (&ic->tme_sparc_fpu_ieee754_ctl, src, dst)) ! 65: #define _TME_SPARC_FPU_OP_DYADIC(func, src0, src1, dst) \ ! 66: _TME_SPARC_FPU_OP(ic->tme_sparc_fpu_ieee754_ops->func, (&ic->tme_sparc_fpu_ieee754_ctl, src0, src1, dst)) ! 67: ! 68: /* globals: */ ! 69: ! 70: /* the floating-point condition codes->conditions mapping. this ! 71: array is indexed by the fcc value: */ ! 72: const tme_uint8_t _tme_sparc_conds_fcc[4] = { ! 73: ! 74: /* E: */ ! 75: (0), ! 76: ! 77: /* L: */ ! 78: (TME_BIT(1) /* fbne */ ! 79: | TME_BIT(2) /* fblg */ ! 80: | TME_BIT(3) /* fbul */ ! 81: | TME_BIT(4)), /* fbl */ ! 82: ! 83: /* G: */ ! 84: (TME_BIT(1) /* fbne */ ! 85: | TME_BIT(2) /* fblg */ ! 86: | TME_BIT(5) /* fbug */ ! 87: | TME_BIT(6)), /* fbg */ ! 88: ! 89: /* U: */ ! 90: (TME_BIT(1) /* fbne */ ! 91: | TME_BIT(3) /* fbul */ ! 92: | TME_BIT(5) /* fbug */ ! 93: | TME_BIT(7)) /* fbu */ ! 94: }; ! 95: ! 96: /* this resets the FPU: */ ! 97: void ! 98: tme_sparc_fpu_reset(struct tme_sparc *ic) ! 99: { ! 100: unsigned int fp_i; ! 101: ! 102: /* put nonsignaling NaNs in the floating-point data registers: */ ! 103: for (fp_i = 0; ! 104: fp_i < TME_ARRAY_ELS(ic->tme_sparc_fpu_fpregs); ! 105: fp_i++) { ! 106: ic->tme_sparc_fpu_fpregs[fp_i].tme_float_format = TME_FLOAT_FORMAT_IEEE754_SINGLE; ! 107: ic->tme_sparc_fpu_fpregs[fp_i].tme_float_value_ieee754_single = ic->tme_sparc_fpu_ieee754_ctl.tme_ieee754_ctl_default_nan_single; ! 108: ic->tme_sparc_fpu_fpreg_sizes[fp_i] = sizeof(tme_uint32_t) / sizeof(tme_uint32_t); ! 109: } ! 110: ! 111: /* zero the FSR, except for the version field: */ ! 112: ic->tme_sparc_fpu_fsr &= TME_SPARC_FSR_VER; ! 113: ! 114: /* use the strict compliance operations: */ ! 115: ic->tme_sparc_fpu_ieee754_ops = ic->tme_sparc_fpu_ieee754_ops_strict; ! 116: ! 117: /* the FPU is in execute mode: */ ! 118: ic->tme_sparc_fpu_mode = TME_SPARC_FPU_MODE_EXECUTE; ! 119: } ! 120: ! 121: /* this enables or disables FPU strict compliance: */ ! 122: void ! 123: tme_sparc_fpu_strict(struct tme_sparc_bus_connection *conn_sparc, unsigned int strict) ! 124: { ! 125: struct tme_sparc *ic; ! 126: ! 127: /* recover our IC: */ ! 128: ic = conn_sparc->tme_sparc_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private; ! 129: ! 130: ic->tme_sparc_fpu_ieee754_ops ! 131: = (strict ! 132: ? ic->tme_sparc_fpu_ieee754_ops_strict ! 133: : ic->tme_sparc_fpu_ieee754_ops_user); ! 134: } ! 135: ! 136: /* this handles a sparc FPU exception: */ ! 137: void ! 138: tme_sparc_fpu_exception(struct tme_sparc *ic, tme_uint32_t ftt) ! 139: { ! 140: ! 141: /* the FPU must be in execute mode, and the FQ must be empty: */ ! 142: assert (ic->tme_sparc_fpu_mode == TME_SPARC_FPU_MODE_EXECUTE ! 143: && (ic->tme_sparc_fpu_fsr & TME_SPARC_FSR_QNE) == 0); ! 144: ! 145: /* put the trapping instruction in the FQ: */ ! 146: ic->tme_sparc_fpu_fq[0].tme_sparc_trapqueue_address ! 147: = (TME_SPARC_VERSION(ic) < 9 ! 148: ? ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_PC) ! 149: : ic->tme_sparc_ireg_uint64(TME_SPARC_IREG_PC)); ! 150: ic->tme_sparc_fpu_fq[0].tme_sparc_trapqueue_insn ! 151: = TME_SPARC_INSN; ! 152: ! 153: /* set QNE and the FTT field in the FSR: */ ! 154: ic->tme_sparc_fpu_fsr ! 155: = ((ic->tme_sparc_fpu_fsr & ~TME_SPARC_FSR_FTT) ! 156: | TME_SPARC_FSR_QNE ! 157: | ftt); ! 158: ! 159: /* enter pending exception mode and redispatch to run the next ! 160: instruction: */ ! 161: ic->tme_sparc_fpu_mode = TME_SPARC_FPU_MODE_EXCEPTION_PENDING; ! 162: tme_sparc_redispatch(ic); ! 163: } ! 164: ! 165: /* this checks for a pending sparc FPU trap: */ ! 166: void ! 167: tme_sparc_fpu_exception_check(struct tme_sparc *ic) ! 168: { ! 169: ! 170: /* if the FPU is in pending exception mode: */ ! 171: if (ic->tme_sparc_fpu_mode == TME_SPARC_FPU_MODE_EXCEPTION_PENDING) { ! 172: ! 173: /* enter exception mode and start IU trap processing: */ ! 174: ic->tme_sparc_fpu_mode = TME_SPARC_FPU_MODE_EXCEPTION; ! 175: TME_SPARC_INSN_TRAP(TME_SPARC_TRAP_fp_exception); ! 176: } ! 177: ! 178: /* otherwise, the FPU must be in exception mode: */ ! 179: assert (ic->tme_sparc_fpu_mode == TME_SPARC_FPU_MODE_EXCEPTION); ! 180: ! 181: /* "If an FPop, floating-point load instruction, or floating-point ! 182: branch instruction is executed while the FPU is in fp_exception ! 183: state, the FPU returns to fp_exception_pending state and also ! 184: sets the FSR ftt field to sequence_error. The instruction that ! 185: caused the sequence_error is not entered into the FQ." */ ! 186: /* XXX FIXME - apparently such an instruction does not trap ! 187: immediately, but since it can't run either, I interpret this to ! 188: mean that the instruction is simply ignored: */ ! 189: ic->tme_sparc_fpu_fsr = (ic->tme_sparc_fpu_fsr & ~TME_SPARC_FSR_FTT) | TME_SPARC_FSR_FTT_sequence_error; ! 190: ic->tme_sparc_fpu_mode = TME_SPARC_FPU_MODE_EXCEPTION; ! 191: tme_sparc_redispatch(ic); ! 192: } ! 193: ! 194: /* the IEEE 754 exception handler: */ ! 195: static void ! 196: _tme_sparc_fpu_exception_ieee754(struct tme_ieee754_ctl *ctl, tme_int8_t exception_ieee754) ! 197: { ! 198: struct tme_sparc *ic; ! 199: tme_uint32_t exception_cexc; ! 200: ! 201: /* map the IEEE754 exception(s) to CEXC bit(s): */ ! 202: exception_cexc = 0; ! 203: #define _TME_SPARC_FPU_EXCEPTION_MAP(e_ieee754, e_sparc) \ ! 204: if (((tme_uint8_t) exception_ieee754) & (e_ieee754)) \ ! 205: exception_cexc |= (e_sparc) ! 206: _TME_SPARC_FPU_EXCEPTION_MAP(TME_FLOAT_EXCEPTION_INVALID, TME_SPARC_FSR_CEXC_NVC); ! 207: _TME_SPARC_FPU_EXCEPTION_MAP(TME_FLOAT_EXCEPTION_DIVBYZERO, TME_SPARC_FSR_CEXC_DZC); ! 208: _TME_SPARC_FPU_EXCEPTION_MAP(TME_FLOAT_EXCEPTION_OVERFLOW, TME_SPARC_FSR_CEXC_OFC); ! 209: _TME_SPARC_FPU_EXCEPTION_MAP(TME_FLOAT_EXCEPTION_UNDERFLOW, TME_SPARC_FSR_CEXC_UFC); ! 210: _TME_SPARC_FPU_EXCEPTION_MAP(TME_FLOAT_EXCEPTION_INEXACT, TME_SPARC_FSR_CEXC_NXC); ! 211: if (exception_cexc == 0) { ! 212: abort(); ! 213: } ! 214: ! 215: /* recover our data structure: */ ! 216: ic = (struct tme_sparc *) ctl->tme_ieee754_ctl_private; ! 217: ! 218: /* set the CEXC field in the FSR. "When a floating-point trap ! 219: occurs ... The value of aexc is unchanged", which is why we don't ! 220: update it until we're sure a trap is not going to occur: */ ! 221: TME_FIELD_MASK_DEPOSITU(ic->tme_sparc_fpu_fsr, TME_SPARC_FSR_CEXC, exception_cexc); ! 222: ! 223: /* if any of the new exceptions are unmasked, take the exception: */ ! 224: if (TME_FIELD_MASK_EXTRACTU(ic->tme_sparc_fpu_fsr, TME_SPARC_FSR_TEM) & exception_cexc) { ! 225: ! 226: /* unlock any lock: */ ! 227: if (ic->tme_sparc_fpu_ieee754_ctl.tme_ieee754_ctl_lock_unlock != NULL) { ! 228: (*ic->tme_sparc_fpu_ieee754_ctl.tme_ieee754_ctl_lock_unlock)(); ! 229: ic->tme_sparc_fpu_ieee754_ctl.tme_ieee754_ctl_lock_unlock = NULL; ! 230: } ! 231: ! 232: /* take the exception: */ ! 233: tme_sparc_fpu_exception(ic, TME_SPARC_FSR_FTT_IEEE754_exception); ! 234: } ! 235: ! 236: /* now that we're sure a trap isn't going to happen, update the AEXC ! 237: field in the FSR: */ ! 238: ic->tme_sparc_fpu_fsr |= exception_cexc * (TME_SPARC_FSR_AEXC / TME_SPARC_FSR_CEXC); ! 239: } ! 240: ! 241: TME_SPARC_FORMAT3(tme_sparc32_stdfq, tme_uint32_t) ! 242: { ! 243: TME_SPARC_INSN_PRIV; ! 244: TME_SPARC_INSN_FPU_STORE(sizeof(tme_uint32_t) * 2); ! 245: ! 246: /* "An attempt to execute STDFQ on an implementation without a ! 247: floating-point queue causes an fp_exception trap with FSR.ftt set ! 248: to 4 (sequence_error). On an implementation with a floating-point ! 249: queue, an attempt to execute STDFQ when the FQ is empty (FSR.qne ! 250: = 0) should cause an fp_exception trap with FSR.ftt set to 4 ! 251: (sequence_error)." */ ! 252: if ((ic->tme_sparc_fpu_fsr & TME_SPARC_FSR_QNE) == 0) { ! 253: assert (ic->tme_sparc_fpu_mode == TME_SPARC_FPU_MODE_EXECUTE); ! 254: tme_sparc_fpu_exception(ic, TME_SPARC_FSR_FTT_sequence_error); ! 255: } ! 256: assert (ic->tme_sparc_fpu_mode == TME_SPARC_FPU_MODE_EXCEPTION); ! 257: ! 258: /* store the FQ entry: */ ! 259: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX + 0) ! 260: = ic->tme_sparc_fpu_fq[0].tme_sparc_trapqueue_address; ! 261: ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX + 1) ! 262: = ic->tme_sparc_fpu_fq[0].tme_sparc_trapqueue_insn; ! 263: tme_sparc32_std(ic, _rs1, _rs2, &ic->tme_sparc_ireg_uint32(TME_SPARC_IREG_FPX)); ! 264: ! 265: /* clear the QNE bit and return to execute mode: */ ! 266: ic->tme_sparc_fpu_fsr &= ~TME_SPARC_FSR_QNE; ! 267: ic->tme_sparc_fpu_mode = TME_SPARC_FPU_MODE_EXECUTE; ! 268: ! 269: TME_SPARC_INSN_OK; ! 270: } ! 271: ! 272: /* this checks that the given floating point register number is aligned ! 273: for a certain format: */ ! 274: int ! 275: tme_sparc_fpu_fpreg_aligned(struct tme_sparc *ic, ! 276: unsigned int fpreg_number, ! 277: unsigned int fpreg_format) ! 278: { ! 279: ! 280: /* if the register number is misaligned for the format: */ ! 281: #if (TME_IEEE754_FPREG_FORMAT_SINGLE != 1 || TME_IEEE754_FPREG_FORMAT_DOUBLE != 2 || TME_IEEE754_FPREG_FORMAT_QUAD != 4) ! 282: #error "bad TME_IEEE754_FPREG_FORMAT_ macros" ! 283: #endif ! 284: if (fpreg_number & ((fpreg_format & ~TME_IEEE754_FPREG_FORMAT_BUILTIN) - 1)) { ! 285: if (!(ic->tme_sparc_fpu_flags & TME_SPARC_FPU_FLAG_OK_REG_MISALIGNED)) { ! 286: tme_sparc_fpu_exception(ic, TME_SPARC_FSR_FTT_invalid_fp_register); ! 287: } ! 288: return (FALSE); ! 289: } ! 290: return (TRUE); ! 291: } ! 292: ! 293: /* this forces the given floating point register to assume the given ! 294: format (width, really) in the register file: */ ! 295: void ! 296: tme_sparc_fpu_fpreg_format(struct tme_sparc *ic, ! 297: unsigned int fpreg_number, ! 298: unsigned int fpreg_format) ! 299: { ! 300: ! 301: /* make sure the register is aligned: */ ! 302: if (!tme_sparc_fpu_fpreg_aligned(ic, fpreg_number, fpreg_format)) { ! 303: abort(); ! 304: } ! 305: ! 306: /* make sure the register is in the given format: */ ! 307: tme_ieee754_fpreg_format(ic->tme_sparc_fpu_fpregs, ! 308: ic->tme_sparc_fpu_fpreg_sizes, ! 309: fpreg_number, ! 310: (fpreg_format ! 311: | TME_IEEE754_FPREG_FORMAT_ENDIAN_BIG)); ! 312: } ! 313: ! 314: /* this forces the given floating point register to assume the given ! 315: format (width, really) in the register file, then returns a pointer ! 316: to the register: */ ! 317: static const struct tme_float * ! 318: tme_sparc_fpu_fpreg_read(struct tme_sparc *ic, ! 319: tme_uint32_t fpreg_number_mask, ! 320: unsigned int fpreg_format) ! 321: { ! 322: unsigned int fpreg_number; ! 323: ! 324: /* extract the register number: */ ! 325: fpreg_number = TME_FIELD_MASK_EXTRACTU(TME_SPARC_INSN, fpreg_number_mask); ! 326: ! 327: /* make sure the register is in the given format: */ ! 328: tme_sparc_fpu_fpreg_format(ic, fpreg_number, fpreg_format); ! 329: ! 330: /* return a pointer to the register: */ ! 331: return (&ic->tme_sparc_fpu_fpregs[fpreg_number]); ! 332: } ! 333: ! 334: /* include the automatically generated code: */ ! 335: #include "sparc-fpu-auto.c" ! 336: ! 337: /* this checks for an FPU argument: */ ! 338: int ! 339: tme_sparc_fpu_new(struct tme_sparc *ic, const char * const *args, int *_arg_i, int *_usage, char **_output) ! 340: { ! 341: int arg_i; ! 342: const char *compliance; ! 343: int complete; ! 344: struct tme_ieee754_ctl *ctl; ! 345: tme_uint32_t ver; ! 346: ! 347: /* get the argument index: */ ! 348: arg_i = *_arg_i; ! 349: ! 350: /* if this is not an FPU type, this is not an sparc FPU argument: */ ! 351: if (!TME_ARG_IS(args[arg_i + 0], "fpu-type")) { ! 352: return (FALSE); ! 353: } ! 354: ! 355: /* you can't specify more than one FPU type: */ ! 356: if ((ic->tme_sparc_fpu_fsr & TME_SPARC_FSR_VER) != TME_SPARC_FSR_VER_missing) { ! 357: tme_output_append_error(_output, ! 358: "%s fpu-type %s", ! 359: _("multiple"), ! 360: _("unexpected")); ! 361: *_usage = TRUE; ! 362: return (TRUE); ! 363: } ! 364: ! 365: /* get the FPU type: */ ! 366: if (args[arg_i + 1] == NULL) { ! 367: *_usage = TRUE; ! 368: return (TRUE); ! 369: } ! 370: ver = (*ic->_tme_sparc_fpu_ver)(ic, args[arg_i + 1], NULL); ! 371: if (ver == TME_SPARC_FSR_VER_missing) { ! 372: tme_output_append_error(_output, ! 373: "%s fpu-type %s", ! 374: _("bad"), ! 375: args[arg_i + 1]); ! 376: *_usage = TRUE; ! 377: return (TRUE); ! 378: } ! 379: ic->tme_sparc_fpu_fsr = (ic->tme_sparc_fpu_fsr & ~TME_SPARC_FSR_VER) | ver; ! 380: arg_i += 2; ! 381: ! 382: /* the next argument must be a compliance level: */ ! 383: compliance = args[arg_i + 1]; ! 384: if (!TME_ARG_IS(args[arg_i + 0], "fpu-compliance") ! 385: || compliance == NULL) { ! 386: *_usage = TRUE; ! 387: return (TRUE); ! 388: } ! 389: ic->tme_sparc_fpu_ieee754_ops_user = tme_ieee754_ops_lookup(compliance); ! 390: if (ic->tme_sparc_fpu_ieee754_ops_user == NULL) { ! 391: tme_output_append_error(_output, ! 392: "%s fpu-compliance %s", ! 393: _("bad"), ! 394: compliance); ! 395: *_usage = TRUE; ! 396: return (TRUE); ! 397: } ! 398: arg_i += 2; ! 399: ! 400: /* see if the operations for this compliance level are complete: */ ! 401: #define _TME_SPARC_FPU_OP_CHECK(func) (ic->tme_sparc_fpu_ieee754_ops_user->func != NULL) ! 402: complete ! 403: = (_TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_single_add) ! 404: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_single_div) ! 405: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_single_from_double) ! 406: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_single_mul) ! 407: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_single_mul) ! 408: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_single_sub) ! 409: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_single_sub) ! 410: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_single_sub) ! 411: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_double_add) ! 412: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_double_div) ! 413: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_double_from_single) ! 414: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_double_from_single) ! 415: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_double_from_single) ! 416: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_double_mul) ! 417: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_double_sub) ! 418: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_double_sub) ! 419: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_double_sub) ! 420: && ((ic->tme_sparc_fpu_flags & TME_SPARC_FPU_FLAG_NO_FSQRT) != 0 ! 421: || (_TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_single_sqrt) ! 422: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_double_sqrt) ! 423: && ((ic->tme_sparc_fpu_flags & TME_SPARC_FPU_FLAG_NO_QUAD) != 0 ! 424: || _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_quad_sqrt)))) ! 425: && ((ic->tme_sparc_fpu_flags & TME_SPARC_FPU_FLAG_NO_QUAD) != 0 ! 426: || (_TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_double_from_quad) ! 427: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_quad_add) ! 428: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_quad_div) ! 429: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_quad_from_double) ! 430: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_quad_from_double) ! 431: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_quad_from_double) ! 432: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_quad_from_single) ! 433: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_quad_mul) ! 434: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_quad_mul) ! 435: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_quad_sub) ! 436: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_quad_sub) ! 437: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_quad_sub) ! 438: && _TME_SPARC_FPU_OP_CHECK(tme_ieee754_ops_single_from_quad)))); ! 439: #undef _TME_SPARC_FPU_OP_CHECK ! 440: ! 441: /* if the next argument is an incomplete disposition: */ ! 442: if (TME_ARG_IS(args[arg_i + 0], "fpu-incomplete")) { ! 443: ! 444: if (TME_ARG_IS(args[arg_i + 1], "abort")) { ! 445: ic->tme_sparc_fpu_incomplete_abort = TRUE; ! 446: } ! 447: else if (TME_ARG_IS(args[arg_i + 1], "trap")) { ! 448: ic->tme_sparc_fpu_incomplete_abort = FALSE; ! 449: } ! 450: else { ! 451: tme_output_append_error(_output, ! 452: "%s fpu-incomplete %s", ! 453: _("bad"), ! 454: args[arg_i + 1]); ! 455: *_usage = TRUE; ! 456: return (TRUE); ! 457: } ! 458: arg_i += 2; ! 459: } ! 460: ! 461: /* otherwise, no incomplete disposition is given. if this ! 462: compliance is incomplete: */ ! 463: else if (!complete) { ! 464: tme_output_append_error(_output, ! 465: "%s %s %s fpu-incomplete", ! 466: _("compliance"), ! 467: compliance, ! 468: _("is incomplete, needs")); ! 469: *_usage = TRUE; ! 470: return (TRUE); ! 471: } ! 472: ! 473: /* initialize the IEEE 754 control: */ ! 474: ctl = &ic->tme_sparc_fpu_ieee754_ctl; ! 475: ! 476: /* a private data structure: */ ! 477: ctl->tme_ieee754_ctl_private = ic; ! 478: ! 479: /* the underflow tininess-detection mode. Appendix N.5 of my V8 ! 480: manual says that this is the mode used on the SPARC: */ ! 481: ctl->tme_ieee754_ctl_detect_tininess = TME_IEEE754_CTL_DETECT_TININESS_BEFORE_ROUNDING; ! 482: ! 483: /* the exception function: */ ! 484: ctl->tme_ieee754_ctl_exception = _tme_sparc_fpu_exception_ieee754; ! 485: ! 486: /* we do check whether or not a value is a sNaN when converting it ! 487: from one precision to another: */ ! 488: ctl->tme_ieee754_ctl_check_snan_on_conversion = TRUE; ! 489: ! 490: /* the default generated NaN patterns: */ ! 491: ctl->tme_ieee754_ctl_default_nan_single = 0x7fffffff; ! 492: ctl->tme_ieee754_ctl_default_nan_double.tme_value64_uint32_hi = 0x7fffffff; ! 493: ctl->tme_ieee754_ctl_default_nan_double.tme_value64_uint32_lo = 0xffffffff; ! 494: ctl->tme_ieee754_ctl_default_nan_quad.tme_float_ieee754_quad_hi.tme_value64_uint32_hi = 0x7fffffff; ! 495: ctl->tme_ieee754_ctl_default_nan_quad.tme_float_ieee754_quad_hi.tme_value64_uint32_lo = 0xffffffff; ! 496: ctl->tme_ieee754_ctl_default_nan_quad.tme_float_ieee754_quad_lo.tme_value64_uint32_hi = 0xffffffff; ! 497: ctl->tme_ieee754_ctl_default_nan_quad.tme_float_ieee754_quad_lo.tme_value64_uint32_lo = 0xffffffff; ! 498: ! 499: /* NaN tests: */ ! 500: ctl->tme_ieee754_ctl_is_snan_single = _tme_sparc_fpu_is_snan_single; ! 501: ctl->tme_ieee754_ctl_is_snan_double = _tme_sparc_fpu_is_snan_double; ! 502: ctl->tme_ieee754_ctl_is_snan_quad = _tme_sparc_fpu_is_snan_quad; ! 503: ! 504: /* NaN canonicalization: */ ! 505: ctl->tme_ieee754_ctl_nan_single_to_common = tme_ieee754_default_nan_single_to_common; ! 506: ctl->tme_ieee754_ctl_nan_common_to_single = tme_ieee754_default_nan_common_to_single; ! 507: ctl->tme_ieee754_ctl_nan_double_to_common = tme_ieee754_default_nan_double_to_common; ! 508: ctl->tme_ieee754_ctl_nan_common_to_double = tme_ieee754_default_nan_common_to_double; ! 509: ctl->tme_ieee754_ctl_nan_quad_to_common = tme_ieee754_default_nan_quad_to_common; ! 510: ctl->tme_ieee754_ctl_nan_common_to_quad = tme_ieee754_default_nan_common_to_quad; ! 511: ! 512: /* NaN propagation: */ ! 513: ctl->tme_ieee754_ctl_nan_from_nans_single = _tme_sparc_fpu_nan_from_nans_single; ! 514: ctl->tme_ieee754_ctl_nan_from_nans_double = _tme_sparc_fpu_nan_from_nans_double; ! 515: ctl->tme_ieee754_ctl_nan_from_nans_quad = _tme_sparc_fpu_nan_from_nans_quad; ! 516: ! 517: /* look up the strict compliance operations: */ ! 518: ic->tme_sparc_fpu_ieee754_ops_strict = tme_ieee754_ops_lookup("strict"); ! 519: assert (ic->tme_sparc_fpu_ieee754_ops_strict != NULL); ! 520: ! 521: /* done: */ ! 522: *_arg_i = arg_i; ! 523: return (TRUE); ! 524: } ! 525: ! 526: /* this returns the FPU usage: */ ! 527: void ! 528: tme_sparc_fpu_usage(struct tme_sparc *ic, char **_output) ! 529: { ! 530: tme_output_append_error(_output, ! 531: "[ fpu-type "); ! 532: (*ic->_tme_sparc_fpu_ver)(ic, NULL, _output); ! 533: tme_output_append_error(_output, ! 534: " ] fpu-compliance %s [ fpu-incomplete { abort | trap } ] ]", ! 535: tme_ieee754_compliance_options); ! 536: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.