Annotation of tme/ic/sparc/sparc-fpu.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.