Annotation of tme/ic/m68k/m6888x.c, revision 1.1.1.2

1.1.1.2 ! root        1: /* $Id: m6888x.c,v 1.4 2007/08/25 20:37:30 fredette Exp $ */
1.1       root        2: 
                      3: /* ic/m68k/m6888x.c - m68k floating-point implementation */
                      4: 
                      5: /*
                      6:  * Copyright (c) 2004 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>
1.1.1.2 ! root       37: _TME_RCSID("$Id: m6888x.c,v 1.4 2007/08/25 20:37:30 fredette Exp $");
1.1       root       38: 
                     39: /* includes: */
                     40: #include "m68k-impl.h"
                     41: 
                     42: /* macros: */
                     43: 
                     44: /* m6888x FPCR bits: */
                     45: #define TME_M6888X_FPCR_RND_MASK       (0x00000030)
                     46: #define  TME_M6888X_FPCR_RND_RN                 (0x00000000)
                     47: #define  TME_M6888X_FPCR_RND_RZ                 (0x00000010)
                     48: #define  TME_M6888X_FPCR_RND_RM                 (0x00000020)
                     49: #define  TME_M6888X_FPCR_RND_RP                 (0x00000030)
                     50: #define TME_M6888X_FPCR_PREC_MASK      (0x000000c0)
                     51: #define  TME_M6888X_FPCR_PREC_X                 (0x00000000)
                     52: #define  TME_M6888X_FPCR_PREC_S                 (0x00000040)
                     53: #define  TME_M6888X_FPCR_PREC_D                 (0x00000080)
                     54: #define  TME_M6888X_FPCR_PREC_UNDEF     (0x000000c0)
                     55: #define TME_M6888X_FPCR_ENABLE_INEX1   TME_BIT(8)
                     56: #define TME_M6888X_FPCR_ENABLE_INEX2   TME_BIT(9)
                     57: #define TME_M6888X_FPCR_ENABLE_DZ      TME_BIT(10)
                     58: #define TME_M6888X_FPCR_ENABLE_UNFL    TME_BIT(11)
                     59: #define TME_M6888X_FPCR_ENABLE_OVFL    TME_BIT(12)
                     60: #define TME_M6888X_FPCR_ENABLE_OPERR   TME_BIT(13)
                     61: #define TME_M6888X_FPCR_ENABLE_SNAN    TME_BIT(14)
                     62: #define TME_M6888X_FPCR_ENABLE_BSUN    TME_BIT(15)
                     63: 
                     64: /* m6888x FPSR bits: */
                     65: #define TME_M6888X_FPSR_AEXC_INEX      TME_BIT(3)
                     66: #define TME_M6888X_FPSR_AEXC_DZ                TME_BIT(4)
                     67: #define TME_M6888X_FPSR_AEXC_UNFL      TME_BIT(5)
                     68: #define TME_M6888X_FPSR_AEXC_OVFL      TME_BIT(6)
                     69: #define TME_M6888X_FPSR_AEXC_IOP       TME_BIT(7)
                     70: #define TME_M6888X_FPSR_EXC_INEX1      TME_M6888X_FPCR_ENABLE_INEX1
                     71: #define TME_M6888X_FPSR_EXC_INEX2      TME_M6888X_FPCR_ENABLE_INEX2
                     72: #define TME_M6888X_FPSR_EXC_DZ         TME_M6888X_FPCR_ENABLE_DZ
                     73: #define TME_M6888X_FPSR_EXC_UNFL       TME_M6888X_FPCR_ENABLE_UNFL
                     74: #define TME_M6888X_FPSR_EXC_OVFL       TME_M6888X_FPCR_ENABLE_OVFL
                     75: #define TME_M6888X_FPSR_EXC_OPERR      TME_M6888X_FPCR_ENABLE_OPERR
                     76: #define TME_M6888X_FPSR_EXC_SNAN       TME_M6888X_FPCR_ENABLE_SNAN
                     77: #define TME_M6888X_FPSR_EXC_BSUN       TME_M6888X_FPCR_ENABLE_BSUN
                     78: #define TME_M6888X_FPSR_QUOTIENT       (0x00ff0000)
                     79: #define TME_M6888X_FPSR_CC_NAN         TME_BIT(24)
                     80: #define TME_M6888X_FPSR_CC_I           TME_BIT(25)
                     81: #define TME_M6888X_FPSR_CC_Z           TME_BIT(26)
                     82: #define TME_M6888X_FPSR_CC_N           TME_BIT(27)
                     83: 
                     84: /* m6888x exceptions: */
                     85: #define TME_M6888X_VECTOR_BSUN         (0x30)
                     86: #define TME_M6888X_VECTOR_INEX         (0x31)
                     87: #define TME_M6888X_VECTOR_DZ           (0x32)
                     88: #define TME_M6888X_VECTOR_UNFL         (0x33)
                     89: #define TME_M6888X_VECTOR_OPERR                (0x34)
                     90: #define TME_M6888X_VECTOR_OVFL         (0x35)
                     91: #define TME_M6888X_VECTOR_SNAN         (0x36)
                     92: 
                     93: /* m6888x frame versions: */
                     94: #define TME_M6888X_FRAME_VERSION_NULL          (0x00)
                     95: #define TME_M6888X_FRAME_VERSION_IDLE_M68881   (0x1f)
                     96: #define TME_M6888X_FRAME_VERSION_IDLE_M68882   (0x21)
                     97: #define TME_M6888X_FRAME_VERSION_IDLE_M68040   (0x23)
                     98: 
                     99: /* m6888x frame sizes: */
                    100: #define TME_M6888X_FRAME_SIZE_NULL             (0x00)
                    101: #define TME_M6888X_FRAME_SIZE_IDLE_M68881      (0x18)
                    102: #define TME_M6888X_FRAME_SIZE_IDLE_M68882      (0x38)
                    103: #define TME_M6888X_FRAME_SIZE_IDLE_M68040      (0x00)
                    104: 
                    105: /* bits in a packed decimal real: */
                    106: #define TME_M6888X_PACKEDDEC_SM                TME_BIT(31)
                    107: #define TME_M6888X_PACKEDDEC_SE                TME_BIT(30)
                    108: #define TME_M6888X_PACKEDDEC_YY                (TME_BIT(29) | TME_BIT(28))
                    109: 
                    110: /* rounding precisions: */
                    111: #define TME_M6888X_ROUNDING_PRECISION_CTL              (0)
                    112: #define TME_M6888X_ROUNDING_PRECISION_SINGLE           (32)
                    113: #define TME_M6888X_ROUNDING_PRECISION_DOUBLE           (64)
                    114: #define TME_M6888X_ROUNDING_PRECISION_EXTENDED80       (80)
                    115: 
                    116: /* operation types: */
                    117: #define TME_M6888X_OPTYPE_MONADIC              (0)
                    118: #define TME_M6888X_OPTYPE_DYADIC_SRC_DST       (1)
                    119: #define TME_M6888X_OPTYPE_DYADIC_DST_SRC       (2)
                    120: 
                    121: /* special opmodes: */
                    122: #define TME_M6888X_FPGEN_OPMODE_FCMP   (0x38)
                    123: #define TME_M6888X_FPGEN_OPMODE_FTST   (0x3a)
                    124: #define TME_M6888X_FPGEN_OPMODE_OTHER  (0xff)
                    125: 
                    126: /* this causes an exception if there is no FPU, or if it isn't enabled: */
                    127: #define TME_M68K_INSN_FPU                              \
                    128: do {                                                   \
                    129:   if (!ic->tme_m68k_fpu_enabled) {                     \
                    130:     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);   \
                    131:   }                                                    \
                    132: } while (/* CONSTCOND */ 0)
                    133: 
                    134: /* these declare an m68k FPgen function: */
                    135: #define TME_M6888X_FPGEN_DECL(name)            \
                    136:   static void name _TME_P((struct tme_m68k *, const struct tme_float *, struct tme_float *))
                    137: #ifdef __STDC__
                    138: #define TME_M6888X_FPGEN(name)                 \
                    139:   static void name(struct tme_m68k *ic, const struct tme_float *src, struct tme_float *dst)
                    140: #else  /* !__STDC__ */
                    141: #define TME_M6888X_FPGEN(name)                 \
                    142:   static void name(ic, src, dst)               \
                    143:   struct tme_m68k *ic;                         \
                    144:   const struct tme_float *src; \
                    145:   struct tme_float *dst;
                    146: #endif /* !__STDC__ */
                    147: 
                    148: /* this gets the offset of a function in the IEEE 754 operations structure: */
                    149: #define TME_M6888X_IEEE754_OP(func)    ((unsigned long) ((char *) &((struct tme_ieee754_ops *) 0)->func))
                    150: 
                    151: /* these invoke an IEEE 754 operation: */
                    152: #define _TME_M6888X_IEEE754_OP(func, x)                        \
                    153: do {                                                   \
                    154:   if ((func) == NULL) {                                        \
                    155:     if (ic->tme_m68k_fpu_incomplete_abort) {           \
                    156:       abort();                                         \
                    157:     }                                                  \
                    158:     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);   \
                    159:   }                                                    \
                    160:   (*(func)) x;                                         \
                    161: } while (/* CONSTCOND */ 0)
                    162: #define TME_M6888X_IEEE754_OP_MONADIC(func, src, dst) \
                    163:   _TME_M6888X_IEEE754_OP(ic->tme_m68k_fpu_ieee754_ops->func, (&ic->tme_m68k_fpu_ieee754_ctl, src, dst))
                    164: #define TME_M6888X_IEEE754_OP_DYADIC(func, src0, src1, dst) \
                    165:   _TME_M6888X_IEEE754_OP(ic->tme_m68k_fpu_ieee754_ops->func, (&ic->tme_m68k_fpu_ieee754_ctl, src0, src1, dst))
                    166: #define TME_M6888X_IEEE754_OP_FUNC(ops_offset) \
                    167:   (*((void **) (((char *) ic->tme_m68k_fpu_ieee754_ops) + (ops_offset))))
                    168: #define TME_M6888X_IEEE754_OP_RUN(ops_offset, t, x) \
                    169:   _TME_M6888X_IEEE754_OP(((void (*) _TME_P(t)) TME_M6888X_IEEE754_OP_FUNC(ops_offset)), x)
                    170: 
                    171: /* this gets the Nth raw unsigned 32-bit word from an EA operand: */
1.1.1.2 ! root      172: #define TME_M6888X_EA_OP32(n)   (ic->tme_m68k_ireg_uint32(op1_ireg32 + (n)))
1.1       root      173: 
                    174: /* this gets the Nth raw digit from a packed decimal operand: */
                    175: #define TME_M6888X_PD_DIGIT(n)  ((TME_M6888X_EA_OP32((n) / 8) >> (4 * ((n) % 8))) & 0xf)
                    176: 
                    177: /* types: */
                    178: 
                    179: /* the FPgen opmode table: */
                    180: struct tme_m6888x_fpgen {
                    181: 
                    182:   /* any m6888x-specific function.  this is normally NULL: */
                    183:   void (*tme_m6888x_fpgen_func) _TME_P((struct tme_m68k *, 
                    184:                                        const struct tme_float *,
                    185:                                        struct tme_float *));
                    186: 
                    187:   /* unless there is an m6888x-specific function, this is the offset
                    188:      in the IEEE 754 operations struct of the function: */
                    189:   unsigned long tme_m6888x_fpgen_func_ops_offset;
                    190: 
                    191:   /* the FPU types that have this function: */
                    192:   tme_uint8_t tme_m6888x_fpgen_fpu_types;
                    193:   
                    194:   /* the operation type: */
                    195:   tme_uint8_t tme_m6888x_fpgen_optype;
                    196: 
                    197:   /* the rounding mode used by the function: */
                    198:   tme_uint8_t tme_m6888x_fpgen_rounding_mode;
                    199: 
                    200:   /* the rounding precision used by the function: */
                    201:   tme_uint8_t tme_m6888x_fpgen_rounding_precision;
                    202: };
                    203: 
                    204: /* an m6888x frame: */
                    205: struct tme_m6888x_frame {
                    206: 
                    207:   /* the frame version: */
                    208:   tme_uint8_t tme_m6888x_frame_version;
                    209: 
                    210:   /* the frame size: */
                    211:   tme_uint8_t tme_m6888x_frame_size;
                    212: 
                    213:   /* reserved: */
                    214:   tme_uint16_t tme_m6888x_frame_reserved2;
                    215: 
                    216:   /* the command/condition register for an IDLE frame: */
                    217:   tme_uint16_t tme_m6888x_frame_ccr;
                    218: 
                    219:   /* reserved: */
                    220:   tme_uint16_t tme_m6888x_frame_reserved6;
                    221: 
                    222:   /* additional words: */
                    223:   tme_uint32_t tme_m6888x_frame_words[(TME_M6888X_FRAME_SIZE_IDLE_M68882 / sizeof(tme_uint32_t)) - 1];
                    224: };
                    225: 
                    226: /* prototypes: */
                    227: TME_M6888X_FPGEN_DECL(_tme_m6888x_fmovecr);
                    228: TME_M6888X_FPGEN_DECL(_tme_m6888x_fsincos);
