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

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

unix.superglobalmegacorp.com

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