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