1.1.1.2 ! root      229: TME_M6888X_FPGEN_DECL(_tme_m6888x_fcmp);
1.1       root      230: TME_M6888X_FPGEN_DECL(_tme_m6888x_ftst);
                    231: TME_M6888X_FPGEN_DECL(_tme_m6888x_ftwotox);
                    232: TME_M6888X_FPGEN_DECL(_tme_m6888x_ftentox);
                    233: TME_M6888X_FPGEN_DECL(_tme_m6888x_flog2);
                    234: TME_M6888X_FPGEN_DECL(_tme_m6888x_fmod);
                    235: TME_M6888X_FPGEN_DECL(_tme_m6888x_frem);
                    236: TME_M6888X_FPGEN_DECL(_tme_m6888x_fsgldiv);
                    237: TME_M6888X_FPGEN_DECL(_tme_m6888x_fsglmul);
                    238: 
                    239: /* globals: */
                    240: 
                    241: /* special fpgen structures: */
                    242: static const struct tme_m6888x_fpgen _tme_m6888x_fpgen_fmovecr = {
                    243:   _tme_m6888x_fmovecr,
                    244:   0,
                    245:   TME_M68K_FPU_ANY,
                    246:   TME_M6888X_OPTYPE_MONADIC,
                    247:   TME_FLOAT_ROUND_NULL,
                    248:   TME_M6888X_ROUNDING_PRECISION_CTL
                    249: };
                    250: static const struct tme_m6888x_fpgen _tme_m6888x_fpgen_fmove_rm = {
                    251:   NULL,
                    252:   0,
                    253:   TME_M68K_FPU_ANY,
                    254:   TME_M6888X_OPTYPE_MONADIC,
                    255:   TME_FLOAT_ROUND_NULL,
                    256:   TME_M6888X_ROUNDING_PRECISION_CTL
                    257: };
                    258: 
                    259: /* include the automatically generated code: */
                    260: #include "m6888x-auto.c"
                    261: 
                    262: /* this resets the FPU: */
                    263: void
                    264: tme_m68k_fpu_reset(struct tme_m68k *ic)
                    265: {
                    266:   unsigned int fp_i;
                    267:   
                    268:   /* put nonsignaling NaNs in the floating-point data registers: */
                    269:   for (fp_i = 0;
                    270:        fp_i < (sizeof(ic->tme_m68k_fpu_fpreg) / sizeof(ic->tme_m68k_fpu_fpreg[0]));
                    271:        fp_i++) {
                    272:     ic->tme_m68k_fpu_fpreg[fp_i].tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
                    273:     ic->tme_m68k_fpu_fpreg[fp_i].tme_float_value_ieee754_extended80 = ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_default_nan_extended80;
                    274:   }
                    275: 
                    276:   /* put zeroes in the floating-point control register, status
                    277:      register, and instruction address register: */
                    278:   ic->tme_m68k_fpu_fpcr = 0;
                    279:   ic->tme_m68k_fpu_fpsr = 0;
                    280:   ic->tme_m68k_fpu_fpiar = 0;
                    281: }
                    282: 
                    283: /* this handles an exception: */
                    284: static void
                    285: _tme_m6888x_exception(struct tme_m68k *ic, tme_uint32_t exceptions)
                    286: {
                    287:   tme_uint8_t vector;
                    288: 
                    289:   /* update the EXC byte in the FPSR: */
                    290:   ic->tme_m68k_fpu_fpsr |= exceptions;
                    291: 
                    292:   /* update the AEXC byte in the FPSR: */
                    293:   if (exceptions & (TME_M6888X_FPSR_EXC_SNAN | TME_M6888X_FPSR_EXC_OPERR | TME_M6888X_FPSR_EXC_BSUN)) {
                    294:     ic->tme_m68k_fpu_fpsr |= TME_M6888X_FPSR_AEXC_IOP;
                    295:   }
                    296:   if (exceptions & TME_M6888X_FPSR_EXC_OVFL) {
                    297:     ic->tme_m68k_fpu_fpsr |= TME_M6888X_FPSR_AEXC_OVFL;
                    298:   }
                    299:   if (exceptions & (TME_M6888X_FPSR_EXC_UNFL | TME_M6888X_FPSR_EXC_INEX2)) {
                    300:     ic->tme_m68k_fpu_fpsr |= TME_M6888X_FPSR_AEXC_UNFL;
                    301:   }
                    302:   if (exceptions & TME_M6888X_FPSR_EXC_DZ) {
                    303:     ic->tme_m68k_fpu_fpsr |= TME_M6888X_FPSR_AEXC_DZ;
                    304:   }
                    305:   if (exceptions & (TME_M6888X_FPSR_EXC_INEX1 | TME_M6888X_FPSR_EXC_INEX2 | TME_M6888X_FPSR_EXC_OVFL)) {
                    306:     ic->tme_m68k_fpu_fpsr |= TME_M6888X_FPSR_AEXC_INEX;
                    307:   }
                    308: 
                    309:   /* if any of the new exceptions are unmasked, take the exception: */
                    310:   if ((ic->tme_m68k_fpu_fpcr & exceptions)) {
                    311: 
                    312:     /* because it's possible for an instruction to cause multiple
                    313:        exceptions, the exceptions are prioritized: */
                    314:     /* XXX FIXME - when the predecrement or postincrement addressing
                    315:        modes are used, are the address registers updated before or
                    316:        after any exceptions are generated? */
                    317:     if (exceptions & TME_M6888X_FPSR_EXC_BSUN) {
                    318:       vector = TME_M6888X_VECTOR_BSUN;
                    319:     }
                    320:     else if (exceptions & TME_M6888X_FPSR_EXC_SNAN) {
                    321:       vector = TME_M6888X_VECTOR_SNAN;
                    322:     }
                    323:     else if (exceptions & TME_M6888X_FPSR_EXC_OPERR) {
                    324:       vector = TME_M6888X_VECTOR_OPERR;
                    325:     }
                    326:     else if (exceptions & TME_M6888X_FPSR_EXC_OVFL) {
                    327:       vector = TME_M6888X_VECTOR_OVFL;
                    328:     }
                    329:     else if (exceptions & TME_M6888X_FPSR_EXC_UNFL) {
                    330:       vector = TME_M6888X_VECTOR_UNFL;
                    331:     }
                    332:     else if (exceptions & TME_M6888X_FPSR_EXC_DZ) {
                    333:       vector = TME_M6888X_VECTOR_DZ;
                    334:     }
                    335:     else {
                    336:       assert (exceptions & (TME_M6888X_FPSR_EXC_INEX2 | TME_M6888X_FPSR_EXC_INEX1));
                    337:       vector = TME_M6888X_VECTOR_INEX;
                    338:     }
                    339: 
                    340:     /* unlock any lock: */
                    341:     if (ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_lock_unlock != NULL) {
                    342:       (*ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_lock_unlock)();
                    343:       ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_lock_unlock = NULL;
                    344:     }
                    345: 
                    346:     /* take the exception: */
                    347:     /* XXX FIXME - we signal all m6888x exceptions as cp
                    348:        Postinstruction exceptions.  exceptions generated by a cpGEN
                    349:        instruction are probably supposed to be cp Preinstruction
                    350:        exceptions, signaled at the time of the next cpGEN instruction: */
                    351:     ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
                    352:     ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
                    353:     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(vector));
                    354:   }
                    355: }
                    356: 
                    357: /* the IEEE 754 exception handler: */
                    358: static void
                    359: _tme_m6888x_exception_ieee754(struct tme_ieee754_ctl *ctl, tme_int8_t exceptions_ieee754)
                    360: {
                    361:   tme_uint32_t exceptions_m6888x;
                    362: 
                    363:   /* map the exceptions: */
                    364:   exceptions_m6888x = 0;
                    365:   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_GENERIC) {
                    366:     exceptions_m6888x |= TME_M6888X_FPSR_EXC_OPERR;
                    367:   }
                    368:   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_INVALID) {
                    369:     exceptions_m6888x |= TME_M6888X_FPSR_EXC_OPERR;
                    370:   }
                    371:   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_DIVBYZERO) {
                    372:     exceptions_m6888x |= TME_M6888X_FPSR_EXC_DZ;
                    373:   }
                    374:   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_OVERFLOW) {
                    375:     exceptions_m6888x |= TME_M6888X_FPSR_EXC_OVFL;
                    376:   }
                    377:   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_UNDERFLOW) {
                    378:     exceptions_m6888x |= TME_M6888X_FPSR_EXC_UNFL;
                    379:   }
                    380:   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_INEXACT) {
                    381:     exceptions_m6888x |= TME_M6888X_FPSR_EXC_INEX2;
                    382:   }
                    383:   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_OVERFLOW_INT) {
                    384:     exceptions_m6888x |= TME_M6888X_FPSR_EXC_OVFL;
                    385:   }
                    386:   /* XXX FIXME - do denormals count as INEX2? */
                    387:   if (exceptions_ieee754 & TME_FLOAT_EXCEPTION_DENORMAL) {
                    388:     exceptions_m6888x |= TME_M6888X_FPSR_EXC_INEX2;
                    389:   }
                    390: 
                    391:   _tme_m6888x_exception((struct tme_m68k *) ctl->tme_ieee754_ctl_private, exceptions_m6888x);
                    392: }
                    393: 
                    394: /* signaling NaN tests: */
                    395: #define _TME_M6888X_IS_SNAN(a) (((a)->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi & TME_BIT(30)) == 0)
                    396: static tme_int8_t
                    397: _tme_m6888x_is_snan_extended80(struct tme_float_ieee754_extended80 *value)
                    398: {
                    399:   return (_TME_M6888X_IS_SNAN(value));
                    400: }
                    401: 
                    402: /* NaN propagation: */
                    403: static void
                    404: _tme_m6888x_nan_from_nans_extended80(struct tme_ieee754_ctl *ctl, 
                    405:                                     const struct tme_float_ieee754_extended80 *a,
                    406:                                     const struct tme_float_ieee754_extended80 *b,
                    407:                                     struct tme_float_ieee754_extended80 *z)
                    408: {
                    409:   struct tme_m68k *ic;
                    410:   int a_is_snan;
                    411:   int b_is_snan;
                    412: 
                    413:   /* recover the m68k: */
                    414:   ic = ctl->tme_ieee754_ctl_private;    
                    415: 
                    416:   /* see if any of the NaNs are signaling NaNs: */
                    417:   a_is_snan = _TME_M6888X_IS_SNAN(a);
                    418:   b_is_snan = _TME_M6888X_IS_SNAN(b);
                    419: 
                    420:   /* if either operand is a signaling NaN: */
                    421:   if (a_is_snan || b_is_snan) {
                    422: 
                    423:     /* signal the signaling NaN: */
                    424:     _tme_m6888x_exception(ic, TME_M6888X_FPSR_EXC_SNAN);
                    425:   }
                    426: 
                    427:   /* if a and b are different NaNs: */
                    428:   if ((a->tme_float_ieee754_extended80_sexp
                    429:        != b->tme_float_ieee754_extended80_sexp)
                    430:       || (a->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi
                    431:          != b->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi)
                    432:       || (a->tme_float_ieee754_extended80_significand.tme_value64_uint32_lo
                    433:          != b->tme_float_ieee754_extended80_significand.tme_value64_uint32_lo)) {
                    434:     
                    435:     /* we need to return the NaN that is the destination operand: */
                    436:     switch (_tme_m6888x_fpgen_opmode_table[TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 7)].tme_m6888x_fpgen_optype) {
                    437:     default:
                    438:     case TME_M6888X_OPTYPE_MONADIC: assert(FALSE);
                    439:     case TME_M6888X_OPTYPE_DYADIC_SRC_DST: a = b; break;
                    440:     case TME_M6888X_OPTYPE_DYADIC_DST_SRC: break;
                    441:     }
                    442:   }
                    443: 
                    444:   /* return a as the NaN, but make sure it's nonsignaling: */
                    445:   *z = *a;
                    446:   z->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi |= TME_BIT(30);
                    447: }
                    448: 
                    449: /* this prepares to run an fpgen instruction: */
                    450: static void inline
                    451: _tme_m6888x_fpgen_enter(struct tme_m68k *ic, const struct tme_m6888x_fpgen *fpgen)
                    452: {
                    453:   tme_int8_t rounding_mode;
                    454:   tme_int8_t rounding_precision;
                    455: 
                    456:   /* set the rounding mode: */
                    457:   rounding_mode = fpgen->tme_m6888x_fpgen_rounding_mode;
                    458:   if (__tme_predict_true(rounding_mode == TME_FLOAT_ROUND_NULL)) {
                    459:     switch (ic->tme_m68k_fpu_fpcr & TME_M6888X_FPCR_RND_MASK) {
                    460:     default: assert(FALSE);
                    461:     case TME_M6888X_FPCR_RND_RN: rounding_mode = TME_FLOAT_ROUND_NEAREST_EVEN; break;
                    462:     case TME_M6888X_FPCR_RND_RZ: rounding_mode = TME_FLOAT_ROUND_TO_ZERO; break;
                    463:     case TME_M6888X_FPCR_RND_RM: rounding_mode = TME_FLOAT_ROUND_DOWN; break;
                    464:     case TME_M6888X_FPCR_RND_RP: rounding_mode = TME_FLOAT_ROUND_UP; break;
                    465:     }
                    466:   }
                    467:   ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_rounding_mode = rounding_mode;
                    468: 
                    469:   /* set the rounding precision: */
                    470:   rounding_precision = fpgen->tme_m6888x_fpgen_rounding_precision;
                    471:   if (__tme_predict_true(rounding_precision == TME_M6888X_ROUNDING_PRECISION_CTL)) {
                    472:     switch (ic->tme_m68k_fpu_fpcr & TME_M6888X_FPCR_PREC_MASK) {
                    473:     default: assert(FALSE); /* FALLTHROUGH */
                    474:     case TME_M6888X_FPCR_PREC_UNDEF: /* FALLTHROUGH */
                    475:     case TME_M6888X_FPCR_PREC_X: rounding_precision = TME_M6888X_ROUNDING_PRECISION_EXTENDED80; break;
                    476:     case TME_M6888X_FPCR_PREC_S: rounding_precision = TME_M6888X_ROUNDING_PRECISION_SINGLE; break;
                    477:     case TME_M6888X_FPCR_PREC_D: rounding_precision = TME_M6888X_ROUNDING_PRECISION_DOUBLE; break;
                    478:     }
                    479:   }
                    480:   ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_extended80_rounding_precision = rounding_precision;
                    481: 
                    482:   /* clear the exception status byte in the FPSR: */
                    483:   ic->tme_m68k_fpu_fpsr
                    484:     &= ~(TME_M6888X_FPSR_EXC_INEX1
                    485:         | TME_M6888X_FPSR_EXC_INEX2
                    486:         | TME_M6888X_FPSR_EXC_DZ
                    487:         | TME_M6888X_FPSR_EXC_UNFL
                    488:         | TME_M6888X_FPSR_EXC_OVFL
                    489:         | TME_M6888X_FPSR_EXC_OPERR
                    490:         | TME_M6888X_FPSR_EXC_SNAN
                    491:         | TME_M6888X_FPSR_EXC_BSUN);
                    492: 
                    493:   /* set the FPIAR: */
                    494:   ic->tme_m68k_fpu_fpiar = ic->tme_m68k_ireg_pc;
                    495: }
                    496: 
                    497: /* this sets the floating-point condition codes: */
                    498: static void inline
                    499: _tme_m6888x_fpcc(struct tme_m68k *ic, const struct tme_float *dst, unsigned int dst_formats)
                    500: {
                    501:   tme_uint32_t fpcc;
                    502: 
                    503:   /* start with no floating-point condition codes: */
                    504:   fpcc = 0;
                    505: 
                    506:   /* set N: */
                    507:   if (tme_float_is_negative(dst, dst_formats)) {
                    508:     fpcc |= TME_M6888X_FPSR_CC_N;
                    509:   }
                    510: 
                    511:   /* set NAN or I or Z: */
                    512:   if (tme_float_is_nan(dst, dst_formats)) {
                    513:     fpcc |= TME_M6888X_FPSR_CC_NAN;
                    514:   }
                    515:   else if (tme_float_is_inf(dst, dst_formats)) {
                    516:     fpcc |= TME_M6888X_FPSR_CC_I;
                    517:   }
                    518:   else if (tme_float_is_zero(dst, dst_formats)) {
                    519:     fpcc |= TME_M6888X_FPSR_CC_Z;
                    520:   }
                    521: 
                    522:   /* set the floating-point condition codes: */
                    523:   ic->tme_m68k_fpu_fpsr
                    524:     = ((ic->tme_m68k_fpu_fpsr
                    525:        & ~(TME_M6888X_FPSR_CC_N
                    526:            | TME_M6888X_FPSR_CC_NAN
                    527:            | TME_M6888X_FPSR_CC_I
                    528:            | TME_M6888X_FPSR_CC_Z))
                    529:        | fpcc);
                    530: }
                    531: 
                    532: TME_M68K_INSN(tme_m68k_fpgen)
                    533: {
                    534:   struct tme_ieee754_ctl *ieee754_ctl;
                    535:   tme_uint16_t command;
                    536:   tme_uint16_t opmode;
                    537:   const struct tme_m6888x_fpgen *fpgen;
                    538:   unsigned int src_ea;
                    539:   const struct tme_float *src;
                    540:   struct tme_float *dst;
                    541:   struct tme_float src_buffer;
                    542:   struct tme_float dst_buffer;
                    543:   struct tme_float conv_buffer;
                    544:   union tme_value64 value64_buffer;
                    545:   struct tme_float_ieee754_extended80 extended80_buffer;
                    546:   unsigned int ea_mode;
                    547:   unsigned int ea_reg;
                    548:   unsigned int ea_size;
1.1.1.2 ! root      549:   unsigned int op1_ireg32;
1.1       root      550:   unsigned int src_specifier;
                    551:   unsigned int digit_i;
                    552:   tme_int32_t packed_value_int32;
                    553:   struct tme_float packed_value_float;
                    554:   tme_int32_t exponent;
                    555: 
                    556:   /* get the IEEE 754 ctl: */
                    557:   ieee754_ctl = &ic->tme_m68k_fpu_ieee754_ctl;
                    558: 
                    559:   /* this is an FPU instruction: */
                    560:   TME_M68K_INSN_FPU;
                    561: 
                    562:   /* get the coprocessor-dependent command word: */
                    563:   command = TME_M68K_INSN_SPECOP;
                    564: 
                    565:   /* if this is an FMOVECR instruction
                    566:      (command word pattern 0101 11dd dooo oooo): */
                    567:   if ((command & 0xfc00) == 0x5c00
                    568:       && TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 6) == 0) {
                    569: 
                    570:     /* use the FMOVECR opmode and FPgen structure: */
                    571:     opmode = TME_M6888X_FPGEN_OPMODE_OTHER;
                    572:     fpgen = &_tme_m6888x_fpgen_fmovecr;
                    573: 
                    574:     /* the source operand does not use the EA: */
                    575:     src_ea = FALSE;
                    576:   }
                    577: 
                    578:   /* otherwise, this is a generic FPgen instruction: */
                    579:   else {
                    580: 
                    581:     /* get the opmode: */
                    582:     opmode = TME_FIELD_EXTRACTU(command, 0, 7);
                    583: 
                    584:     /* decode this instruction: */
                    585:     fpgen = &_tme_m6888x_fpgen_opmode_table[opmode];
                    586: 
                    587:     /* the source operand uses the EA if this is an EA-to-register
                    588:        operation: */
                    589:     src_ea = (command & TME_BIT(14)) != 0;
                    590:   }
                    591: 
                    592:   /* catch illegal instructions: */
                    593:   switch (fpgen->tme_m6888x_fpgen_fpu_types) {
                    594: 
                    595:   case TME_M68K_FPU_M6888X:
                    596:     /* instructions not supported in hardware by the m68040 are caught
                    597:        later: */
                    598:   case TME_M68K_FPU_ANY:
                    599:     break;
                    600:     
                    601:   case TME_M68K_FPU_M68040:
                    602:     if (ic->tme_m68k_fpu_type == TME_M68K_FPU_M68040) {
                    603:       break;
                    604:     }
                    605:     /* FALLTHROUGH */
                    606:   case TME_M68K_FPU_NONE:
                    607:     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
                    608:     break;
                    609:   default:
                    610:     abort();
                    611:   }
                    612:   
                    613:   /* get the source specifier: */
                    614:   src_specifier = TME_FIELD_EXTRACTU(command, 10, 3);
                    615: 
                    616:   /* if the source operand uses the EA: */
                    617:   if (src_ea) {
                    618: 
1.1.1.2 ! root      619:     /* assume that the most-significant first 32-bit part of the
        !           620:        source operand will end up in the internal memx register: */
        !           621:     op1_ireg32 = TME_M68K_IREG_MEMX32;
        !           622: 
1.1       root      623:     /* get the EA mode and register fields: */
                    624:     ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);
                    625:     ea_reg = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
                    626: 
                    627:     /* if this is a data register direct EA: */
                    628:     if (ea_mode == 0) {
                    629:     
                    630:       /* dispatch on the source specifier, since we need to
                    631:         sign-extend a byte or word to long, and we need to check that
                    632:         only a byte, word, long, or single precision source is
                    633:         specified: */
                    634:       switch (src_specifier) {
                    635:       case TME_M6888X_TYPE_LONG:
                    636:       case TME_M6888X_TYPE_SINGLE:
1.1.1.2 ! root      637:        op1_ireg32 = TME_M68K_IREG_D0 + ea_reg;
1.1       root      638:        break;
                    639:       case TME_M6888X_TYPE_WORD:
1.1.1.2 ! root      640:        ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMX32) = (tme_int16_t) TME_M68K_INSN_OP1(tme_int32_t);
1.1       root      641:        break;
                    642:       case TME_M6888X_TYPE_BYTE:
1.1.1.2 ! root      643:        ic->tme_m68k_ireg_int32(TME_M68K_IREG_MEMX32) = (tme_int8_t) TME_M68K_INSN_OP1(tme_int32_t);
1.1       root      644:        break;
                    645:       default:
                    646:        TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
                    647:        break;
                    648:       }
                    649:     }
                    650: 
                    651:     /* otherwise, if this is an address register direct EA: */
                    652:     else if (ea_mode == 1) {
                    653:       TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
                    654:     }
                    655: 
                    656:     /* otherwise, if this is an immediate EA: */
                    657:     else if (ea_mode == 7
                    658:             && ea_reg == 4) {
                    659: 
                    660:       /* _op1 already points to the operand as one or more 32-bit
                    661:          words: */
1.1.1.2 ! root      662:       assert (_op1 == &ic->tme_m68k_ireg_uint32(TME_M68K_IREG_IMM32 + 0));
        !           663:       op1_ireg32 = TME_M68K_IREG_IMM32;
1.1       root      664:     }
                    665: 
                    666:     /* otherwise, this is a memory EA: */
                    667:     else {
                    668: 
                    669:       /* this instruction can fault: */
                    670:       TME_M68K_INSN_CANFAULT;
                    671: 
                    672:       /* adjust ea_reg to reference the address register: */
                    673:       ea_reg += TME_M68K_IREG_A0;
                    674: 
                    675:       /* dispatch on the source specifier to size the operand: */
                    676:       switch (src_specifier) {
                    677:       case TME_M6888X_TYPE_LONG:
                    678:       case TME_M6888X_TYPE_SINGLE:
                    679:        ea_size = TME_M68K_SIZE_32;
                    680:        break;
                    681: 
                    682:       case TME_M6888X_TYPE_PACKEDDEC:
                    683:       case TME_M6888X_TYPE_EXTENDED80:
                    684:        ea_size = TME_M68K_SIZE_96;
                    685:        break;
                    686: 
                    687:       case TME_M6888X_TYPE_WORD:
                    688:        ea_size = TME_M68K_SIZE_16;
                    689:        break;
                    690: 
                    691:       case TME_M6888X_TYPE_DOUBLE:
                    692:        ea_size = TME_M68K_SIZE_64;
                    693:        break;
                    694: 
                    695:       case TME_M6888X_TYPE_BYTE:
                    696:        ea_size = TME_M68K_SIZE_8;
                    697:        break;
                    698: 
                    699:       default:
                    700:        abort();
                    701:       }
                    702: 
                    703:       /* for the effective address predecrement and postincrement
                    704:         modes, we require that these size macros correspond exactly
                    705:         to the number of bytes: */
                    706: #if TME_M68K_SIZE_8 != 1
                    707: #error "TME_M68K_SIZE_8 must be 1"
                    708: #endif
                    709: #if TME_M68K_SIZE_16 != 2
                    710: #error "TME_M68K_SIZE_16 must be 2"
                    711: #endif
                    712: #if TME_M68K_SIZE_32 != 4
                    713: #error "TME_M68K_SIZE_32 must be 4"
                    714: #endif
                    715: #if TME_M68K_SIZE_64 != 8
                    716: #error "TME_M68K_SIZE_64 must be 8"
                    717: #endif
                    718: #if TME_M68K_SIZE_96 != 12
                    719: #error "TME_M68K_SIZE_96 must be 12"
                    720: #endif
                    721: #define TME_M68K_AREG_INCREMENT(areg, size) \
                    722:   ((size) + (((size) == TME_M68K_SIZE_8 && (areg) == TME_M68K_IREG_A7) ? 1 : 0))
                    723: 
                    724:       /* address register indirect postincrement: */
                    725:       if (ea_mode == 3) {
                    726:        /* if we are not restarting, set the effective address: */
                    727:        if (!TME_M68K_SEQUENCE_RESTARTING) {
                    728:          ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
                    729:          ic->tme_m68k_ireg_uint32(ea_reg) += TME_M68K_AREG_INCREMENT(ea_reg, ea_size);
                    730:        }
                    731:       }
                    732: 
                    733:       /* address register indirect predecrement: */
                    734:       else if (ea_mode == 4) {
                    735:        /* if we are not restarting, set the effective address: */
                    736:        if (!TME_M68K_SEQUENCE_RESTARTING) {
                    737:          ic->tme_m68k_ireg_uint32(ea_reg) -= TME_M68K_AREG_INCREMENT(ea_reg, ea_size);
                    738:          ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
                    739:        }
                    740:       }
                    741: 
                    742:       /* dispatch on the operand size to read in the operand as one or
                    743:          more 32-bit words.  we will read up to three 32-bit words
1.1.1.2 ! root      744:          into memx, memy, and memz: */
        !           745:       assert ((TME_M68K_IREG_MEMX32 + 1) == TME_M68K_IREG_MEMY32
        !           746:              && (TME_M68K_IREG_MEMY32 + 1) == TME_M68K_IREG_MEMZ32);
1.1       root      747:       switch (ea_size) {
                    748: 
                    749:        /* this can only happen when the source operand is a byte.  we
                    750:           sign-extend the byte to a long: */
                    751:       case TME_M68K_SIZE_8:
                    752:        tme_m68k_read_memx8(ic);
                    753:        assert (!TME_M68K_SEQUENCE_RESTARTING);
                    754:        ic->tme_m68k_ireg_memx32 = TME_EXT_S8_S32((tme_int8_t) ic->tme_m68k_ireg_memx8);
                    755:        break;
                    756: 
                    757:        /* this can only happen when the source operand is a word.  we
                    758:           sign-extend the word to a long: */
                    759:       case TME_M68K_SIZE_16:
                    760:        tme_m68k_read_memx16(ic);
                    761:        assert (!TME_M68K_SEQUENCE_RESTARTING);
                    762:        ic->tme_m68k_ireg_memx32 = TME_EXT_S16_S32((tme_int16_t) ic->tme_m68k_ireg_memx16);
                    763:        break;
                    764: 
                    765:        /* everything else is one or more 32-bit words: */
                    766:       default:
                    767: 
                    768:        /* read the first 32 bits into the memx register: */
                    769:        tme_m68k_read_memx32(ic);
                    770:        if (ea_size == TME_M68K_SIZE_32) {
                    771:          break;
                    772:        }
                    773: 
                    774:        /* read the second 32 bits into the memy register: */
                    775:        if (!TME_M68K_SEQUENCE_RESTARTING) {
                    776:          ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
                    777:        }
                    778:        tme_m68k_read_mem32(ic, TME_M68K_IREG_MEMY32);
                    779:        if (ea_size == TME_M68K_SIZE_64) {
                    780:          break;
                    781:        }
                    782:          
                    783:        /* read the third 32 bits into the memz register: */
                    784:        if (!TME_M68K_SEQUENCE_RESTARTING) {
                    785:          ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
                    786:        }
                    787:        tme_m68k_read_mem32(ic, TME_M68K_IREG_MEMZ32);
                    788:        break;
                    789:       }
                    790:     }
                    791: 
                    792:     /* convert the operand from one or more raw 32-bit words into the
                    793:        internal extended precision format: */
                    794:     switch (src_specifier) {
                    795:       
                    796:       /* convert a 32-bit integral value.  all of these integral types
                    797:         have already been converted into 32-bit signed integers: */
                    798:     case TME_M6888X_TYPE_BYTE:
                    799:     case TME_M6888X_TYPE_WORD:
                    800:     case TME_M6888X_TYPE_LONG:
1.1.1.2 ! root      801:       tme_ieee754_extended80_from_int32((tme_int32_t) TME_M6888X_EA_OP32(0), &src_buffer);
1.1       root      802:       break;
                    803: 
                    804:       /* convert a single-precision value: */
                    805:     case TME_M6888X_TYPE_SINGLE:
                    806:       tme_ieee754_single_value_set(&conv_buffer, TME_M6888X_EA_OP32(0));
                    807:       TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_extended80_from_single,
                    808:                                    &conv_buffer, 
                    809:                                    &src_buffer);
                    810:       break;
                    811: 
                    812:       /* convert a double-precision value: */
                    813:     case TME_M6888X_TYPE_DOUBLE:
                    814:       /* NB that TME_M6888X_EA_OP32(0) is always the most significant
                    815:         32 bits of the double, regardless of the endianness of the
                    816:         host.  this is how both the executer fetches an immediate
                    817:         double, and how the memory code above reads a double: */
                    818:       value64_buffer.tme_value64_uint32_hi = TME_M6888X_EA_OP32(0);
                    819:       value64_buffer.tme_value64_uint32_lo = TME_M6888X_EA_OP32(1);
                    820:       tme_ieee754_double_value_set(&conv_buffer, value64_buffer);
                    821:       TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_extended80_from_double,
                    822:                                    &conv_buffer, 
                    823:                                    &src_buffer);
                    824:       break;
                    825: 
                    826:       /* assign an extended-precision value: */
                    827:     case TME_M6888X_TYPE_EXTENDED80:
                    828:       /* NB that TME_M6888X_EA_OP32(0) is always the most significant
                    829:         32 bits of the extended80, regardless of the endianness of
                    830:         the host.  this is how both the executer fetches an immediate
                    831:         extended80, and how the memory code above reads a extended80: */
                    832:       extended80_buffer.tme_float_ieee754_extended80_sexp = TME_M6888X_EA_OP32(0) >> 16;
                    833:       extended80_buffer.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi = TME_M6888X_EA_OP32(1);
                    834:       extended80_buffer.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = TME_M6888X_EA_OP32(2);
                    835:       tme_ieee754_extended80_value_set(&src_buffer, extended80_buffer);
                    836:       break;
                    837:       
                    838:     case TME_M6888X_TYPE_PACKEDDEC:
                    839: 
                    840:       /* if this value's SE and YY bits are all set, and the exponent
                    841:         is 0xFFF, the value is either an infinity or a NaN: */
                    842:       if ((TME_M6888X_EA_OP32(0)
                    843:           & (TME_M6888X_PACKEDDEC_SE
                    844:              | TME_M6888X_PACKEDDEC_YY))
                    845:          == (TME_M6888X_PACKEDDEC_SE
                    846:              | TME_M6888X_PACKEDDEC_YY)
                    847:          && TME_M6888X_PD_DIGIT(22) == 0xf
                    848:          && TME_M6888X_PD_DIGIT(21) == 0xf
                    849:          && TME_M6888X_PD_DIGIT(20) == 0xf) {
                    850: 
                    851:        /* "A packed decimal real data format with the SE and both Y
                    852:           bits set, an exponent of $FFF and a nonzero 16-bit [sic]
                    853:           decimal fraction is a NAN.  When the FPU uses this format,
                    854:           the fraction of the NAN is moved bit- by-bit into the
                    855:           extended-precision mantissa of a floating-point data
                    856:           register."
                    857:           
                    858:           moving the fraction bit-by-bit works for the infinities,
                    859:           too, since both the packed decimal and the extended
                    860:           precision infinities have all-bits-zero fractions: */
                    861:        extended80_buffer.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi = TME_M6888X_EA_OP32(1);
                    862:        extended80_buffer.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = TME_M6888X_EA_OP32(2);
                    863:          
                    864:        /* "The exponent of the register is set to signify a NAN,
                    865:           and no conversion occurs.  The MSB of the most
                    866:           significant digit in the decimal fraction (the MSB of
                    867:           digit 15) is a don't care, as in extended-precision NANs,
                    868:           and the MSB of minus one of digit 15 is the SNAN bit. If
                    869:           the NAN bit is a zero, then it is an SNAN."
                    870: 
                    871:           the biased exponent for NaNs and infinities is the same,
                    872:           and the sign bit is a don't care for a NaN: */
                    873:        extended80_buffer.tme_float_ieee754_extended80_sexp
                    874:          = (0x7fff
                    875:             | (TME_M6888X_EA_OP32(0) & TME_M6888X_PACKEDDEC_SM
                    876:                ? 0x8000
                    877:                : 0));
                    878: 
                    879:        /* finally create the source operand: */
                    880:        tme_ieee754_extended80_value_set(&src_buffer, extended80_buffer);
                    881:       }
                    882: 
                    883:       /* otherwise, this should be an in-range value: */
                    884:       else {
                    885: 
                    886:        /* "The FPU does not detect non-decimal digits in the exponent,
                    887:           integer, or fraction digits of an in-range packed decimal real data
                    888:           format.  These non-decimal digits are converted to binary in the
                    889:           same manner as decimal digits; however, the result is probably
                    890:           useless although it is repeatable." */
                    891: 
                    892:        /* convert the significand: */
                    893:        tme_ieee754_extended80_from_int32(TME_M6888X_PD_DIGIT(16), &src_buffer);
                    894:        tme_ieee754_extended80_from_int32(100000000, &conv_buffer);
                    895:        packed_value_int32 = 0;
                    896:        digit_i = 15;
                    897:        do {
                    898:          packed_value_int32 = (packed_value_int32 * 10) + TME_M6888X_PD_DIGIT(digit_i);
                    899:          if ((digit_i % 8) == 0) {
                    900:            TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_mul,
                    901:                                         &src_buffer, 
                    902:                                         &conv_buffer,
                    903:                                         &src_buffer);
                    904:            tme_ieee754_extended80_from_int32(packed_value_int32, &packed_value_float);
                    905:            TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_add,
                    906:                                         &src_buffer, 
                    907:                                         &packed_value_float,
                    908:                                         &src_buffer);
                    909:            packed_value_int32 = 0;
                    910:          }
                    911:        } while (digit_i-- > 0);
                    912:        if (TME_M6888X_EA_OP32(0) & TME_M6888X_PACKEDDEC_SM) {
                    913:          tme_ieee754_extended80_from_int32(-1, &conv_buffer);
                    914:          TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_mul,
                    915:                                       &src_buffer, 
                    916:                                       &conv_buffer,
                    917:                                       &src_buffer);
                    918:        }
                    919:          
                    920:        /* convert the exponent: */
                    921:        exponent = 0;
                    922:        digit_i = 22;
                    923:        do {
                    924:          exponent = (exponent * 10) + TME_M6888X_PD_DIGIT(digit_i);
                    925:        } while (digit_i-- > 21);
                    926:        if (TME_M6888X_EA_OP32(0) & TME_M6888X_PACKEDDEC_SE) {
                    927:          exponent = -exponent;
                    928:        }
                    929: 
                    930:        /* adjust the exponent, since we ignored the implicit decimal
                    931:           point when converting the significand: */
                    932:        exponent -= 16;
                    933: 
                    934:        /* scale the significand: */
                    935:        tme_ieee754_extended80_from_int32(exponent, &conv_buffer);
                    936:        tme_ieee754_extended80_radix10_scale(&ic->tme_m68k_fpu_ieee754_ctl, &src_buffer, &conv_buffer, &src_buffer);
                    937:       }
                    938:       break;
                    939: 
                    940:     default:
                    941:       abort();
                    942:     }
                    943: 
                    944:     /* the source operand is in the buffer: */
                    945:     src = &src_buffer;
                    946:   }
                    947: 
                    948:   /* otherwise, the source operand is in a register: */
                    949:   else {
                    950:     src = &ic->tme_m68k_fpu_fpreg[src_specifier];
                    951:   }
                    952: 
                    953:   /* XXX FIXME - a check for operand types not implemented on the
                    954:      m68040 would go here: */
                    955: 
                    956:   /* do the common fpgen setup: */
                    957:   _tme_m6888x_fpgen_enter(ic, fpgen);
                    958: 
                    959:   /* get the destination operand: */
                    960:   dst = &ic->tme_m68k_fpu_fpreg[TME_FIELD_EXTRACTU(command, 7, 3)];
                    961: 
                    962:   /* dispatch on the opmode to handle any special cases: */
                    963:   switch (opmode) {
                    964: 
                    965:     /* these instructions don't modify the destination register: */
                    966:   case TME_M6888X_FPGEN_OPMODE_FCMP:
                    967:   case TME_M6888X_FPGEN_OPMODE_FTST:
                    968:     dst_buffer = *dst;
                    969:     dst = &dst_buffer;
                    970:     break;
                    971: 
                    972:   default:
                    973:     break;
                    974:   }
                    975: 
                    976:   /* if this instruction is m6888x specific: */
                    977:   if (fpgen->tme_m6888x_fpgen_func != NULL) {
                    978: 
                    979:     /* run the function: */
                    980:     (*fpgen->tme_m6888x_fpgen_func)(ic, src, dst);
                    981:   }
                    982: 
                    983:   /* otherwise, this instruction has an IEEE 754 operation: */
                    984:   else {
                    985: 
                    986:     /* run the function: */
                    987:     switch (fpgen->tme_m6888x_fpgen_optype) {
                    988:     default: assert(FALSE);
                    989:     case TME_M6888X_OPTYPE_MONADIC:
                    990:       TME_M6888X_IEEE754_OP_RUN(fpgen->tme_m6888x_fpgen_func_ops_offset, (struct tme_ieee754_ctl *, const struct tme_float *, struct tme_float *), (&ic->tme_m68k_fpu_ieee754_ctl, src, dst));
                    991:       break;
                    992:     case TME_M6888X_OPTYPE_DYADIC_SRC_DST:
                    993:       TME_M6888X_IEEE754_OP_RUN(fpgen->tme_m6888x_fpgen_func_ops_offset, (struct tme_ieee754_ctl *, const struct tme_float *, const struct tme_float *, struct tme_float *), (&ic->tme_m68k_fpu_ieee754_ctl, src, dst, dst));
                    994:       break;
                    995:     case TME_M6888X_OPTYPE_DYADIC_DST_SRC:
                    996:       TME_M6888X_IEEE754_OP_RUN(fpgen->tme_m6888x_fpgen_func_ops_offset, (struct tme_ieee754_ctl *, const struct tme_float *, const struct tme_float *, struct tme_float *), (&ic->tme_m68k_fpu_ieee754_ctl, dst, src, dst));
                    997:       break;
                    998:     }
                    999:   }
                   1000: 
                   1001:   /* set the floating-point condition codes: */
                   1002:   _tme_m6888x_fpcc(ic, dst, TME_FLOAT_FORMAT_IEEE754_EXTENDED80 | TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN);
                   1003: 
                   1004: #undef TME_M68K_AREG_INCREMENT
                   1005: }
                   1006: 
                   1007: TME_M6888X_FPGEN(_tme_m6888x_fsincos)
                   1008: {
                   1009:   /* "If FPs and FPc are specified to be the same register, the cosine
                   1010:      result is first loaded into the register and then is overwritten
                   1011:      with the sine result." */
                   1012:   TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_extended80_cos,
                   1013:                                src, 
                   1014:                                &ic->tme_m68k_fpu_fpreg[TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 3)]);
                   1015:   TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_extended80_sin,
                   1016:                                src, 
                   1017:                                dst);
                   1018: }
                   1019: 
