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