Annotation of tme/ic/sparc/sparc-fpu.c, revision 1.1.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.