1.1.1.2 ! root     1020: TME_M6888X_FPGEN(_tme_m6888x_fcmp)
        !          1021: {
        !          1022:   int dst_is_negative;
        !          1023:   int src_is_negative;
        !          1024: 
        !          1025:   /* check for a NaN operand: */
        !          1026:   if (__tme_predict_false(tme_ieee754_extended80_check_nan_dyadic(&ic->tme_m68k_fpu_ieee754_ctl, src, dst, dst))) {
        !          1027:     return;
        !          1028:   }
        !          1029: 
        !          1030:   /* see if the destination is negative: */
        !          1031:   dst_is_negative
        !          1032:     = (tme_float_is_negative(dst,
        !          1033:                             (TME_FLOAT_FORMAT_IEEE754_EXTENDED80
        !          1034:                              | TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN))
        !          1035:        != 0);
        !          1036: 
        !          1037:   /* if the source operand is an infinity: */
        !          1038:   if (tme_ieee754_extended80_is_inf(src)) {
        !          1039: 
        !          1040:     /* see if the source operand is negative infinity: */
        !          1041:     src_is_negative
        !          1042:       = (tme_float_is_negative(src,
        !          1043:                               (TME_FLOAT_FORMAT_IEEE754_EXTENDED80
        !          1044:                                | TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN))
        !          1045:         != 0);
        !          1046: 
        !          1047:     /* if the destination operand is the same infinity as the source operand: */
        !          1048:     if (tme_ieee754_extended80_is_inf(dst)
        !          1049:        && dst_is_negative == src_is_negative) {
        !          1050: 
        !          1051:       /* return a zero, to set Z, with the same sign as the source
        !          1052:         operand, to set N appropriately: */
        !          1053:       tme_ieee754_extended80_value_set_constant(dst, &tme_ieee754_extended80_constant_zero);
        !          1054:       if (src_is_negative) {
        !          1055:        assert (dst->tme_float_format == TME_FLOAT_FORMAT_IEEE754_EXTENDED80);
        !          1056:        dst->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_sexp |= 0x8000;
        !          1057:       }
        !          1058:     }
        !          1059: 
        !          1060:     /* otherwise, either the destination operand is not an infinity
        !          1061:        or it is the other infinity: */
        !          1062:     else {
        !          1063: 
        !          1064:       /* return a one with the opposite sign as the source operand, to
        !          1065:         set N appropriately: */
        !          1066:       tme_ieee754_extended80_value_set_constant(dst, &tme_ieee754_extended80_constant_one);
        !          1067:       if (!src_is_negative) {
        !          1068:        assert (dst->tme_float_format == TME_FLOAT_FORMAT_IEEE754_EXTENDED80);
        !          1069:        dst->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_sexp |= 0x8000;
        !          1070:       }
        !          1071:     }
        !          1072:     return;
        !          1073:   }
        !          1074: 
        !          1075:   /* otherwise, if the destination operand is an infinity: */
        !          1076:   else if (tme_ieee754_extended80_is_inf(dst)) {
        !          1077: 
        !          1078:     /* return a one with the same sign as the destination operand, to
        !          1079:        set N appropriately: */
        !          1080:     tme_ieee754_extended80_value_set_constant(dst, &tme_ieee754_extended80_constant_one);
        !          1081:     if (dst_is_negative) {
        !          1082:       assert (dst->tme_float_format == TME_FLOAT_FORMAT_IEEE754_EXTENDED80);
        !          1083:       dst->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_sexp |= 0x8000;
        !          1084:     }
        !          1085:     return;
        !          1086:   }
        !          1087: 
        !          1088:   /* do the subtraction: */
        !          1089:   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_sub,
        !          1090:                               dst,
        !          1091:                               src,
        !          1092:                               dst);
        !          1093: }
        !          1094: 
1.1       root     1095: TME_M6888X_FPGEN(_tme_m6888x_ftst)
                   1096: {
                   1097:   *dst = *src;
                   1098: }
                   1099: 
                   1100: TME_M6888X_FPGEN(_tme_m6888x_ftwotox)
                   1101: {
                   1102:   struct tme_float two;
                   1103: 
                   1104:   tme_ieee754_extended80_value_set_constant(&two, &tme_ieee754_extended80_constant_2e2ex[0]);
                   1105:   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_pow,
                   1106:                               src, 
                   1107:                               &two,
                   1108:                               dst);
                   1109: }
                   1110: 
                   1111: TME_M6888X_FPGEN(_tme_m6888x_ftentox)
                   1112: {
                   1113:   struct tme_float ten;
                   1114: 
                   1115:   tme_ieee754_extended80_value_set_constant(&ten, &tme_ieee754_extended80_constant_10e2ex[0]);
                   1116:   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_pow,
                   1117:                               src, 
                   1118:                               &ten,
                   1119:                               dst);
                   1120: }
                   1121: 
                   1122: TME_M6888X_FPGEN(_tme_m6888x_flog2)
                   1123: {
                   1124:   struct tme_float log_two;
                   1125: 
                   1126:   /* 2^log2(x) = e^log(x) */
                   1127:   /* log(2^log2(x)) = log(e^log(x)) */
                   1128:   /* log2(x) * log(2) = log(x) * log(e) */
                   1129:   /* log2(x) = log(x) / log(2) */
                   1130: 
                   1131:   TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_extended80_log,
                   1132:                                src,
                   1133:                                dst);
                   1134:   tme_ieee754_extended80_value_set_constant(&log_two, &tme_ieee754_extended80_constant_ln_2);
                   1135:   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_div,
                   1136:                               dst,
                   1137:                               &log_two,
                   1138:                               dst);
                   1139: }
                   1140: 
                   1141: /* this internal function handles fmod and frem: */
                   1142: static void
                   1143: _tme_m6888x_fmodrem(struct tme_m68k *ic, const struct tme_float *src, struct tme_float *dst, int rounding)
                   1144: {
                   1145:   struct tme_float quotient;
                   1146:   struct tme_float quotient_divisor;
                   1147:   tme_int32_t quotient_byte;
                   1148:   struct tme_float two_hundred_fifty_six;
                   1149: 
                   1150:   /* check for a NaN operand: */
                   1151:   if (__tme_predict_false(tme_ieee754_extended80_check_nan_dyadic(&ic->tme_m68k_fpu_ieee754_ctl, src, dst, dst))) {
                   1152:     return;
                   1153:   }
                   1154: 
                   1155:   /* if the source operand is zero, or if the destination operand is infinity: */
                   1156:   if (tme_ieee754_extended80_is_zero(src)
                   1157:       || tme_ieee754_extended80_is_inf(dst)) {
                   1158: 
                   1159:     /* return a NaN: */
                   1160:     dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
                   1161:     dst->tme_float_value_ieee754_extended80 = ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_default_nan_extended80;
                   1162:     return;
                   1163:   }
                   1164: 
                   1165:   /* do the division.  the quotient must not be a NaN: */
                   1166:   ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_rounding_mode = rounding;
                   1167:   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_div, dst, src, &quotient);
                   1168:   assert (!tme_ieee754_extended80_is_nan(&quotient));
                   1169: 
                   1170:   /* round the quotient to an integer: */
                   1171:   /* XXX FIXME we assume that the rounding mode is the same as the division: */
                   1172:   TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_extended80_rint, &quotient, &quotient);
                   1173: 
                   1174:   /* get the remainder: */
                   1175:   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_mul, src, &quotient, &quotient_divisor);
                   1176:   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_sub, dst, &quotient_divisor, dst);
                   1177: 
                   1178:   /* get the quotient's least significant eight bits, eventually
                   1179:      truncating them to seven: */
                   1180:   tme_ieee754_extended80_from_int32(256, &two_hundred_fifty_six);
                   1181:   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_rem, &quotient, &two_hundred_fifty_six, &quotient);
                   1182:   quotient_byte = tme_ieee754_extended80_value_builtin_get(&quotient);
                   1183:   if (quotient_byte >= 0) {
                   1184:     quotient_byte &= 0x7f;
                   1185:   }
                   1186:   else {
                   1187:     quotient_byte = ((-quotient_byte) & 0x7f) | 0x80;
                   1188:   }
                   1189: 
                   1190:   /* update the quotient byte in the FPSR: */
                   1191:   TME_FIELD_MASK_DEPOSITU(ic->tme_m68k_fpu_fpsr, TME_M6888X_FPSR_QUOTIENT, ((tme_uint32_t) quotient_byte));
                   1192: }
                   1193: 
                   1194: TME_M6888X_FPGEN(_tme_m6888x_fmod)
                   1195: {
                   1196:   _tme_m6888x_fmodrem(ic, src, dst, TME_FLOAT_ROUND_TO_ZERO);
                   1197: }
                   1198: 
                   1199: TME_M6888X_FPGEN(_tme_m6888x_frem)
                   1200: {
                   1201:   _tme_m6888x_fmodrem(ic, src, dst, TME_FLOAT_ROUND_NEAREST_EVEN);  
                   1202: }
                   1203: 
                   1204: TME_M6888X_FPGEN(_tme_m6888x_fsgldiv)
                   1205: {
                   1206:   struct tme_float src_trunc, dst_trunc;
                   1207:   struct tme_float_ieee754_extended80 src_buffer, dst_buffer;
                   1208: 
                   1209:   /* check for a NaN operand: */
                   1210:   if (__tme_predict_false(tme_ieee754_extended80_check_nan_dyadic(&ic->tme_m68k_fpu_ieee754_ctl, src, dst, dst))) {
                   1211:     return;
                   1212:   }
                   1213: 
                   1214:   /* if the source and destination operands are both zero or both
                   1215:      infinity: */
                   1216:   if ((tme_ieee754_extended80_is_zero(src)
                   1217:        && tme_ieee754_extended80_is_zero(dst))
                   1218:       || (tme_ieee754_extended80_is_inf(src)
                   1219:          && tme_ieee754_extended80_is_inf(dst))) {
                   1220: 
                   1221:     /* return a NaN: */
                   1222:     dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
                   1223:     dst->tme_float_value_ieee754_extended80 = ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_default_nan_extended80;
                   1224: 
                   1225:     /* set OPERR: */
                   1226:     _tme_m6888x_exception(ic, TME_M6888X_FPSR_EXC_OPERR);
                   1227:     return;
                   1228:   }
                   1229: 
                   1230:   /* truncate the significands of the source and destination to no
                   1231:      more than 24 bits to the right of the point.  24 becomes 25
                   1232:      because the extended80 format includes the explicit integer bit: */
                   1233:   tme_ieee754_extended80_value_set(&src_trunc, *tme_ieee754_extended80_value_get(src, &src_buffer));
                   1234:   src_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi &= 0xffff8000;
                   1235:   src_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = 0x00000000;
                   1236:   tme_ieee754_extended80_value_set(&dst_trunc, *tme_ieee754_extended80_value_get(dst, &dst_buffer));
                   1237:   dst_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi &= 0xffff8000;
                   1238:   dst_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = 0x00000000;
                   1239: 
                   1240:   /* do the division: */
                   1241:   ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_extended80_rounding_precision = 32;
                   1242:   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_div, &dst_trunc, &src_trunc, dst);
                   1243: }
                   1244: 
                   1245: TME_M6888X_FPGEN(_tme_m6888x_fsglmul)
                   1246: {
                   1247:   struct tme_float src_trunc, dst_trunc;
                   1248:   struct tme_float_ieee754_extended80 src_buffer, dst_buffer;
                   1249: 
                   1250:   /* check for a NaN operand: */
                   1251:   if (__tme_predict_false(tme_ieee754_extended80_check_nan_dyadic(&ic->tme_m68k_fpu_ieee754_ctl, src, dst, dst))) {
                   1252:     return;
                   1253:   }
                   1254: 
                   1255:   /* if the source is a zero and the destination is a NaN, or vice
                   1256:      versa: */
                   1257:   if ((tme_ieee754_extended80_is_zero(src)
                   1258:        && tme_ieee754_extended80_is_inf(dst))
                   1259:       || (tme_ieee754_extended80_is_inf(src)
                   1260:          && tme_ieee754_extended80_is_zero(dst))) {
                   1261: 
                   1262:     /* return a NaN: */
                   1263:     dst->tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
                   1264:     dst->tme_float_value_ieee754_extended80 = ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_default_nan_extended80;
                   1265: 
                   1266:     /* if the destination is a zero, set OPERR: */
                   1267:     if (tme_ieee754_extended80_is_zero(dst)) {
                   1268:       _tme_m6888x_exception(ic, TME_M6888X_FPSR_EXC_OPERR);
                   1269:     }
                   1270:     return;
                   1271:   }
                   1272: 
                   1273:   /* truncate the significands of the source and destination to no
                   1274:      more than 24 bits to the right of the point.  24 becomes 25
                   1275:      because the extended80 format includes the explicit integer bit: */
                   1276:   tme_ieee754_extended80_value_set(&src_trunc, *tme_ieee754_extended80_value_get(src, &src_buffer));
                   1277:   src_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi &= 0xffff8000;
                   1278:   src_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = 0x00000000;
                   1279:   tme_ieee754_extended80_value_set(&dst_trunc, *tme_ieee754_extended80_value_get(dst, &dst_buffer));
                   1280:   dst_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi &= 0xffff8000;
                   1281:   dst_trunc.tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = 0x00000000;
                   1282: 
                   1283:   /* do the multiplication: */
                   1284:   ic->tme_m68k_fpu_ieee754_ctl.tme_ieee754_ctl_extended80_rounding_precision = 32;
                   1285:   TME_M6888X_IEEE754_OP_DYADIC(tme_ieee754_ops_extended80_mul, &src_trunc, &dst_trunc, dst);
                   1286: }
                   1287: 
                   1288: TME_M6888X_FPGEN(_tme_m6888x_fmovecr)
                   1289: {
                   1290:   const struct tme_ieee754_extended80_constant *constant;
                   1291:   tme_uint16_t offset;
                   1292: 
                   1293:   offset = TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 7);
                   1294:   
                   1295:   /* the binary powers of 10 offsets: */
                   1296:   if (offset >= 0x33
                   1297:       && offset <= 0x3f) {
                   1298:     constant = &tme_ieee754_extended80_constant_10e2ex[offset - 0x33];
                   1299:   }
                   1300: 
                   1301:   /* anything else: */
                   1302:   else {
                   1303:     switch (offset) {
                   1304:     case 0x00: constant = &tme_ieee754_extended80_constant_pi; break;
                   1305:     case 0x0b: constant = &tme_ieee754_extended80_constant_log10_2; break;
                   1306:     case 0x0c: constant = &tme_ieee754_extended80_constant_e; break;
                   1307:     case 0x0d: constant = &tme_ieee754_extended80_constant_log2_e; break;
                   1308:     case 0x0e: constant = &tme_ieee754_extended80_constant_log10_e; break;
                   1309:     default:
                   1310:     case 0x0f: constant = &tme_ieee754_extended80_constant_zero; break;
                   1311:     case 0x30: constant = &tme_ieee754_extended80_constant_ln_2; break;
                   1312:     case 0x31: constant = &tme_ieee754_extended80_constant_ln_10; break;
                   1313:     case 0x32: constant = &tme_ieee754_extended80_constant_one; break;
                   1314:     }
                   1315:   }
                   1316: 
                   1317:   /* return the result: */
                   1318:   tme_ieee754_extended80_value_set_constant(dst, constant);
                   1319: }
                   1320: 
                   1321: /* this can fault: */
                   1322: TME_M68K_INSN(tme_m68k_fmove_rm)
                   1323: {
                   1324:   unsigned int ea_mode;
                   1325:   unsigned int ea_reg;
                   1326:   unsigned int ea_size;
                   1327:   unsigned int destination_format;
                   1328:   const struct tme_float *src;
                   1329:   struct tme_float src_buffer;
                   1330:   const struct tme_float *dst;
                   1331:   struct tme_float dst_buffer;
                   1332:   unsigned int dst_formats;
                   1333:   int src_is_nan;
                   1334:   tme_int32_t value_int32_raw;
                   1335:   tme_int32_t value_int32;
                   1336:   tme_uint32_t single_buffer;
                   1337:   const union tme_value64 *value64;
                   1338:   union tme_value64 value64_buffer;
                   1339:   const struct tme_float_ieee754_extended80 *extended80;
                   1340:   struct tme_float_ieee754_extended80 extended80_buffer;
                   1341: 
                   1342:   /* get the EA mode and register fields: */
                   1343:   ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);
                   1344:   ea_reg = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
                   1345: 
                   1346:   /* get the destination format: */
                   1347:   destination_format = TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 10, 3);
                   1348: 
                   1349:   /* if this is an address register direct EA, or this is a data
                   1350:      register direct EA and the destination format isn't byte, word,
                   1351:      long, or single, this is an illegal instruction: */
                   1352:   if (ea_mode == 1
                   1353:       || (ea_mode == 0
                   1354:          && destination_format != TME_M6888X_TYPE_BYTE
                   1355:          && destination_format != TME_M6888X_TYPE_WORD
                   1356:          && destination_format != TME_M6888X_TYPE_LONG
                   1357:          && destination_format != TME_M6888X_TYPE_SINGLE)) {
                   1358:     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
                   1359:   }
                   1360: 
                   1361:   /* for the effective address predecrement and postincrement modes,
                   1362:      and for the integer conversions, we require that these size
                   1363:      macros correspond exactly to the number of bytes: */
                   1364: #if TME_M68K_SIZE_8 != 1
                   1365: #error "TME_M68K_SIZE_8 must be 1"
                   1366: #endif
                   1367: #if TME_M68K_SIZE_16 != 2
                   1368: #error "TME_M68K_SIZE_16 must be 2"
                   1369: #endif
                   1370: #if TME_M68K_SIZE_32 != 4
                   1371: #error "TME_M68K_SIZE_32 must be 4"
                   1372: #endif
                   1373: #if TME_M68K_SIZE_64 != 8
                   1374: #error "TME_M68K_SIZE_64 must be 8"
                   1375: #endif
                   1376: #if TME_M68K_SIZE_96 != 12
                   1377: #error "TME_M68K_SIZE_96 must be 12"
                   1378: #endif
                   1379: #define TME_M68K_AREG_INCREMENT(areg, size) \
                   1380:   ((size) + (((size) == TME_M68K_SIZE_8 && (areg) == TME_M68K_IREG_A7) ? 1 : 0))
                   1381: 
                   1382:   /* dispatch on the destination format to get the size of the destination: */
                   1383:   switch (destination_format) {
                   1384:   case TME_M6888X_TYPE_BYTE: ea_size = TME_M68K_SIZE_8; break;
                   1385:   case TME_M6888X_TYPE_WORD: ea_size = TME_M68K_SIZE_16; break;
                   1386:   case TME_M6888X_TYPE_LONG: /* FALLTHROUGH */
                   1387:   case TME_M6888X_TYPE_SINGLE: ea_size = TME_M68K_SIZE_32; break;
                   1388:   case TME_M6888X_TYPE_DOUBLE: ea_size = TME_M68K_SIZE_64; break;
                   1389:   default: assert(FALSE);
                   1390:   case TME_M6888X_TYPE_PACKEDDEC: /* FALLTHROUGH */
                   1391:   case TME_M6888X_TYPE_PACKEDDEC_DK: /* FALLTHROUGH */
                   1392:   case TME_M6888X_TYPE_EXTENDED80: ea_size = TME_M68K_SIZE_96; break;
                   1393:   }
                   1394: 
                   1395:   /* if we're not restarting: */
                   1396:   if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1397: 
                   1398:     /* do the common fpgen setup: */
                   1399:     _tme_m6888x_fpgen_enter(ic, &_tme_m6888x_fpgen_fmove_rm);
                   1400: 
                   1401:     /* get the source register: */
                   1402:     src = &ic->tme_m68k_fpu_fpreg[TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 7, 3)];
                   1403: 
                   1404:     /* check for a NaN operand: */
                   1405:     src_is_nan = tme_ieee754_extended80_check_nan_monadic(&ic->tme_m68k_fpu_ieee754_ctl, src, &src_buffer);
                   1406:     if (src_is_nan) {
                   1407:       src = &src_buffer;
                   1408:     }
                   1409: 
                   1410:     /* assume that the source is the destination: */
                   1411:     dst = src;
                   1412:     dst_formats = TME_FLOAT_FORMAT_IEEE754_EXTENDED80 | TME_FLOAT_FORMAT_IEEE754_EXTENDED80_BUILTIN;
                   1413: 
                   1414:     /* dispatch on the destination format: */
                   1415:     switch (destination_format) {
                   1416: 
                   1417:     case TME_M6888X_TYPE_BYTE:
                   1418:     case TME_M6888X_TYPE_WORD:
                   1419:     case TME_M6888X_TYPE_LONG:
                   1420:       if (src_is_nan) {
                   1421:        /* XXX how is a NaN converted into an integer? */
                   1422:        value_int32 = -1;
                   1423:        _tme_m6888x_exception(ic, TME_M6888X_FPSR_EXC_OPERR);
                   1424:       }
                   1425:       else {
                   1426:        TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_extended80_to_int32, src, &value_int32_raw);
                   1427:        value_int32 = TME_MIN(value_int32_raw, (2147483647 / (1L << (8 * (TME_M68K_SIZE_32 - ea_size)))));
                   1428:        value_int32 = TME_MAX(value_int32, ((-1073741824 * 2) / (1L << (8 * (TME_M68K_SIZE_32 - ea_size)))));
                   1429:        if (tme_ieee754_extended80_is_inf(src)
                   1430:            || value_int32 != value_int32_raw) {
                   1431:          _tme_m6888x_exception(ic, TME_M6888X_FPSR_EXC_OPERR);
                   1432:        }
                   1433:       }
                   1434:       ic->tme_m68k_ireg_memx32 = value_int32;
                   1435:       break;
                   1436: 
                   1437:     case TME_M6888X_TYPE_SINGLE:
                   1438:       TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_single_from_extended80, src, &dst_buffer);
                   1439:       ic->tme_m68k_ireg_memx32 = *tme_ieee754_single_value_get(&dst_buffer, &single_buffer);
                   1440:       dst = &dst_buffer;
                   1441:       dst_formats = TME_FLOAT_FORMAT_IEEE754_SINGLE | TME_FLOAT_FORMAT_IEEE754_SINGLE_BUILTIN;
                   1442:       break;
                   1443: 
                   1444:     case TME_M6888X_TYPE_DOUBLE:
                   1445:       TME_M6888X_IEEE754_OP_MONADIC(tme_ieee754_ops_double_from_extended80, src, &dst_buffer);
                   1446:       value64 = tme_ieee754_double_value_get(&dst_buffer, &value64_buffer);
                   1447:       ic->tme_m68k_ireg_memx32 = value64->tme_value64_uint32_hi;
                   1448:       ic->tme_m68k_ireg_memy32 = value64->tme_value64_uint32_lo;
                   1449:       dst = &dst_buffer;
                   1450:       dst_formats = TME_FLOAT_FORMAT_IEEE754_DOUBLE | TME_FLOAT_FORMAT_IEEE754_DOUBLE_BUILTIN;
                   1451:       break;
                   1452: 
                   1453:     case TME_M6888X_TYPE_EXTENDED80:
                   1454:       extended80 = tme_ieee754_extended80_value_get(src, &extended80_buffer);
                   1455:       ic->tme_m68k_ireg_memx32 = extended80->tme_float_ieee754_extended80_sexp << 16;
                   1456:       ic->tme_m68k_ireg_memy32 = extended80->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi;
                   1457:       ic->tme_m68k_ireg_memz32 = extended80->tme_float_ieee754_extended80_significand.tme_value64_uint32_lo;
                   1458:       break;
                   1459: 
                   1460:     default:
                   1461:       assert(FALSE);
                   1462:       /* FALLTHROUGH */
                   1463: 
                   1464:     case TME_M6888X_TYPE_PACKEDDEC:
                   1465:     case TME_M6888X_TYPE_PACKEDDEC_DK:
                   1466: 
                   1467:       /* we punt on the packed-decimal format for now: */
                   1468:       TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
                   1469:       break;    
                   1470:     }
                   1471: 
                   1472:     /* set the floating-point condition codes: */
                   1473:     _tme_m6888x_fpcc(ic, dst, dst_formats);
                   1474:   }
                   1475:       
                   1476:   /* if this is a data register direct EA: */
                   1477:   if (ea_mode == 0) {
                   1478: 
                   1479:     switch (ea_size) {
                   1480:     case TME_M68K_SIZE_8:
                   1481:       ic->tme_m68k_ireg_uint8(ea_reg << 2) = ic->tme_m68k_ireg_memx32;
                   1482:       break;
                   1483: 
                   1484:     case TME_M68K_SIZE_16:
                   1485:       ic->tme_m68k_ireg_uint8(ea_reg << 1) = ic->tme_m68k_ireg_memx32;
                   1486:       break;
                   1487: 
                   1488:     default:
                   1489:       assert (FALSE);
                   1490:       /* FALLTHROUGH */
                   1491: 
                   1492:     case TME_M68K_SIZE_32:
                   1493:       ic->tme_m68k_ireg_uint32(ea_reg) = ic->tme_m68k_ireg_memx32;
                   1494:       break;
                   1495:     }
                   1496:   }
                   1497: 
                   1498:   /* otherwise, this is a memory EA: */
                   1499:   else {
                   1500: 
                   1501:     /* this instruction can fault: */
                   1502:     TME_M68K_INSN_CANFAULT;
                   1503: 
                   1504:     /* adjust ea_reg to reference the address register: */
                   1505:     ea_reg += TME_M68K_IREG_A0;
                   1506: 
                   1507:     /* address register indirect postincrement: */
                   1508:     if (ea_mode == 3) {
                   1509:       /* if we are not restarting, set the effective address: */
                   1510:       if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1511:        ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
                   1512:        ic->tme_m68k_ireg_uint32(ea_reg) += TME_M68K_AREG_INCREMENT(ea_reg, ea_size);
                   1513:       }
                   1514:     }
                   1515: 
                   1516:     /* address register indirect predecrement: */
                   1517:     else if (ea_mode == 4) {
                   1518:       /* if we are not restarting, set the effective address: */
                   1519:       if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1520:        ic->tme_m68k_ireg_uint32(ea_reg) -= TME_M68K_AREG_INCREMENT(ea_reg, ea_size);
                   1521:        ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
                   1522:       }
                   1523:     }
                   1524: 
                   1525:     /* dispatch on the operand size to write in the destination as one
                   1526:        or more 32-bit words.  we will write up to three 32-bit words
1.1.1.2 ! root     1527:        from memx, memy, and memz: */
1.1       root     1528:     switch (ea_size) {
                   1529: 
                   1530:       /* this can only happen when the source operand is a byte: */
                   1531:     case TME_M68K_SIZE_8:
                   1532:       tme_m68k_write_memx8(ic);
                   1533:       assert (!TME_M68K_SEQUENCE_RESTARTING);
                   1534:       break;
                   1535: 
                   1536:       /* this can only happen when the source operand is a word: */
                   1537:     case TME_M68K_SIZE_16:
                   1538:       tme_m68k_write_memx16(ic);
                   1539:       assert (!TME_M68K_SEQUENCE_RESTARTING);
                   1540:       break;
                   1541: 
                   1542:       /* everything else is one or more 32-bit words: */
                   1543:     default:
                   1544: 
                   1545:       /* write the first 32 bits from the memx register: */
                   1546:       tme_m68k_write_memx32(ic);
                   1547:       if (ea_size == TME_M68K_SIZE_32) {
                   1548:        break;
                   1549:       }
                   1550: 
                   1551:       /* write the second 32 bits from the memy register: */
                   1552:       if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1553:        ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
                   1554:       }
                   1555:       tme_m68k_write_mem32(ic, TME_M68K_IREG_MEMY32);
                   1556:       if (ea_size == TME_M68K_SIZE_64) {
                   1557:        break;
                   1558:       }
                   1559:          
                   1560:       /* write the third 32 bits from the memz register: */
                   1561:       if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1562:        ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
                   1563:       }
                   1564:       tme_m68k_write_mem32(ic, TME_M68K_IREG_MEMZ32);
                   1565:       break;
                   1566:     }
                   1567:   }
                   1568: 
                   1569:   TME_M68K_INSN_OK;
                   1570: 
                   1571: #undef TME_M68K_AREG_INCREMENT
                   1572: }
                   1573: 
                   1574: /* this can fault: */
                   1575: TME_M68K_INSN(tme_m68k_fmovem)
                   1576: {  
                   1577:   unsigned int ea_mode;
                   1578:   unsigned int ea_reg;
                   1579:   unsigned int register_to_memory;
                   1580:   tme_uint16_t mask;
                   1581:   unsigned int bit;
                   1582:   unsigned int first_register;
                   1583:   struct tme_float *fpreg;
                   1584:   const struct tme_float_ieee754_extended80 *extended80;
                   1585:   struct tme_float_ieee754_extended80 extended80_buffer;
                   1586: 
                   1587:   TME_M68K_INSN_FPU;
                   1588: 
                   1589:   /* get the EA mode and register fields: */
                   1590:   ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);
                   1591:   ea_reg = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
                   1592: 
                   1593:   /* get the register-to-memory flag: */
                   1594:   register_to_memory = (TME_M68K_INSN_SPECOP & TME_BIT(13)) != 0;
                   1595: 
                   1596:   /* immediate EAs must have already been caught as illegal instructions: */
                   1597:   assert (!(ea_mode == 7 && ea_reg == 4));
                   1598: 
                   1599:   /* if this is a data register direct EA or an address register
                   1600:      direct EA, or if this is a predecrement EA and this is a
                   1601:      memory-to-register operation, or if this is a postincrement EA
                   1602:      and this is a register-to-memory operation, this is an illegal
                   1603:      instruction: */
                   1604:   if (ea_mode == 0
                   1605:       || ea_mode == 1
                   1606:       || (ea_mode == 4
                   1607:          && !register_to_memory)
                   1608:       || (ea_mode == 3
                   1609:          && register_to_memory)) {
                   1610:     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
                   1611:   }
                   1612: 
                   1613:   /* get the register list: */
                   1614:   mask = TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 8);
                   1615: 
                   1616:   /* if the register list is dynamic: */
                   1617:   if (TME_M68K_INSN_SPECOP & TME_BIT(11)) {
                   1618: 
                   1619:     /* the mask field is supposed to contain only a data register
                   1620:        number: */
                   1621:     if (mask & 0x8f) {
                   1622:       TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
                   1623:     }
                   1624: 
                   1625:     /* get the dynamic register list: */
                   1626:     mask = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(mask, 4, 3));
                   1627:   }
                   1628: 
                   1629:   /* get the FP register corresponding to bit 7 in the mask: */
                   1630:   if (TME_M68K_INSN_SPECOP & TME_BIT(12)) {
                   1631:     first_register = 0;
                   1632:   }
                   1633:   else {
                   1634: 
                   1635:     /* this must be a predecrement EA: */
                   1636:     if (ea_mode != 4) {
                   1637:       TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
                   1638:     }
                   1639: 
                   1640:     first_register = 7;
                   1641:   }
                   1642: 
                   1643:   /* if the mask is empty, return now: */
                   1644:   if (mask == 0) {
                   1645:     TME_M68K_INSN_OK;
                   1646:   }
                   1647: 
                   1648:   /* this instruction can fault: */
                   1649:   TME_M68K_INSN_CANFAULT;
                   1650: 
                   1651:   /* we require that TME_M68K_SIZE_96 be 12: */
                   1652: #if TME_M68K_SIZE_96 != 12
                   1653: #error "TME_M68K_SIZE_96 must be 12"
                   1654: #endif
                   1655: 
                   1656:   /* loop over the bits in the mask: */
                   1657:   for (bit = 0; bit < 8; bit++, mask <<= 1) {
                   1658: 
                   1659:     /* skip this register if its bit isn't set in the mask: */
                   1660:     if (!(mask & 0x80)) {
                   1661:       continue;
                   1662:     }
                   1663: 
                   1664:     /* get this register: */
                   1665:     fpreg = &ic->tme_m68k_fpu_fpreg[bit ^ first_register];
                   1666: 
                   1667:     /* if this is a register-to-memory operation: */
                   1668:     if (register_to_memory) {
                   1669: 
                   1670:       /* if this is a predecrement EA, and we're not restarting,
                   1671:          predecrement the EA: */
                   1672:       if (!TME_M68K_SEQUENCE_RESTARTING
                   1673:          && ea_mode == 4) {
                   1674:        ic->_tme_m68k_ea_address = (ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ea_reg) -= TME_M68K_SIZE_96);
                   1675:       }
                   1676: 
                   1677:       /* write out the register: */
                   1678:       extended80 = tme_ieee754_extended80_value_get(fpreg, &extended80_buffer);
                   1679:       if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1680:        ic->tme_m68k_ireg_memx32 = extended80->tme_float_ieee754_extended80_sexp << 16;
                   1681:       }
                   1682:       tme_m68k_write_memx32(ic);
                   1683:       if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1684:        ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
                   1685:        ic->tme_m68k_ireg_memx32 = extended80->tme_float_ieee754_extended80_significand.tme_value64_uint32_hi;
                   1686:       }
                   1687:       tme_m68k_write_memx32(ic);
                   1688:       if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1689:        ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
                   1690:        ic->tme_m68k_ireg_memx32 = extended80->tme_float_ieee754_extended80_significand.tme_value64_uint32_lo;
                   1691:       }
                   1692:       tme_m68k_write_memx32(ic);
1.1.1.2 ! root     1693:       if (!TME_M68K_SEQUENCE_RESTARTING) {
        !          1694:        ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
        !          1695:       }
1.1       root     1696:     }
                   1697: 
                   1698:     /* otherwise, this is a memory-to-register operation: */
                   1699:     else {
                   1700: 
                   1701:       /* read in this register: */
                   1702:       tme_m68k_read_memx32(ic);
                   1703:       if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1704:        fpreg->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_sexp = (ic->tme_m68k_ireg_memx32 >> 16);
                   1705:        ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
                   1706:       }
                   1707:       tme_m68k_read_memx32(ic);
                   1708:       if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1709:        fpreg->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi = ic->tme_m68k_ireg_memx32;
                   1710:        ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
                   1711:       }
                   1712:       tme_m68k_read_memx32(ic);
                   1713:       if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1714:        fpreg->tme_float_value_ieee754_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = ic->tme_m68k_ireg_memx32;
                   1715:        ic->_tme_m68k_ea_address += TME_M68K_SIZE_32;
                   1716:        fpreg->tme_float_format = TME_FLOAT_FORMAT_IEEE754_EXTENDED80;
                   1717:       }
                   1718:     }
                   1719:   }
                   1720: 
                   1721:   /* if this is the postincrement addressing mode: */
                   1722:   if (ea_mode == 3) {
                   1723: 
                   1724:     /* update the address register: */
                   1725:     assert (!TME_M68K_SEQUENCE_RESTARTING);
                   1726:     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ea_reg) = ic->_tme_m68k_ea_address;
                   1727:   }
                   1728: 
                   1729:   TME_M68K_INSN_OK;
                   1730: }
                   1731: 
                   1732: /* this can fault: */
                   1733: TME_M68K_INSN(tme_m68k_fmovemctl)
                   1734: {
                   1735:   tme_uint16_t mask;
                   1736:   unsigned int ea_mode;
                   1737:   unsigned int ea_reg;
                   1738:   unsigned int register_to_memory;
                   1739:   unsigned int bit;
                   1740:   tme_uint32_t *value;
                   1741: 
                   1742:   TME_M68K_INSN_FPU;
                   1743: 
                   1744:   /* get the register mask: */
                   1745:   mask = TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 10, 3);
                   1746: 
                   1747:   /* get the EA mode and register fields: */
                   1748:   ea_mode = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3);
                   1749:   ea_reg = TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3);
                   1750: 
                   1751:   /* get the register-to-memory flag: */
                   1752:   register_to_memory = (TME_M68K_INSN_SPECOP & TME_BIT(13)) != 0;
                   1753: 
                   1754:   /* if no registers have been selected, or if this is a data register
                   1755:      direct EA and multiple registers have been selected, or if this
                   1756:      is an address register direct EA and the floating point
                   1757:      instruction address register is not the single register selected,
                   1758:      this is an illegal instruction: */
                   1759:   if (mask == 0
                   1760:       || (ea_mode == 0
                   1761:          && ((mask & (mask - 1)) != 0))
                   1762:       || (ea_mode == 1
                   1763:          && mask != 1)) {
                   1764:     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
                   1765:   }
                   1766: 
                   1767:   /* if this isn't a data register direct EA or an address register
                   1768:      direct EA, this instruction can fault: */
                   1769:   if (ea_mode != 0
                   1770:       && ea_mode != 1) {
                   1771:     TME_M68K_INSN_CANFAULT;
                   1772:   }
                   1773: 
                   1774:   /* if we're not restarting, and this is the predecrement addressing mode: */
                   1775:   if (!TME_M68K_SEQUENCE_RESTARTING
                   1776:       && ea_mode == 4) {
                   1777: 
                   1778:     /* update the effective address: */
                   1779:     for (; mask != 0; ic->_tme_m68k_ea_address -= sizeof(tme_uint32_t), mask &= (mask - 1));
                   1780: 
                   1781:     /* update the address register: */
                   1782:     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ea_reg) = ic->_tme_m68k_ea_address;
                   1783:   }
                   1784: 
                   1785:   /* get the register mask: */
                   1786:   mask = TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 10, 3);
                   1787: 
                   1788:   /* loop over the register mask bits: */
                   1789:   for (bit = 3; bit-- > 0; ) {
                   1790: 
                   1791:     /* ignore this register if its bit isn't set: */
                   1792:     if (!(mask & (1 << bit))) {
                   1793:       continue;
                   1794:     }
                   1795: 
                   1796:     /* get a pointer to this register's value: */
                   1797:     value = (bit == 2
                   1798:             ? &ic->tme_m68k_fpu_fpcr
                   1799:             : bit == 1
                   1800:             ? &ic->tme_m68k_fpu_fpsr
                   1801:             : &ic->tme_m68k_fpu_fpiar);
                   1802: 
                   1803:     /* transfer this register's value: */
                   1804: 
                   1805:     /* if this is a data register direct EA: */
                   1806:     if (ea_mode == 0) {
                   1807:       if (register_to_memory) {
                   1808:        ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + ea_reg) = *value;
                   1809:       }
                   1810:       else {
                   1811:        *value = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_D0 + ea_reg);
                   1812:       }
                   1813:     }
                   1814: 
                   1815:     /* if this is an address register direct EA: */
                   1816:     else if (ea_mode == 1) {
                   1817:       if (register_to_memory) {
                   1818:        ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ea_reg) = *value;
                   1819:       }
                   1820:       else {
                   1821:        *value = ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ea_reg);
                   1822:       }
                   1823:     }
                   1824: 
                   1825:     /* otherwise, this is a memory EA: */
                   1826:     else {
                   1827:       if (register_to_memory) {
                   1828:        if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1829:          ic->tme_m68k_ireg_memx32 = *value;
                   1830:        }
                   1831:        tme_m68k_write_memx32(ic);
                   1832:        if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1833:          ic->_tme_m68k_ea_address += sizeof(tme_uint32_t);
                   1834:        }       
                   1835:       }
                   1836:       else {
                   1837:        tme_m68k_read_memx32(ic);
                   1838:        if (!TME_M68K_SEQUENCE_RESTARTING) {
                   1839:          *value = ic->tme_m68k_ireg_memx32;
                   1840:          ic->_tme_m68k_ea_address += sizeof(tme_uint32_t);
                   1841:        }
                   1842:       }
                   1843:     }
                   1844:   }
                   1845: 
                   1846:   /* if this is the postincrement addressing mode: */
                   1847:   if (ea_mode == 3) {
                   1848: 
                   1849:     /* update the address register: */
                   1850:     assert (!TME_M68K_SEQUENCE_RESTARTING);
                   1851:     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0 + ea_reg) = ic->_tme_m68k_ea_address;
                   1852:   }
                   1853: 
                   1854:   TME_M68K_INSN_OK;
                   1855: }
                   1856: 
                   1857: /* this evaluates a floating-point predicate: */
                   1858: static int
                   1859: _tme_m6888x_predicate_true(struct tme_m68k *ic, tme_uint16_t predicate)
                   1860: {
                   1861:   unsigned int cc_nan;
                   1862:   unsigned int cc_i;
                   1863:   unsigned int cc_z;
                   1864:   unsigned int cc_n;
                   1865: 
                   1866:   /* get the condition codes: */
                   1867:   cc_nan = (ic->tme_m68k_fpu_fpsr & TME_M6888X_FPSR_CC_NAN) != 0;
                   1868:   cc_i = (ic->tme_m68k_fpu_fpsr & TME_M6888X_FPSR_CC_I) != 0;
                   1869:   cc_z = (ic->tme_m68k_fpu_fpsr & TME_M6888X_FPSR_CC_Z) != 0;
                   1870:   cc_n = (ic->tme_m68k_fpu_fpsr & TME_M6888X_FPSR_CC_N) != 0;
                   1871: 
                   1872:   /* if this predicate is greater than 0x1f, this is an illegal instruction: */
                   1873:   if (predicate > 0x1f) {
                   1874:     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_ILL);
                   1875:   }
                   1876: 
                   1877:   /* if this predicate sets BSUN when NaN is set: */
                   1878:   if (predicate > 0x0f) {
                   1879: 
                   1880:     /* if NaN is set, set BSUN: */
                   1881:     if (cc_nan) {
                   1882:       _tme_m6888x_exception(ic, TME_M6888X_FPSR_EXC_BSUN);
                   1883:     }
                   1884: 
                   1885:     /* adjust predicate to be its non-BSUN-setting version: */
                   1886:     predicate -= 0x10;
                   1887:   }
                   1888: 
                   1889:   /* dispatch on the predicate: */
                   1890:   switch (predicate) {
                   1891:   default: assert(FALSE);
                   1892:   case 0x00: predicate = FALSE; break;                         /* F, SF */
                   1893:   case 0x01: predicate =  cc_z; break;                         /* EQ, SEQ */
                   1894:   case 0x02: predicate = !(cc_nan || cc_z || cc_n); break;     /* OGT, GT */
                   1895:   case 0x03: predicate = cc_z || !(cc_nan || cc_n); break;     /* OGE, GE */
                   1896:   case 0x04: predicate = cc_n && !(cc_nan || cc_z); break;     /* OLT, LT */
                   1897:   case 0x05: predicate = cc_z || (cc_n && !cc_nan); break;     /* OLE, LE */
                   1898:   case 0x06: predicate = !(cc_nan || cc_z); break;             /* OGL, GL */
                   1899:   case 0x07: predicate = !cc_nan; break;                       /* OR, GLE */
                   1900:   case 0x08: predicate =  cc_nan; break;                       /* UN, NGLE */
                   1901:   case 0x09: predicate =  (cc_nan || cc_z); break;             /* UEQ, NGL */
                   1902:   case 0x0a: predicate = cc_nan || !(cc_n || cc_z); break;     /* UGT, NLE */
                   1903:   case 0x0b: predicate = cc_nan || cc_z || !cc_n; break;       /* UGE, NLT */
                   1904:   case 0x0c: predicate = cc_nan || (cc_n && !cc_z); break;     /* ULT, NGE */
                   1905:   case 0x0d: predicate =  (cc_nan || cc_z || cc_n); break;     /* ULE, NGT */
                   1906:   case 0x0e: predicate = !cc_z; break;                         /* NE, SNE */
                   1907:   case 0x0f: predicate = FALSE; break;                         /* T, ST */
                   1908:   }
                   1909: 
                   1910:   return (predicate);
                   1911: }
                   1912: 
                   1913: /* this cannot fault: */
                   1914: TME_M68K_INSN(tme_m68k_fdbcc)
                   1915: {
                   1916:   TME_M68K_INSN_FPU;
                   1917: 
                   1918:   if (_tme_m6888x_predicate_true(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 6))) {
                   1919:     if (--TME_M68K_INSN_OP0(tme_int16_t) != -1) {
                   1920:       TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_pc
                   1921:                           + 4
                   1922:                           + TME_EXT_S16_U32(TME_M68K_INSN_OP1(tme_int16_t)));
                   1923:     }
                   1924:   }
                   1925:   TME_M68K_INSN_OK;
                   1926: }
                   1927: 
                   1928: /* this cannot fault: */
                   1929: TME_M68K_INSN(tme_m68k_ftrapcc)
                   1930: {
                   1931:   TME_M68K_INSN_FPU;
                   1932:   if (_tme_m6888x_predicate_true(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 6))) {
                   1933:     ic->tme_m68k_ireg_pc_last = ic->tme_m68k_ireg_pc;
                   1934:     ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
                   1935:     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_TRAP));
                   1936:   }
                   1937:   TME_M68K_INSN_OK;
                   1938: }
                   1939: 
                   1940: /* this cannot fault: */
                   1941: TME_M68K_INSN(tme_m68k_fscc)
                   1942: {
                   1943:   TME_M68K_INSN_FPU;
                   1944:   TME_M68K_INSN_OP1(tme_uint8_t) =
                   1945:     (_tme_m6888x_predicate_true(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_SPECOP, 0, 6))
                   1946:      ? 0xff
                   1947:      : 0x00);
                   1948:   TME_M68K_INSN_OK;
                   1949: }
                   1950: 
                   1951: /* this cannot fault: */
                   1952: TME_M68K_INSN(tme_m68k_fbcc)
                   1953: {
                   1954:   TME_M68K_INSN_FPU;
                   1955: 
                   1956:   if (_tme_m6888x_predicate_true(ic, TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 6))) {
                   1957:     TME_M68K_INSN_BRANCH(ic->tme_m68k_ireg_pc
                   1958:                         + sizeof(tme_uint16_t)
                   1959:                         + TME_M68K_INSN_OP0(tme_uint32_t));
                   1960:   }
                   1961:   TME_M68K_INSN_OK;
                   1962: }
                   1963: 
                   1964: /* this can fault: */
                   1965: TME_M68K_INSN(tme_m68k_fsave)
                   1966: {
                   1967:   struct tme_m6888x_frame frame;
                   1968:   tme_uint32_t frame_size;
                   1969: 
                   1970:   TME_M68K_INSN_FPU;
                   1971:   TME_M68K_INSN_PRIV;
                   1972:   TME_M68K_INSN_CANFAULT;
                   1973: 
                   1974:   /* zero the frame: */
                   1975:   memset(&frame, 0, sizeof(frame));
                   1976: 
                   1977:   /* dispatch on the FPU type: */
                   1978:   switch (ic->tme_m68k_fpu_type) {
                   1979:   default: assert (FALSE);
                   1980:   case TME_M68K_FPU_M68881:
                   1981:     frame.tme_m6888x_frame_version = TME_M6888X_FRAME_VERSION_IDLE_M68881;
                   1982:     frame.tme_m6888x_frame_size = TME_M6888X_FRAME_SIZE_IDLE_M68881;
                   1983:     break;
                   1984:   case TME_M68K_FPU_M68882:
                   1985:     frame.tme_m6888x_frame_version = TME_M6888X_FRAME_VERSION_IDLE_M68882;
                   1986:     frame.tme_m6888x_frame_size = TME_M6888X_FRAME_SIZE_IDLE_M68882;
                   1987:     break;
                   1988:   case TME_M68K_FPU_M68040:
                   1989:     frame.tme_m6888x_frame_version = TME_M6888X_FRAME_VERSION_IDLE_M68040;
                   1990:     frame.tme_m6888x_frame_size = TME_M6888X_FRAME_SIZE_IDLE_M68040;
                   1991:     break;
                   1992:   }
                   1993: 
                   1994:   /* if this is the m68881 or m68882: */
                   1995:   if (ic->tme_m68k_fpu_type & TME_M68K_FPU_M6888X) {
                   1996: 
                   1997:     /* fill in a minimal BIU flags field: */
1.1.1.2 ! root     1998:     frame.tme_m6888x_frame_words[(frame.tme_m6888x_frame_size / sizeof(tme_uint32_t)) - 2] = tme_htobe_u32(0x70000000);
1.1       root     1999:   }
                   2000: 
                   2001:   /* get the total size of the frame: */
                   2002:   frame_size
                   2003:     = (sizeof(frame.tme_m6888x_frame_version)
                   2004:        + sizeof(frame.tme_m6888x_frame_size)
                   2005:        + sizeof(frame.tme_m6888x_frame_reserved2)
                   2006:        + frame.tme_m6888x_frame_size);
                   2007: 
                   2008:   /* if we're not restarting, and this is the predecrement addressing
                   2009:      mode, update the effective address and the address register: */
                   2010:   if (!TME_M68K_SEQUENCE_RESTARTING
                   2011:       && TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3) == 4) {
                   2012:     ic->_tme_m68k_ea_address -= frame_size;
                   2013:     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0
                   2014:                             + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))
                   2015:       = ic->_tme_m68k_ea_address;
                   2016:   }
                   2017: 
                   2018:   /* write out the saved frame: */
                   2019:   tme_m68k_write_mem(ic, (tme_uint8_t *) &frame, frame_size);
                   2020: }
                   2021: 
                   2022: /* this can fault: */
                   2023: TME_M68K_INSN(tme_m68k_frestore)
                   2024: {
                   2025:   tme_uint8_t frame_version;
                   2026:   tme_uint8_t frame_size;
                   2027:   int format_error;
                   2028: 
                   2029:   TME_M68K_INSN_FPU;
                   2030:   TME_M68K_INSN_PRIV;
                   2031:   TME_M68K_INSN_CANFAULT;
                   2032: 
                   2033:   /* read in the format word: */
                   2034:   tme_m68k_read_memx32(ic);
                   2035:   frame_version = (ic->tme_m68k_ireg_memx32 >> 24) & 0xff;
                   2036:   frame_size = (ic->tme_m68k_ireg_memx32 >> 16) & 0xff;
                   2037:   
                   2038:   /* determine if we have a format error: */
                   2039:   if (frame_version == TME_M6888X_FRAME_VERSION_NULL) {
                   2040:     format_error = (frame_size != TME_M6888X_FRAME_SIZE_NULL);
                   2041:   }
                   2042:   else {
                   2043:     switch (ic->tme_m68k_fpu_type) {
                   2044:     default: assert (FALSE);
                   2045:     case TME_M68K_FPU_M68881:
                   2046:       format_error = (frame_version != TME_M6888X_FRAME_VERSION_IDLE_M68881
                   2047:                      || frame_size != TME_M6888X_FRAME_SIZE_IDLE_M68881);
                   2048:       break;
                   2049:     case TME_M68K_FPU_M68882:
                   2050:       format_error = (frame_version != TME_M6888X_FRAME_VERSION_IDLE_M68882
                   2051:                      || frame_size != TME_M6888X_FRAME_SIZE_IDLE_M68882);
                   2052:       break;
                   2053:     case TME_M68K_FPU_M68040:
                   2054:       format_error = (frame_version != TME_M6888X_FRAME_VERSION_IDLE_M68040
                   2055:                      || frame_size != TME_M6888X_FRAME_SIZE_IDLE_M68040);
                   2056:       break;
                   2057:     }
                   2058:   }
                   2059:   
                   2060:   /* if we have a format error: */
                   2061:   if (format_error) {
                   2062:     TME_M68K_INSN_EXCEPTION(TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_FORMAT));
                   2063:   }
                   2064: 
                   2065:   /* XXX FIXME - we don't bother reading in the rest of the frame.
                   2066:      this gives an incomplete emulation: */
                   2067: 
                   2068:   /* if this is the postincrement addressing mode, update the address
                   2069:      register: */
                   2070:   if (TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 3, 3) == 3) {
                   2071:     ic->tme_m68k_ireg_uint32(TME_M68K_IREG_A0
                   2072:                             + TME_FIELD_EXTRACTU(TME_M68K_INSN_OPCODE, 0, 3))
                   2073:       += (sizeof(ic->tme_m68k_ireg_memx32)
                   2074:          + frame_size);
                   2075:   }
                   2076: 
                   2077:   /* if this was a NULL frame, reset the FPU: */
                   2078:   if (frame_version == TME_M6888X_FRAME_VERSION_NULL) {
                   2079:     tme_m68k_fpu_reset(ic);
                   2080:   }
                   2081: }
                   2082: 
                   2083: /* this checks for an FPU argument: */
                   2084: int
                   2085: tme_m68k_fpu_new(struct tme_m68k *ic, const char * const *args, int *_arg_i, int *_usage, char **_output)
                   2086: {
                   2087:   int arg_i;
                   2088:   int fpu_type;
                   2089:   const char *compliance;
                   2090:   int complete;
                   2091:   unsigned int opmode_i;
                   2092:   struct tme_ieee754_ctl *ctl;
                   2093: 
                   2094:   /* get the argument index: */
                   2095:   arg_i = *_arg_i;
                   2096:   
                   2097:   /* if this is not an FPU type, this is not an m6888x argument: */
                   2098:   if (!TME_ARG_IS(args[arg_i + 0], "fpu-type")) {
                   2099:     return (FALSE);
                   2100:   }
                   2101: 
                   2102:   /* you can't specify more than one FPU type: */
                   2103:   if (ic->tme_m68k_fpu_type != TME_M68K_FPU_NONE) {
                   2104:     tme_output_append_error(_output, 
                   2105:                            "%s fpu-type %s",
                   2106:                            _("multiple"),
                   2107:                            _("unexpected"));
                   2108:     *_usage = TRUE;
                   2109:     return (TRUE);
                   2110:   }
                   2111: 
                   2112:   /* get the FPU type: */
                   2113:   if (args[arg_i + 1] == NULL) {
                   2114:     *_usage = TRUE;
                   2115:     return (TRUE);
                   2116:   }
                   2117:   if (TME_ARG_IS(args[arg_i + 1], "m68881")) {
                   2118:     fpu_type = TME_M68K_FPU_M68881;
                   2119:   }
                   2120:   else if (TME_ARG_IS(args[arg_i + 1], "m68882")) {
                   2121:     fpu_type = TME_M68K_FPU_M68882;
                   2122:   }
                   2123:   else if (TME_ARG_IS(args[arg_i + 1], "m68040")) {
                   2124:     fpu_type = TME_M68K_FPU_M68040;
                   2125:   }
                   2126:   else {
                   2127:     tme_output_append_error(_output, 
                   2128:                            "%s fpu-type %s",
                   2129:                            _("bad"),
                   2130:                            args[arg_i + 1]);
                   2131:     *_usage = TRUE;
                   2132:     return (TRUE);
                   2133:   }
                   2134:   ic->tme_m68k_fpu_type = fpu_type;
                   2135:   arg_i += 2;
                   2136: 
                   2137:   /* the next argument must be a compliance level: */
                   2138:   compliance = args[arg_i + 1];
                   2139:   if (!TME_ARG_IS(args[arg_i + 0], "fpu-compliance")
                   2140:       || compliance == NULL) {
                   2141:     *_usage = TRUE;
                   2142:     return (TRUE);
                   2143:   }
                   2144:   ic->tme_m68k_fpu_ieee754_ops = tme_ieee754_ops_lookup(compliance);
                   2145:   if (ic->tme_m68k_fpu_ieee754_ops == NULL) {
                   2146:     tme_output_append_error(_output, 
                   2147:                            "%s fpu-compliance %s",
                   2148:                            _("bad"),
                   2149:                            compliance);
                   2150:     *_usage = TRUE;
                   2151:     return (TRUE);
                   2152:   }
                   2153:   arg_i += 2;
                   2154: 
                   2155:   /* see if the operations for this compliance level are complete: */
                   2156:   complete = TRUE;
                   2157:   for (opmode_i = 0;
                   2158:        opmode_i < (sizeof(_tme_m6888x_fpgen_opmode_table) / sizeof(_tme_m6888x_fpgen_opmode_table[0]));
                   2159:        opmode_i++) {
                   2160:     if (_tme_m6888x_fpgen_opmode_table[opmode_i].tme_m6888x_fpgen_func_ops_offset != 0
                   2161:        && TME_M6888X_IEEE754_OP_FUNC(_tme_m6888x_fpgen_opmode_table[opmode_i].tme_m6888x_fpgen_func_ops_offset) == NULL) {
                   2162:       complete = FALSE;
                   2163:       break;
                   2164:     }
                   2165:   }
                   2166: 
                   2167:   /* if the next argument is an incomplete disposition: */
                   2168:   if (TME_ARG_IS(args[arg_i + 0], "fpu-incomplete")) {
                   2169:     
                   2170:     if (TME_ARG_IS(args[arg_i + 1], "abort")) {
                   2171:       ic->tme_m68k_fpu_incomplete_abort = TRUE;
                   2172:     }
                   2173:     else if (TME_ARG_IS(args[arg_i + 1], "line-f")) {
                   2174:       ic->tme_m68k_fpu_incomplete_abort = FALSE;
                   2175:     }
                   2176:     else {
                   2177:       tme_output_append_error(_output, 
                   2178:                              "%s fpu-incomplete %s",
                   2179:                              _("bad"),
                   2180:                              args[arg_i + 1]);
                   2181:       *_usage = TRUE;
                   2182:       return (TRUE);
                   2183:     }
                   2184:     arg_i += 2;
                   2185:   }
                   2186: 
                   2187:   /* otherwise, no incomplete disposition is given.  if this
                   2188:      compliance is incomplete: */
                   2189:   else if (!complete) {
                   2190:     tme_output_append_error(_output, 
                   2191:                            "%s %s %s fpu-incomplete",
                   2192:                            _("compliance"),
                   2193:                            compliance,
                   2194:                            _("is incomplete, needs"));
                   2195:     *_usage = TRUE;
                   2196:     return (TRUE);
                   2197:   }
                   2198: 
                   2199:   /* initialize the IEEE 754 control: */
                   2200:   ctl = &ic->tme_m68k_fpu_ieee754_ctl;
                   2201: 
                   2202:   /* a private data structure: */
                   2203:   ctl->tme_ieee754_ctl_private = ic;
                   2204: 
                   2205:   /* the underflow tininess-detection mode: */
                   2206:   /* XXX FIXME - is this right for the m6888x? */
                   2207:   ctl->tme_ieee754_ctl_detect_tininess = TME_IEEE754_CTL_DETECT_TININESS_BEFORE_ROUNDING;
                   2208: 
                   2209:   /* the exception function: */
                   2210:   ctl->tme_ieee754_ctl_exception = _tme_m6888x_exception_ieee754;
                   2211: 
                   2212:   /* we don't check whether or not a value is a NaN when converting it
                   2213:      from one precision to another: */
                   2214:   ctl->tme_ieee754_ctl_check_snan_on_conversion = FALSE;
                   2215: 
                   2216:   /* the default generated NaN patterns: */
                   2217:   ctl->tme_ieee754_ctl_default_nan_single = 0x7fffffff;
                   2218:   ctl->tme_ieee754_ctl_default_nan_double.tme_value64_uint32_hi = 0x7fffffff;
                   2219:   ctl->tme_ieee754_ctl_default_nan_double.tme_value64_uint32_lo = 0xffffffff;
                   2220:   ctl->tme_ieee754_ctl_default_nan_extended80.tme_float_ieee754_extended80_sexp = 0x7fff;
                   2221:   ctl->tme_ieee754_ctl_default_nan_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_hi = 0xffffffff;
                   2222:   ctl->tme_ieee754_ctl_default_nan_extended80.tme_float_ieee754_extended80_significand.tme_value64_uint32_lo = 0xffffffff;
                   2223: 
                   2224:   /* NaN tests: */
                   2225:   ctl->tme_ieee754_ctl_is_snan_extended80 = _tme_m6888x_is_snan_extended80;
                   2226: 
                   2227:   /* NaN canonicalization: */
                   2228:   ctl->tme_ieee754_ctl_nan_single_to_common = tme_ieee754_default_nan_single_to_common;
                   2229:   ctl->tme_ieee754_ctl_nan_common_to_single = tme_ieee754_default_nan_common_to_single;
                   2230:   ctl->tme_ieee754_ctl_nan_double_to_common = tme_ieee754_default_nan_double_to_common;
                   2231:   ctl->tme_ieee754_ctl_nan_common_to_double = tme_ieee754_default_nan_common_to_double;
                   2232:   ctl->tme_ieee754_ctl_nan_extended80_to_common = tme_ieee754_default_nan_extended80_to_common;
                   2233:   ctl->tme_ieee754_ctl_nan_common_to_extended80 = tme_ieee754_default_nan_common_to_extended80;
                   2234: 
                   2235:   /* NaN propagation: */
                   2236:   ctl->tme_ieee754_ctl_nan_from_nans_extended80 = _tme_m6888x_nan_from_nans_extended80;
                   2237: 
                   2238:   /* done: */
                   2239:   *_arg_i = arg_i;
                   2240:   return (TRUE);
                   2241: }
                   2242: 
                   2243: /* this returns the FPU usage: */
                   2244: void
                   2245: tme_m68k_fpu_usage(char **_output)
                   2246: {
                   2247:   tme_output_append_error(_output, 
                   2248:                          "[ fpu-type { m68881 | m68882 | m68040 } fpu-compliance %s [ fpu-incomplete { abort | line-f } ] ]",
                   2249:                          tme_ieee754_compliance_options);
                   2250: }

unix.superglobalmegacorp.com

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