Annotation of uae/src/fpp.c, revision 1.1.1.12

1.1       root        1:  /*
                      2:   * UAE - The Un*x Amiga Emulator
                      3:   *
                      4:   * MC68881 emulation
                      5:   *
                      6:   * Copyright 1996 Herman ten Brugge
                      7:   */
                      8: 
1.1.1.8   root        9: #define __USE_ISOC9X  /* We might be able to pick up a NaN */
1.1       root       10: #include <math.h>
                     11: 
                     12: #include "sysconfig.h"
                     13: #include "sysdeps.h"
                     14: 
                     15: #include "options.h"
                     16: #include "memory.h"
                     17: #include "custom.h"
1.1.1.8   root       18: #include "events.h"
1.1       root       19: #include "newcpu.h"
                     20: #include "ersatz.h"
1.1.1.4   root       21: #include "md-fpp.h"
1.1.1.12! root       22: #include "savestate.h"
1.1       root       23: 
1.1.1.3   root       24: #if 1
1.1       root       25: 
                     26: #define        DEBUG_FPP       0
                     27: 
1.1.1.8   root       28: #define FFLAG_Z   0x4000
                     29: #define FFLAG_N   0x0100
1.1.1.10  root       30: #define FFLAG_NAN 0x0400
1.1.1.8   root       31: 
                     32: #define MAKE_FPSR(r)  regs.fp_result=(r)
                     33: 
                     34: static __inline__ void native_set_fpucw (uae_u32 m68k_cw)
                     35: {
                     36: }
                     37: 
1.1.1.12! root       38: static int get_fpu_version(void)
        !            39: {
        !            40:     int v = 0;
        !            41:     //    if (currprefs.fpu_revision >= 0)
        !            42:     // return currprefs.fpu_revision;
        !            43:     switch (currprefs.fpu_model)
        !            44:     {
        !            45:     case 68881:
        !            46:        v = 0x1f;
        !            47:        break;
        !            48:     case 68882:
        !            49:        v = 0x20; /* ??? */
        !            50:        break;
        !            51:     case 68040:
        !            52:        v = 0x41;
        !            53:        break;
        !            54:     }
        !            55:     return v;
        !            56: }
        !            57: 
1.1.1.8   root       58: #if defined(uae_s64) /* Close enough for government work? */
1.1.1.12! root       59: static __inline__ uae_s64 toint (fptype src)
1.1.1.8   root       60: #else
1.1.1.12! root       61: static __inline__ uae_s32 toint (fptype src)
1.1.1.8   root       62: #endif
                     63: {
                     64:     switch ((regs.fpcr >> 4) & 0x3) {
                     65:     case 0:
                     66:        return (int) (src + 0.5);
                     67:     case 1:
                     68:        return (int) src;
                     69:     case 2:
                     70:        return floor (src);
                     71:     case 3:
                     72:        return ceil (src);
                     73:     }
                     74:     return src; /* Should never be reached */
                     75: }
                     76: 
1.1.1.10  root       77: static uae_u32 get_fpsr (void)
1.1.1.8   root       78: {
                     79:     uae_u32 answer = regs.fpsr & 0x00ffffff;
1.1.1.9   root       80: #ifdef HAVE_ISNAN
1.1.1.8   root       81:     if (isnan (regs.fp_result))
                     82:        answer |= 0x01000000;
1.1.1.9   root       83:     else
                     84: #endif
                     85:     {
                     86:        if (regs.fp_result == 0)
                     87:            answer |= 0x04000000;
                     88:        else if (regs.fp_result < 0)
                     89:            answer |= 0x08000000;
                     90: #ifdef HAVE_ISINF
                     91:        if (isinf (regs.fp_result))
                     92:            answer |= 0x02000000;
                     93: #endif
                     94:     }
1.1.1.8   root       95:     return answer;
                     96: }
                     97: 
1.1.1.10  root       98: STATIC_INLINE void set_fpsr (uae_u32 x)
1.1.1.8   root       99: {
                    100:     regs.fpsr = x;
                    101: 
                    102:     if (x & 0x01000000) {
                    103: #ifdef NAN
                    104:        regs.fp_result = NAN;
                    105: #else
                    106:        regs.fp_result = pow (1e100, 10) - pow(1e100, 10);  /* Any better way? */
                    107: #endif
                    108:     }
                    109:     else if (x & 0x04000000)
                    110:        regs.fp_result = 0;
                    111:     else if (x & 0x08000000)
                    112:        regs.fp_result = -1;
                    113:     else
                    114:        regs.fp_result = 1;
                    115: }
                    116: 
1.1.1.5   root      117: 
1.1       root      118: /* single   : S  8*E 23*F */
                    119: /* double   : S 11*E 52*F */
                    120: /* extended : S 15*E 64*F */
                    121: /* E = 0 & F = 0 -> 0 */
                    122: /* E = MAX & F = 0 -> Infin */
                    123: /* E = MAX & F # 0 -> NotANumber */
                    124: /* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */
                    125: 
1.1.1.8   root      126: STATIC_INLINE fptype to_pack (uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
1.1       root      127: {
1.1.1.8   root      128:     fptype d;
1.1.1.3   root      129:     char *cp;
                    130:     char str[100];
                    131: 
                    132:     cp = str;
                    133:     if (wrd1 & 0x80000000)
                    134:        *cp++ = '-';
                    135:     *cp++ = (wrd1 & 0xf) + '0';
                    136:     *cp++ = '.';
                    137:     *cp++ = ((wrd2 >> 28) & 0xf) + '0';
                    138:     *cp++ = ((wrd2 >> 24) & 0xf) + '0';
                    139:     *cp++ = ((wrd2 >> 20) & 0xf) + '0';
                    140:     *cp++ = ((wrd2 >> 16) & 0xf) + '0';
                    141:     *cp++ = ((wrd2 >> 12) & 0xf) + '0';
                    142:     *cp++ = ((wrd2 >> 8) & 0xf) + '0';
                    143:     *cp++ = ((wrd2 >> 4) & 0xf) + '0';
                    144:     *cp++ = ((wrd2 >> 0) & 0xf) + '0';
                    145:     *cp++ = ((wrd3 >> 28) & 0xf) + '0';
                    146:     *cp++ = ((wrd3 >> 24) & 0xf) + '0';
                    147:     *cp++ = ((wrd3 >> 20) & 0xf) + '0';
                    148:     *cp++ = ((wrd3 >> 16) & 0xf) + '0';
                    149:     *cp++ = ((wrd3 >> 12) & 0xf) + '0';
                    150:     *cp++ = ((wrd3 >> 8) & 0xf) + '0';
                    151:     *cp++ = ((wrd3 >> 4) & 0xf) + '0';
                    152:     *cp++ = ((wrd3 >> 0) & 0xf) + '0';
                    153:     *cp++ = 'E';
                    154:     if (wrd1 & 0x40000000)
                    155:        *cp++ = '-';
                    156:     *cp++ = ((wrd1 >> 24) & 0xf) + '0';
                    157:     *cp++ = ((wrd1 >> 20) & 0xf) + '0';
                    158:     *cp++ = ((wrd1 >> 16) & 0xf) + '0';
                    159:     *cp = 0;
1.1.1.5   root      160:     sscanf (str, "%le", &d);
1.1.1.3   root      161:     return d;
1.1       root      162: }
                    163: 
1.1.1.8   root      164: STATIC_INLINE void from_pack (fptype src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
1.1       root      165: {
1.1.1.3   root      166:     int i;
                    167:     int t;
                    168:     char *cp;
                    169:     char str[100];
                    170: 
1.1.1.5   root      171:     sprintf (str, "%.16e", src);
1.1.1.3   root      172:     cp = str;
                    173:     *wrd1 = *wrd2 = *wrd3 = 0;
                    174:     if (*cp == '-') {
                    175:        cp++;
                    176:        *wrd1 = 0x80000000;
                    177:     }
                    178:     if (*cp == '+')
                    179:        cp++;
                    180:     *wrd1 |= (*cp++ - '0');
                    181:     if (*cp == '.')
                    182:        cp++;
                    183:     for (i = 0; i < 8; i++) {
                    184:        *wrd2 <<= 4;
                    185:        if (*cp >= '0' && *cp <= '9')
                    186:            *wrd2 |= *cp++ - '0';
                    187:     }
                    188:     for (i = 0; i < 8; i++) {
                    189:        *wrd3 <<= 4;
                    190:        if (*cp >= '0' && *cp <= '9')
                    191:            *wrd3 |= *cp++ - '0';
                    192:     }
                    193:     if (*cp == 'e' || *cp == 'E') {
                    194:        cp++;
                    195:        if (*cp == '-') {
                    196:            cp++;
                    197:            *wrd1 |= 0x40000000;
                    198:        }
                    199:        if (*cp == '+')
                    200:            cp++;
                    201:        t = 0;
                    202:        for (i = 0; i < 3; i++) {
                    203:            if (*cp >= '0' && *cp <= '9')
                    204:                t = (t << 4) | (*cp++ - '0');
1.1       root      205:        }
1.1.1.3   root      206:        *wrd1 |= t << 16;
                    207:     }
1.1       root      208: }
                    209: 
1.1.1.12! root      210: static void fpu_op_illg (uae_u32 opcode, int pcoffset)
        !           211: {
        !           212:     if ((currprefs.cpu_model == 68060 && (currprefs.fpu_model == 0 || (regs.pcr & 2)))
        !           213:        || (currprefs.cpu_model == 68040 && currprefs.fpu_model == 0)) {
        !           214:        /* 68040 unimplemented/68060 FPU disabled exception.
        !           215:         * Line F exception with different stack frame.. */
        !           216:        uaecptr newpc = m68k_getpc ();
        !           217:        uaecptr oldpc = newpc - pcoffset;
        !           218:        MakeSR ();
        !           219:        if (!regs.s) {
        !           220:            regs.usp = m68k_areg (regs, 7);
        !           221:            m68k_areg (regs, 7) = regs.isp;
        !           222:        }
        !           223:        regs.s = 1;
        !           224:        m68k_areg (regs, 7) -= 4;
        !           225:        put_long (m68k_areg (regs, 7), oldpc);
        !           226:        m68k_areg (regs, 7) -= 4;
        !           227:        put_long (m68k_areg (regs, 7), oldpc);
        !           228:        m68k_areg (regs, 7) -= 2;
        !           229:        put_word (m68k_areg (regs, 7), 0x4000 + 11 * 4);
        !           230:        m68k_areg (regs, 7) -= 4;
        !           231:        put_long (m68k_areg (regs, 7), newpc);
        !           232:        m68k_areg (regs, 7) -= 2;
        !           233:        put_word (m68k_areg (regs, 7), regs.sr);
        !           234:        write_log ("68040/060 FPU disabled exception PC=%x\n", newpc);
        !           235:        newpc = get_long (regs.vbr + 11 * 4);
        !           236:        m68k_setpc (newpc);
        !           237:        return;
        !           238:     }
        !           239:     op_illg (opcode);
        !           240: }
        !           241: 
        !           242: STATIC_INLINE int fault_if_no_fpu (uae_u32 opcode, int pcoffset)
        !           243: {
        !           244:     if ((regs.pcr & 2) || currprefs.fpu_model <= 0) {
        !           245:        fpu_op_illg (opcode, pcoffset);
        !           246:        return 1;
        !           247:     }
        !           248:     return 0;
        !           249: }
        !           250: 
1.1.1.8   root      251: STATIC_INLINE int get_fp_value (uae_u32 opcode, uae_u16 extra, fptype *src)
1.1       root      252: {
1.1.1.3   root      253:     uaecptr tmppc;
                    254:     uae_u16 tmp;
                    255:     int size;
                    256:     int mode;
                    257:     int reg;
                    258:     uae_u32 ad = 0;
1.1.1.12! root      259:     static const int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 };
        !           260:     static const int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 };
1.1.1.3   root      261: 
                    262:     if ((extra & 0x4000) == 0) {
                    263:        *src = regs.fp[(extra >> 10) & 7];
                    264:        return 1;
                    265:     }
                    266:     mode = (opcode >> 3) & 7;
                    267:     reg = opcode & 7;
                    268:     size = (extra >> 10) & 7;
1.1.1.12! root      269: 
1.1.1.3   root      270:     switch (mode) {
                    271:     case 0:
                    272:        switch (size) {
                    273:        case 6:
1.1.1.8   root      274:            *src = (fptype) (uae_s8) m68k_dreg (regs, reg);
1.1.1.3   root      275:            break;
                    276:        case 4:
1.1.1.8   root      277:            *src = (fptype) (uae_s16) m68k_dreg (regs, reg);
1.1.1.3   root      278:            break;
1.1       root      279:        case 0:
1.1.1.8   root      280:            *src = (fptype) (uae_s32) m68k_dreg (regs, reg);
1.1.1.3   root      281:            break;
                    282:        case 1:
1.1.1.5   root      283:            *src = to_single (m68k_dreg (regs, reg));
1.1.1.3   root      284:            break;
                    285:        default:
                    286:            return 0;
                    287:        }
                    288:        return 1;
                    289:     case 1:
                    290:        return 0;
                    291:     case 2:
                    292:        ad = m68k_areg (regs, reg);
                    293:        break;
                    294:     case 3:
                    295:        ad = m68k_areg (regs, reg);
                    296:        m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
                    297:        break;
                    298:     case 4:
                    299:        m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
                    300:        ad = m68k_areg (regs, reg);
                    301:        break;
                    302:     case 5:
1.1.1.5   root      303:        ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword ();
1.1.1.3   root      304:        break;
                    305:     case 6:
1.1.1.5   root      306:        ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword ());
1.1.1.3   root      307:        break;
                    308:     case 7:
                    309:        switch (reg) {
                    310:        case 0:
1.1.1.5   root      311:            ad = (uae_s32) (uae_s16) next_iword ();
1.1.1.3   root      312:            break;
1.1       root      313:        case 1:
1.1.1.5   root      314:            ad = next_ilong ();
1.1.1.3   root      315:            break;
1.1       root      316:        case 2:
1.1.1.3   root      317:            ad = m68k_getpc ();
1.1.1.5   root      318:            ad += (uae_s32) (uae_s16) next_iword ();
1.1.1.3   root      319:            break;
1.1       root      320:        case 3:
1.1.1.3   root      321:            tmppc = m68k_getpc ();
1.1.1.5   root      322:            tmp = next_iword ();
1.1.1.3   root      323:            ad = get_disp_ea_020 (tmppc, tmp);
                    324:            break;
1.1       root      325:        case 4:
1.1.1.3   root      326:            ad = m68k_getpc ();
                    327:            m68k_setpc (ad + sz2[size]);
                    328:            break;
1.1       root      329:        default:
1.1.1.3   root      330:            return 0;
1.1       root      331:        }
1.1.1.3   root      332:     }
                    333:     switch (size) {
                    334:     case 0:
1.1.1.8   root      335:        *src = (fptype) (uae_s32) get_long (ad);
1.1.1.3   root      336:        break;
                    337:     case 1:
1.1.1.5   root      338:        *src = to_single (get_long (ad));
1.1.1.3   root      339:        break;
                    340:     case 2:{
                    341:            uae_u32 wrd1, wrd2, wrd3;
                    342:            wrd1 = get_long (ad);
                    343:            ad += 4;
                    344:            wrd2 = get_long (ad);
                    345:            ad += 4;
                    346:            wrd3 = get_long (ad);
1.1.1.5   root      347:            *src = to_exten (wrd1, wrd2, wrd3);
1.1.1.3   root      348:        }
                    349:        break;
                    350:     case 3:{
                    351:            uae_u32 wrd1, wrd2, wrd3;
                    352:            wrd1 = get_long (ad);
                    353:            ad += 4;
                    354:            wrd2 = get_long (ad);
                    355:            ad += 4;
                    356:            wrd3 = get_long (ad);
1.1.1.5   root      357:            *src = to_pack (wrd1, wrd2, wrd3);
1.1.1.3   root      358:        }
                    359:        break;
                    360:     case 4:
1.1.1.8   root      361:        *src = (fptype) (uae_s16) get_word (ad);
1.1.1.3   root      362:        break;
                    363:     case 5:{
                    364:            uae_u32 wrd1, wrd2;
                    365:            wrd1 = get_long (ad);
                    366:            ad += 4;
                    367:            wrd2 = get_long (ad);
1.1.1.5   root      368:            *src = to_double (wrd1, wrd2);
1.1.1.3   root      369:        }
                    370:        break;
                    371:     case 6:
1.1.1.8   root      372:        *src = (fptype) (uae_s8) get_byte (ad);
1.1.1.3   root      373:        break;
                    374:     default:
                    375:        return 0;
                    376:     }
                    377:     return 1;
1.1       root      378: }
                    379: 
1.1.1.8   root      380: STATIC_INLINE int put_fp_value (fptype value, uae_u32 opcode, uae_u16 extra)
1.1       root      381: {
1.1.1.3   root      382:     uae_u16 tmp;
                    383:     uaecptr tmppc;
                    384:     int size;
                    385:     int mode;
                    386:     int reg;
                    387:     uae_u32 ad;
1.1.1.5   root      388:     static int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 };
                    389:     static int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 };
1.1.1.3   root      390: 
                    391:     if ((extra & 0x4000) == 0) {
                    392:        regs.fp[(extra >> 10) & 7] = value;
                    393:        return 1;
                    394:     }
                    395:     mode = (opcode >> 3) & 7;
                    396:     reg = opcode & 7;
                    397:     size = (extra >> 10) & 7;
                    398:     ad = -1;
1.1.1.10  root      399: 
1.1.1.3   root      400:     switch (mode) {
                    401:     case 0:
                    402:        switch (size) {
                    403:        case 6:
1.1.1.12! root      404:            m68k_dreg (regs, reg) = ((toint (value) & 0xff)
1.1.1.4   root      405:                                     | (m68k_dreg (regs, reg) & ~0xff));
1.1.1.3   root      406:            break;
                    407:        case 4:
1.1.1.12! root      408:            m68k_dreg (regs, reg) = ((toint (value) & 0xffff)
1.1.1.4   root      409:                                     | (m68k_dreg (regs, reg) & ~0xffff));
1.1.1.3   root      410:            break;
1.1       root      411:        case 0:
1.1.1.12! root      412:            m68k_dreg (regs, reg) = toint (value);
1.1.1.3   root      413:            break;
1.1       root      414:        case 1:
1.1.1.5   root      415:            m68k_dreg (regs, reg) = from_single (value);
1.1.1.3   root      416:            break;
                    417:        default:
                    418:            return 0;
                    419:        }
                    420:        return 1;
                    421:     case 1:
                    422:        return 0;
                    423:     case 2:
                    424:        ad = m68k_areg (regs, reg);
                    425:        break;
                    426:     case 3:
                    427:        ad = m68k_areg (regs, reg);
                    428:        m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
                    429:        break;
                    430:     case 4:
                    431:        m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
                    432:        ad = m68k_areg (regs, reg);
                    433:        break;
                    434:     case 5:
1.1.1.5   root      435:        ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword ();
1.1.1.3   root      436:        break;
                    437:     case 6:
1.1.1.5   root      438:        ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword ());
1.1.1.3   root      439:        break;
                    440:     case 7:
                    441:        switch (reg) {
                    442:        case 0:
1.1.1.5   root      443:            ad = (uae_s32) (uae_s16) next_iword ();
1.1.1.3   root      444:            break;
                    445:        case 1:
1.1.1.5   root      446:            ad = next_ilong ();
1.1.1.3   root      447:            break;
1.1       root      448:        case 2:
1.1.1.3   root      449:            ad = m68k_getpc ();
1.1.1.5   root      450:            ad += (uae_s32) (uae_s16) next_iword ();
1.1.1.3   root      451:            break;
1.1       root      452:        case 3:
1.1.1.3   root      453:            tmppc = m68k_getpc ();
1.1.1.5   root      454:            tmp = next_iword ();
1.1.1.3   root      455:            ad = get_disp_ea_020 (tmppc, tmp);
                    456:            break;
1.1       root      457:        case 4:
1.1.1.3   root      458:            ad = m68k_getpc ();
                    459:            m68k_setpc (ad + sz2[size]);
                    460:            break;
1.1       root      461:        default:
1.1.1.3   root      462:            return 0;
1.1       root      463:        }
1.1.1.3   root      464:     }
                    465:     switch (size) {
                    466:     case 0:
1.1.1.12! root      467:        put_long (ad, toint (value));
1.1.1.3   root      468:        break;
                    469:     case 1:
1.1.1.5   root      470:        put_long (ad, from_single (value));
1.1.1.3   root      471:        break;
                    472:     case 2:
                    473:        {
                    474:            uae_u32 wrd1, wrd2, wrd3;
1.1.1.5   root      475:            from_exten (value, &wrd1, &wrd2, &wrd3);
1.1.1.3   root      476:            put_long (ad, wrd1);
                    477:            ad += 4;
                    478:            put_long (ad, wrd2);
                    479:            ad += 4;
                    480:            put_long (ad, wrd3);
                    481:        }
                    482:        break;
                    483:     case 3:
                    484:        {
                    485:            uae_u32 wrd1, wrd2, wrd3;
1.1.1.5   root      486:            from_pack (value, &wrd1, &wrd2, &wrd3);
1.1.1.3   root      487:            put_long (ad, wrd1);
                    488:            ad += 4;
                    489:            put_long (ad, wrd2);
                    490:            ad += 4;
                    491:            put_long (ad, wrd3);
                    492:        }
                    493:        break;
                    494:     case 4:
1.1.1.12! root      495:        put_word (ad, (uae_s16) toint (value));
1.1.1.3   root      496:        break;
                    497:     case 5:{
                    498:            uae_u32 wrd1, wrd2;
1.1.1.5   root      499:            from_double (value, &wrd1, &wrd2);
1.1.1.3   root      500:            put_long (ad, wrd1);
                    501:            ad += 4;
                    502:            put_long (ad, wrd2);
                    503:        }
                    504:        break;
                    505:     case 6:
1.1.1.12! root      506:        put_byte (ad, (uae_s8)toint (value));
1.1.1.3   root      507:        break;
                    508:     default:
                    509:        return 0;
                    510:     }
                    511:     return 1;
1.1       root      512: }
                    513: 
1.1.1.5   root      514: STATIC_INLINE int get_fp_ad (uae_u32 opcode, uae_u32 * ad)
1.1       root      515: {
1.1.1.3   root      516:     uae_u16 tmp;
                    517:     uaecptr tmppc;
                    518:     int mode;
                    519:     int reg;
                    520: 
                    521:     mode = (opcode >> 3) & 7;
                    522:     reg = opcode & 7;
                    523:     switch (mode) {
                    524:     case 0:
                    525:     case 1:
                    526:        return 0;
                    527:     case 2:
                    528:        *ad = m68k_areg (regs, reg);
                    529:        break;
                    530:     case 3:
                    531:        *ad = m68k_areg (regs, reg);
                    532:        break;
                    533:     case 4:
                    534:        *ad = m68k_areg (regs, reg);
                    535:        break;
                    536:     case 5:
1.1.1.5   root      537:        *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword ();
1.1.1.3   root      538:        break;
                    539:     case 6:
1.1.1.5   root      540:        *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword ());
1.1.1.3   root      541:        break;
                    542:     case 7:
                    543:        switch (reg) {
1.1       root      544:        case 0:
1.1.1.5   root      545:            *ad = (uae_s32) (uae_s16) next_iword ();
1.1.1.3   root      546:            break;
1.1       root      547:        case 1:
1.1.1.5   root      548:            *ad = next_ilong ();
1.1.1.3   root      549:            break;
1.1       root      550:        case 2:
1.1.1.3   root      551:            *ad = m68k_getpc ();
1.1.1.5   root      552:            *ad += (uae_s32) (uae_s16) next_iword ();
1.1.1.3   root      553:            break;
1.1       root      554:        case 3:
1.1.1.3   root      555:            tmppc = m68k_getpc ();
1.1.1.5   root      556:            tmp = next_iword ();
1.1.1.3   root      557:            *ad = get_disp_ea_020 (tmppc, tmp);
                    558:            break;
                    559:        default:
                    560:            return 0;
1.1       root      561:        }
1.1.1.3   root      562:     }
                    563:     return 1;
1.1       root      564: }
                    565: 
1.1.1.5   root      566: STATIC_INLINE int fpp_cond (uae_u32 opcode, int contition)
1.1       root      567: {
1.1.1.12! root      568:     int N = (regs.fp_result < 0);
        !           569:     int Z = (regs.fp_result == 0);
1.1.1.3   root      570:     /* int I = (regs.fpsr & 0x2000000) != 0; */
1.1.1.9   root      571:     int NotANumber = 0;
                    572: 
                    573: #ifdef HAVE_ISNAN
                    574:     NotANumber = isnan (regs.fp_result);
                    575: #endif
                    576: 
1.1.1.8   root      577:     if (NotANumber)
                    578:        N=Z=0;
1.1.1.3   root      579: 
                    580:     switch (contition) {
                    581:     case 0x00:
                    582:        return 0;
                    583:     case 0x01:
                    584:        return Z;
                    585:     case 0x02:
                    586:        return !(NotANumber || Z || N);
                    587:     case 0x03:
                    588:        return Z || !(NotANumber || N);
                    589:     case 0x04:
                    590:        return N && !(NotANumber || Z);
                    591:     case 0x05:
                    592:        return Z || (N && !NotANumber);
                    593:     case 0x06:
                    594:        return !(NotANumber || Z);
                    595:     case 0x07:
                    596:        return !NotANumber;
                    597:     case 0x08:
                    598:        return NotANumber;
                    599:     case 0x09:
                    600:        return NotANumber || Z;
                    601:     case 0x0a:
                    602:        return NotANumber || !(N || Z);
                    603:     case 0x0b:
                    604:        return NotANumber || Z || !N;
                    605:     case 0x0c:
                    606:        return NotANumber || (N && !Z);
                    607:     case 0x0d:
                    608:        return NotANumber || Z || N;
                    609:     case 0x0e:
                    610:        return !Z;
                    611:     case 0x0f:
                    612:        return 1;
                    613:     case 0x10:
                    614:        return 0;
                    615:     case 0x11:
                    616:        return Z;
                    617:     case 0x12:
                    618:        return !(NotANumber || Z || N);
                    619:     case 0x13:
                    620:        return Z || !(NotANumber || N);
                    621:     case 0x14:
                    622:        return N && !(NotANumber || Z);
                    623:     case 0x15:
                    624:        return Z || (N && !NotANumber);
                    625:     case 0x16:
                    626:        return !(NotANumber || Z);
                    627:     case 0x17:
                    628:        return !NotANumber;
                    629:     case 0x18:
                    630:        return NotANumber;
                    631:     case 0x19:
                    632:        return NotANumber || Z;
                    633:     case 0x1a:
                    634:        return NotANumber || !(N || Z);
                    635:     case 0x1b:
                    636:        return NotANumber || Z || !N;
                    637:     case 0x1c:
1.1.1.8   root      638: #if 0
1.1.1.10  root      639:        return NotANumber || (Z && N); /* This is wrong, compare 0x0c */
1.1.1.8   root      640: #else
1.1.1.10  root      641:        return NotANumber || (N && !Z);
1.1.1.8   root      642: #endif
1.1.1.3   root      643:     case 0x1d:
                    644:        return NotANumber || Z || N;
                    645:     case 0x1e:
                    646:        return !Z;
                    647:     case 0x1f:
                    648:        return 1;
                    649:     }
                    650:     return -1;
1.1       root      651: }
                    652: 
1.1.1.5   root      653: void fdbcc_opp (uae_u32 opcode, uae_u16 extra)
1.1       root      654: {
1.1.1.3   root      655:     uaecptr pc = (uae_u32) m68k_getpc ();
1.1.1.12! root      656:     uae_s32 disp;
1.1.1.3   root      657:     int cc;
1.1       root      658: 
1.1.1.12! root      659:     if (fault_if_no_fpu (opcode, 4))
        !           660:        return;
        !           661: 
        !           662:     disp = (uae_s32) (uae_s16) next_iword ();
        !           663: 
1.1       root      664: #if DEBUG_FPP
1.1.1.5   root      665:     printf ("fdbcc_opp at %08lx\n", m68k_getpc ());
                    666:     fflush (stdout);
1.1       root      667: #endif
1.1.1.5   root      668:     cc = fpp_cond (opcode, extra & 0x3f);
1.1.1.3   root      669:     if (cc == -1) {
1.1.1.12! root      670:        fpu_op_illg (opcode, 4);
1.1.1.3   root      671:     } else if (!cc) {
                    672:        int reg = opcode & 0x7;
                    673: 
                    674:        m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & ~0xffff)
1.1.1.5   root      675:                                 | ((m68k_dreg (regs, reg) - 1) & 0xffff));
1.1.1.3   root      676:        if ((m68k_dreg (regs, reg) & 0xffff) == 0xffff)
                    677:            m68k_setpc (pc + disp);
                    678:     }
1.1       root      679: }
                    680: 
1.1.1.5   root      681: void fscc_opp (uae_u32 opcode, uae_u16 extra)
1.1       root      682: {
1.1.1.3   root      683:     uae_u32 ad;
                    684:     int cc;
1.1       root      685: 
1.1.1.12! root      686:     if (fault_if_no_fpu (opcode, 4))
        !           687:        return;
        !           688: 
1.1       root      689: #if DEBUG_FPP
1.1.1.5   root      690:     printf ("fscc_opp at %08lx\n", m68k_getpc ());
                    691:     fflush (stdout);
1.1       root      692: #endif
1.1.1.12! root      693: 
1.1.1.5   root      694:     cc = fpp_cond (opcode, extra & 0x3f);
1.1.1.3   root      695:     if (cc == -1) {
1.1.1.12! root      696:        fpu_op_illg (opcode, 4);
1.1.1.3   root      697:     } else if ((opcode & 0x38) == 0) {
1.1.1.5   root      698:        m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | (cc ? 0xff : 0x00);
1.1.1.3   root      699:     } else {
1.1.1.5   root      700:        if (get_fp_ad (opcode, &ad) == 0) {
1.1.1.3   root      701:            m68k_setpc (m68k_getpc () - 4);
                    702:            op_illg (opcode);
                    703:        } else
1.1.1.5   root      704:            put_byte (ad, cc ? 0xff : 0x00);
1.1.1.3   root      705:     }
1.1       root      706: }
                    707: 
1.1.1.5   root      708: void ftrapcc_opp (uae_u32 opcode, uaecptr oldpc)
1.1       root      709: {
1.1.1.3   root      710:     int cc;
1.1       root      711: 
1.1.1.12! root      712:     if (fault_if_no_fpu (opcode, m68k_getpc () - oldpc))
        !           713:        return;
        !           714: 
1.1       root      715: #if DEBUG_FPP
1.1.1.5   root      716:     printf ("ftrapcc_opp at %08lx\n", m68k_getpc ());
                    717:     fflush (stdout);
1.1       root      718: #endif
1.1.1.5   root      719:     cc = fpp_cond (opcode, opcode & 0x3f);
1.1.1.3   root      720:     if (cc == -1) {
1.1.1.12! root      721:        fpu_op_illg (opcode, m68k_getpc () - oldpc);
1.1.1.3   root      722:     }
                    723:     if (cc)
1.1.1.5   root      724:        Exception (7, oldpc - 2);
1.1       root      725: }
                    726: 
1.1.1.5   root      727: void fbcc_opp (uae_u32 opcode, uaecptr pc, uae_u32 extra)
1.1       root      728: {
1.1.1.3   root      729:     int cc;
1.1       root      730: 
1.1.1.12! root      731:     if (fault_if_no_fpu (opcode, m68k_getpc () - pc))
        !           732:        return;
        !           733: 
1.1       root      734: #if DEBUG_FPP
1.1.1.5   root      735:     printf ("fbcc_opp at %08lx\n", m68k_getpc ());
                    736:     fflush (stdout);
1.1       root      737: #endif
1.1.1.5   root      738:     cc = fpp_cond (opcode, opcode & 0x3f);
1.1.1.3   root      739:     if (cc == -1) {
1.1.1.12! root      740:        fpu_op_illg (opcode, m68k_getpc () - pc);
1.1.1.3   root      741:     } else if (cc) {
                    742:        if ((opcode & 0x40) == 0)
                    743:            extra = (uae_s32) (uae_s16) extra;
                    744:        m68k_setpc (pc + extra);
                    745:     }
1.1       root      746: }
                    747: 
1.1.1.5   root      748: void fsave_opp (uae_u32 opcode)
1.1       root      749: {
1.1.1.3   root      750:     uae_u32 ad;
                    751:     int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
1.1.1.12! root      752:     int fpu_version = get_fpu_version();
1.1.1.3   root      753:     int i;
                    754: 
1.1.1.12! root      755:     if (fault_if_no_fpu (opcode, 2))
        !           756:        return;
        !           757: 
1.1       root      758: #if DEBUG_FPP
1.1.1.5   root      759:     printf ("fsave_opp at %08lx\n", m68k_getpc ());
                    760:     fflush (stdout);
1.1       root      761: #endif
1.1.1.5   root      762:     if (get_fp_ad (opcode, &ad) == 0) {
1.1.1.12! root      763:        fpu_op_illg (opcode, 2);
1.1.1.3   root      764:        return;
                    765:     }
1.1.1.5   root      766: 
1.1.1.12! root      767:     if (currprefs.fpu_model == 68060) {
        !           768:        /* 12 byte 68060 IDLE frame.  */
        !           769:        if (incr < 0) {
        !           770:            ad -= 4;
        !           771:            put_long (ad, 0x00000000);
        !           772:            ad -= 4;
        !           773:            put_long (ad, 0x00000000);
        !           774:            ad -= 4;
        !           775:            put_long (ad, 0x00006000);
        !           776:        } else {
        !           777:            put_long (ad, 0x00006000);
        !           778:            ad += 4;
        !           779:            put_long (ad, 0x00000000);
        !           780:            ad += 4;
        !           781:            put_long (ad, 0x00000000);
        !           782:            ad += 4;
        !           783:        }
        !           784:     } else if (currprefs.fpu_model == 68040) {
1.1.1.6   root      785:        /* 4 byte 68040 IDLE frame.  */
                    786:        if (incr < 0) {
                    787:            ad -= 4;
1.1.1.12! root      788:            put_long (ad, fpu_version << 24);
1.1.1.6   root      789:        } else {
1.1.1.12! root      790:            put_long (ad, fpu_version << 24);
1.1.1.6   root      791:            ad += 4;
                    792:        }
1.1.1.12! root      793:     } else { /* 68881/68882 */
        !           794:        int idle_size = currprefs.fpu_model == 68882 ? 0x38 : 0x18;
1.1.1.5   root      795:        if (incr < 0) {
                    796:            ad -= 4;
                    797:            put_long (ad, 0x70000000);
1.1.1.12! root      798:            for (i = 0; i < (idle_size - 1) / 4; i++) {
1.1.1.5   root      799:                ad -= 4;
                    800:                put_long (ad, 0x00000000);
                    801:            }
                    802:            ad -= 4;
1.1.1.12! root      803:            put_long (ad, (fpu_version << 24) | (idle_size << 16));
1.1.1.5   root      804:        } else {
1.1.1.12! root      805:            put_long (ad, (fpu_version << 24) | (idle_size << 16));
1.1.1.5   root      806:            ad += 4;
1.1.1.12! root      807:            for (i = 0; i < (idle_size - 1) / 4; i++) {
1.1.1.5   root      808:                put_long (ad, 0x00000000);
                    809:                ad += 4;
                    810:            }
                    811:            put_long (ad, 0x70000000);
1.1.1.3   root      812:            ad += 4;
                    813:        }
                    814:     }
                    815:     if ((opcode & 0x38) == 0x18)
                    816:        m68k_areg (regs, opcode & 7) = ad;
                    817:     if ((opcode & 0x38) == 0x20)
                    818:        m68k_areg (regs, opcode & 7) = ad;
1.1       root      819: }
                    820: 
1.1.1.5   root      821: void frestore_opp (uae_u32 opcode)
1.1       root      822: {
1.1.1.3   root      823:     uae_u32 ad;
                    824:     uae_u32 d;
                    825:     int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
                    826: 
1.1.1.12! root      827:     if (fault_if_no_fpu (opcode, 2))
        !           828:        return;
        !           829: 
1.1       root      830: #if DEBUG_FPP
1.1.1.5   root      831:     printf ("frestore_opp at %08lx\n", m68k_getpc ());
                    832:     fflush (stdout);
1.1       root      833: #endif
1.1.1.5   root      834:     if (get_fp_ad (opcode, &ad) == 0) {
1.1.1.12! root      835:        fpu_op_illg (opcode, 2);
1.1.1.3   root      836:        return;
                    837:     }
1.1.1.12! root      838:     if (currprefs.fpu_model == 68060) {
        !           839:        /* all 68060 FPU frames are 12 bytes */
        !           840:        if (incr < 0) {
        !           841:            ad -= 4;
        !           842:            d = get_long (ad);
        !           843:            ad -= 8;
        !           844:        } else {
        !           845:            d = get_long (ad);
        !           846:            ad += 4;
        !           847:            ad += 8;
        !           848:        }
        !           849: 
        !           850:     } else if (currprefs.fpu_model == 68040) {
1.1.1.6   root      851:        /* 68040 */
                    852:        if (incr < 0) {
                    853:            /* @@@ This may be wrong.  */
                    854:            ad -= 4;
                    855:            d = get_long (ad);
                    856:            if ((d & 0xff000000) != 0) { /* Not a NULL frame? */
                    857:                if ((d & 0x00ff0000) == 0) { /* IDLE */
                    858:                } else if ((d & 0x00ff0000) == 0x00300000) { /* UNIMP */
                    859:                    ad -= 44;
                    860:                } else if ((d & 0x00ff0000) == 0x00600000) { /* BUSY */
                    861:                    ad -= 92;
                    862:                }
                    863:            }
                    864:        } else {
                    865:            d = get_long (ad);
                    866:            ad += 4;
                    867:            if ((d & 0xff000000) != 0) { /* Not a NULL frame? */
                    868:                if ((d & 0x00ff0000) == 0) { /* IDLE */
                    869:                } else if ((d & 0x00ff0000) == 0x00300000) { /* UNIMP */
                    870:                    ad += 44;
                    871:                } else if ((d & 0x00ff0000) == 0x00600000) { /* BUSY */
                    872:                    ad += 92;
                    873:                }
                    874:            }
                    875:        }
1.1.1.12! root      876:     } else { /* 68881/68882 */
1.1.1.5   root      877:        if (incr < 0) {
                    878:            ad -= 4;
                    879:            d = get_long (ad);
                    880:            if ((d & 0xff000000) != 0) {
                    881:                if ((d & 0x00ff0000) == 0x00180000)
                    882:                    ad -= 6 * 4;
                    883:                else if ((d & 0x00ff0000) == 0x00380000)
                    884:                    ad -= 14 * 4;
                    885:                else if ((d & 0x00ff0000) == 0x00b40000)
                    886:                    ad -= 45 * 4;
                    887:            }
                    888:        } else {
                    889:            d = get_long (ad);
                    890:            ad += 4;
                    891:            if ((d & 0xff000000) != 0) {
                    892:                if ((d & 0x00ff0000) == 0x00180000)
                    893:                    ad += 6 * 4;
                    894:                else if ((d & 0x00ff0000) == 0x00380000)
                    895:                    ad += 14 * 4;
                    896:                else if ((d & 0x00ff0000) == 0x00b40000)
                    897:                    ad += 45 * 4;
                    898:            }
1.1.1.3   root      899:        }
                    900:     }
                    901:     if ((opcode & 0x38) == 0x18)
                    902:        m68k_areg (regs, opcode & 7) = ad;
                    903:     if ((opcode & 0x38) == 0x20)
                    904:        m68k_areg (regs, opcode & 7) = ad;
1.1       root      905: }
                    906: 
1.1.1.5   root      907: void fpp_opp (uae_u32 opcode, uae_u16 extra)
1.1       root      908: {
1.1.1.3   root      909:     int reg;
1.1.1.8   root      910:     fptype src;
1.1       root      911: 
1.1.1.12! root      912:     if (fault_if_no_fpu (opcode, 4))
        !           913:        return;
        !           914: 
1.1       root      915: #if DEBUG_FPP
1.1.1.5   root      916:     printf ("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra & 0xffff, m68k_getpc () - 4);
                    917:     fflush (stdout);
1.1       root      918: #endif
1.1.1.3   root      919:     switch ((extra >> 13) & 0x7) {
                    920:     case 3:
                    921:        if (put_fp_value (regs.fp[(extra >> 7) & 7], opcode, extra) == 0) {
                    922:            m68k_setpc (m68k_getpc () - 4);
                    923:            op_illg (opcode);
                    924:        }
                    925:        return;
                    926:     case 4:
                    927:     case 5:
                    928:        if ((opcode & 0x38) == 0) {
                    929:            if (extra & 0x2000) {
                    930:                if (extra & 0x1000)
                    931:                    m68k_dreg (regs, opcode & 7) = regs.fpcr;
                    932:                if (extra & 0x0800)
1.1.1.8   root      933:                    m68k_dreg (regs, opcode & 7) = get_fpsr ();
1.1.1.3   root      934:                if (extra & 0x0400)
                    935:                    m68k_dreg (regs, opcode & 7) = regs.fpiar;
                    936:            } else {
1.1.1.8   root      937:                if (extra & 0x1000) {
1.1.1.3   root      938:                    regs.fpcr = m68k_dreg (regs, opcode & 7);
1.1.1.8   root      939:                    native_set_fpucw (regs.fpcr);
                    940:                }
1.1.1.3   root      941:                if (extra & 0x0800)
1.1.1.8   root      942:                    set_fpsr (m68k_dreg (regs, opcode & 7));
1.1.1.3   root      943:                if (extra & 0x0400)
                    944:                    regs.fpiar = m68k_dreg (regs, opcode & 7);
                    945:            }
1.1.1.7   root      946:        } else if ((opcode & 0x38) == 0x08) {
1.1.1.3   root      947:            if (extra & 0x2000) {
                    948:                if (extra & 0x1000)
                    949:                    m68k_areg (regs, opcode & 7) = regs.fpcr;
                    950:                if (extra & 0x0800)
1.1.1.8   root      951:                    m68k_areg (regs, opcode & 7) = get_fpsr ();
1.1.1.3   root      952:                if (extra & 0x0400)
                    953:                    m68k_areg (regs, opcode & 7) = regs.fpiar;
                    954:            } else {
1.1.1.8   root      955:                if (extra & 0x1000) {
1.1.1.3   root      956:                    regs.fpcr = m68k_areg (regs, opcode & 7);
1.1.1.8   root      957:                    native_set_fpucw (regs.fpcr);
                    958:                }
1.1.1.3   root      959:                if (extra & 0x0800)
1.1.1.8   root      960:                    set_fpsr (m68k_areg (regs, opcode & 7));
1.1.1.3   root      961:                if (extra & 0x0400)
                    962:                    regs.fpiar = m68k_areg (regs, opcode & 7);
                    963:            }
                    964:        } else if ((opcode & 0x3f) == 0x3c) {
                    965:            if ((extra & 0x2000) == 0) {
1.1.1.8   root      966:                if (extra & 0x1000) {
1.1.1.5   root      967:                    regs.fpcr = next_ilong ();
1.1.1.8   root      968:                    native_set_fpucw (regs.fpcr);
                    969:                }
1.1.1.3   root      970:                if (extra & 0x0800)
1.1.1.8   root      971:                    set_fpsr (next_ilong ());
1.1.1.3   root      972:                if (extra & 0x0400)
1.1.1.5   root      973:                    regs.fpiar = next_ilong ();
1.1.1.3   root      974:            }
                    975:        } else if (extra & 0x2000) {
                    976:            /* FMOVEM FPP->memory */
                    977:            uae_u32 ad;
                    978:            int incr = 0;
                    979: 
1.1.1.5   root      980:            if (get_fp_ad (opcode, &ad) == 0) {
1.1.1.3   root      981:                m68k_setpc (m68k_getpc () - 4);
                    982:                op_illg (opcode);
1.1       root      983:                return;
1.1.1.3   root      984:            }
                    985:            if ((opcode & 0x38) == 0x20) {
                    986:                if (extra & 0x1000)
                    987:                    incr += 4;
                    988:                if (extra & 0x0800)
                    989:                    incr += 4;
                    990:                if (extra & 0x0400)
                    991:                    incr += 4;
                    992:            }
                    993:            ad -= incr;
                    994:            if (extra & 0x1000) {
                    995:                put_long (ad, regs.fpcr);
                    996:                ad += 4;
                    997:            }
                    998:            if (extra & 0x0800) {
1.1.1.8   root      999:                put_long (ad, get_fpsr());
1.1.1.3   root     1000:                ad += 4;
                   1001:            }
                   1002:            if (extra & 0x0400) {
                   1003:                put_long (ad, regs.fpiar);
                   1004:                ad += 4;
                   1005:            }
                   1006:            ad -= incr;
                   1007:            if ((opcode & 0x38) == 0x18)
                   1008:                m68k_areg (regs, opcode & 7) = ad;
                   1009:            if ((opcode & 0x38) == 0x20)
                   1010:                m68k_areg (regs, opcode & 7) = ad;
                   1011:        } else {
                   1012:            /* FMOVEM memory->FPP */
                   1013:            uae_u32 ad;
                   1014: 
1.1.1.5   root     1015:            if (get_fp_ad (opcode, &ad) == 0) {
1.1.1.3   root     1016:                m68k_setpc (m68k_getpc () - 4);
                   1017:                op_illg (opcode);
1.1       root     1018:                return;
1.1.1.3   root     1019:            }
                   1020:            ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad;
                   1021:            if (extra & 0x1000) {
                   1022:                regs.fpcr = get_long (ad);
1.1.1.8   root     1023:                native_set_fpucw(regs.fpcr);
1.1.1.3   root     1024:                ad += 4;
                   1025:            }
                   1026:            if (extra & 0x0800) {
1.1.1.8   root     1027:                set_fpsr(get_long (ad));
1.1.1.3   root     1028:                ad += 4;
                   1029:            }
                   1030:            if (extra & 0x0400) {
                   1031:                regs.fpiar = get_long (ad);
                   1032:                ad += 4;
                   1033:            }
                   1034:            if ((opcode & 0x38) == 0x18)
                   1035:                m68k_areg (regs, opcode & 7) = ad;
                   1036:            if ((opcode & 0x38) == 0x20)
                   1037:                m68k_areg (regs, opcode & 7) = ad - 12;
                   1038:        }
                   1039:        return;
                   1040:     case 6:
                   1041:     case 7:
1.1.1.7   root     1042:     {
                   1043:        uae_u32 ad, list = 0;
                   1044:        int incr = 0;
                   1045:        if (extra & 0x2000) {
                   1046:            /* FMOVEM FPP->memory */
                   1047:            if (get_fp_ad (opcode, &ad) == 0) {
                   1048:                m68k_setpc (m68k_getpc () - 4);
                   1049:                op_illg (opcode);
                   1050:                return;
                   1051:            }
                   1052:            switch ((extra >> 11) & 3) {
                   1053:            case 0:     /* static pred */
                   1054:                list = extra & 0xff;
                   1055:                incr = -1;
                   1056:                break;
                   1057:            case 1:     /* dynamic pred */
                   1058:                list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
                   1059:                incr = -1;
                   1060:                break;
                   1061:            case 2:     /* static postinc */
                   1062:                list = extra & 0xff;
                   1063:                incr = 1;
                   1064:                break;
                   1065:            case 3:     /* dynamic postinc */
                   1066:                list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
                   1067:                incr = 1;
                   1068:                break;
                   1069:            }
                   1070:            while (list) {
                   1071:                uae_u32 wrd1, wrd2, wrd3;
                   1072:                if (incr < 0) {
                   1073:                    from_exten (regs.fp[fpp_movem_index2[list]], &wrd1, &wrd2, &wrd3);
                   1074:                    ad -= 4;
                   1075:                    put_long (ad, wrd3);
                   1076:                    ad -= 4;
                   1077:                    put_long (ad, wrd2);
                   1078:                    ad -= 4;
                   1079:                    put_long (ad, wrd1);
                   1080:                } else {
                   1081:                    from_exten (regs.fp[fpp_movem_index1[list]], &wrd1, &wrd2, &wrd3);
                   1082:                    put_long (ad, wrd1);
                   1083:                    ad += 4;
                   1084:                    put_long (ad, wrd2);
                   1085:                    ad += 4;
                   1086:                    put_long (ad, wrd3);
                   1087:                    ad += 4;
1.1.1.3   root     1088:                }
1.1.1.7   root     1089:                list = fpp_movem_next[list];
                   1090:            }
                   1091:            if ((opcode & 0x38) == 0x18)
                   1092:                m68k_areg (regs, opcode & 7) = ad;
                   1093:            if ((opcode & 0x38) == 0x20)
                   1094:                m68k_areg (regs, opcode & 7) = ad;
                   1095:        } else {
                   1096:            /* FMOVEM memory->FPP */
                   1097:            if (get_fp_ad (opcode, &ad) == 0) {
                   1098:                m68k_setpc (m68k_getpc () - 4);
                   1099:                op_illg (opcode);
                   1100:                return;
                   1101:            }
                   1102:            switch ((extra >> 11) & 3) {
                   1103:            case 0:     /* static pred */
                   1104:                list = extra & 0xff;
                   1105:                incr = -1;
                   1106:                break;
                   1107:            case 1:     /* dynamic pred */
                   1108:                list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
                   1109:                incr = -1;
                   1110:                break;
                   1111:            case 2:     /* static postinc */
                   1112:                list = extra & 0xff;
                   1113:                incr = 1;
                   1114:                break;
                   1115:            case 3:     /* dynamic postinc */
                   1116:                list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff;
                   1117:                incr = 1;
                   1118:                break;
                   1119:            }
                   1120:            while (list) {
                   1121:                uae_u32 wrd1, wrd2, wrd3;
                   1122:                if (incr < 0) {
                   1123:                    ad -= 4;
                   1124:                    wrd3 = get_long (ad);
                   1125:                    ad -= 4;
                   1126:                    wrd2 = get_long (ad);
                   1127:                    ad -= 4;
                   1128:                    wrd1 = get_long (ad);
                   1129:                    regs.fp[fpp_movem_index2[list]] = to_exten (wrd1, wrd2, wrd3);
                   1130:                } else {
                   1131:                    wrd1 = get_long (ad);
                   1132:                    ad += 4;
                   1133:                    wrd2 = get_long (ad);
                   1134:                    ad += 4;
                   1135:                    wrd3 = get_long (ad);
                   1136:                    ad += 4;
                   1137:                    regs.fp[fpp_movem_index1[list]] = to_exten (wrd1, wrd2, wrd3);
1.1       root     1138:                }
1.1.1.7   root     1139:                list = fpp_movem_next[list];
1.1.1.3   root     1140:            }
1.1.1.7   root     1141:            if ((opcode & 0x38) == 0x18)
                   1142:                m68k_areg (regs, opcode & 7) = ad;
                   1143:            if ((opcode & 0x38) == 0x20)
                   1144:                m68k_areg (regs, opcode & 7) = ad;
1.1.1.3   root     1145:        }
1.1.1.7   root     1146:     }
                   1147:     return;
1.1.1.3   root     1148:     case 0:
1.1.1.8   root     1149:     case 2: /* Extremely common */
1.1.1.3   root     1150:        reg = (extra >> 7) & 7;
                   1151:        if ((extra & 0xfc00) == 0x5c00) {
                   1152:            switch (extra & 0x7f) {
                   1153:            case 0x00:
1.1.1.5   root     1154:                regs.fp[reg] = 4.0 * atan (1.0);
1.1.1.3   root     1155:                break;
                   1156:            case 0x0b:
                   1157:                regs.fp[reg] = log10 (2.0);
                   1158:                break;
                   1159:            case 0x0c:
                   1160:                regs.fp[reg] = exp (1.0);
                   1161:                break;
                   1162:            case 0x0d:
                   1163:                regs.fp[reg] = log (exp (1.0)) / log (2.0);
                   1164:                break;
                   1165:            case 0x0e:
                   1166:                regs.fp[reg] = log (exp (1.0)) / log (10.0);
                   1167:                break;
                   1168:            case 0x0f:
                   1169:                regs.fp[reg] = 0.0;
                   1170:                break;
                   1171:            case 0x30:
                   1172:                regs.fp[reg] = log (2.0);
                   1173:                break;
                   1174:            case 0x31:
                   1175:                regs.fp[reg] = log (10.0);
                   1176:                break;
                   1177:            case 0x32:
                   1178:                regs.fp[reg] = 1.0e0;
                   1179:                break;
                   1180:            case 0x33:
                   1181:                regs.fp[reg] = 1.0e1;
                   1182:                break;
                   1183:            case 0x34:
                   1184:                regs.fp[reg] = 1.0e2;
                   1185:                break;
                   1186:            case 0x35:
                   1187:                regs.fp[reg] = 1.0e4;
                   1188:                break;
                   1189:            case 0x36:
                   1190:                regs.fp[reg] = 1.0e8;
                   1191:                break;
                   1192:            case 0x37:
                   1193:                regs.fp[reg] = 1.0e16;
                   1194:                break;
                   1195:            case 0x38:
                   1196:                regs.fp[reg] = 1.0e32;
                   1197:                break;
                   1198:            case 0x39:
                   1199:                regs.fp[reg] = 1.0e64;
                   1200:                break;
                   1201:            case 0x3a:
                   1202:                regs.fp[reg] = 1.0e128;
                   1203:                break;
                   1204:            case 0x3b:
                   1205:                regs.fp[reg] = 1.0e256;
                   1206:                break;
1.1       root     1207: #if 0
1.1.1.3   root     1208:            case 0x3c:
                   1209:                regs.fp[reg] = 1.0e512;
                   1210:                break;
                   1211:            case 0x3d:
                   1212:                regs.fp[reg] = 1.0e1024;
                   1213:                break;
                   1214:            case 0x3e:
                   1215:                regs.fp[reg] = 1.0e2048;
                   1216:                break;
                   1217:            case 0x3f:
                   1218:                regs.fp[reg] = 1.0e4096;
                   1219:                break;
1.1       root     1220: #endif
1.1.1.3   root     1221:            default:
                   1222:                m68k_setpc (m68k_getpc () - 4);
                   1223:                op_illg (opcode);
                   1224:                break;
                   1225:            }
                   1226:            return;
                   1227:        }
                   1228:        if (get_fp_value (opcode, extra, &src) == 0) {
                   1229:            m68k_setpc (m68k_getpc () - 4);
                   1230:            op_illg (opcode);
                   1231:            return;
                   1232:        }
                   1233:        switch (extra & 0x7f) {
                   1234:        case 0x00:              /* FMOVE */
1.1.1.7   root     1235:        case 0x40:  /* Explicit rounding. This is just a quick fix. Same
                   1236:                     * for all other cases that have three choices */
1.1.1.10  root     1237:        case 0x44:
1.1.1.3   root     1238:            regs.fp[reg] = src;
1.1.1.5   root     1239:            /* Brian King was here.  <ea> to register needs FPSR updated.
                   1240:             * See page 3-73 in Motorola 68K programmers reference manual.
                   1241:             * %%%FPU */
1.1.1.7   root     1242:            if ((extra & 0x44) == 0x40)
                   1243:                regs.fp[reg] = (float)regs.fp[reg];
1.1.1.8   root     1244:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1245:            break;
1.1.1.4   root     1246:        case 0x01:              /* FINT */
1.1.1.5   root     1247:            /* need to take the current rounding mode into account */
1.1.1.12! root     1248:            regs.fp[reg] = toint (src);
1.1.1.4   root     1249:            break;
1.1.1.3   root     1250:        case 0x02:              /* FSINH */
                   1251:            regs.fp[reg] = sinh (src);
1.1.1.8   root     1252:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1253:            break;
                   1254:        case 0x03:              /* FINTRZ */
                   1255:            regs.fp[reg] = (int) src;
1.1.1.8   root     1256:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1257:            break;
                   1258:        case 0x04:              /* FSQRT */
1.1.1.7   root     1259:        case 0x41:
                   1260:        case 0x45:
1.1.1.3   root     1261:            regs.fp[reg] = sqrt (src);
1.1.1.7   root     1262:            if ((extra & 0x44) == 0x40)
                   1263:                regs.fp[reg] = (float)regs.fp[reg];
1.1.1.8   root     1264:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1265:            break;
                   1266:        case 0x06:              /* FLOGNP1 */
                   1267:            regs.fp[reg] = log (src + 1.0);
1.1.1.8   root     1268:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1269:            break;
                   1270:        case 0x08:              /* FETOXM1 */
                   1271:            regs.fp[reg] = exp (src) - 1.0;
1.1.1.8   root     1272:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1273:            break;
                   1274:        case 0x09:              /* FTANH */
                   1275:            regs.fp[reg] = tanh (src);
1.1.1.8   root     1276:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1277:            break;
                   1278:        case 0x0a:              /* FATAN */
                   1279:            regs.fp[reg] = atan (src);
1.1.1.8   root     1280:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1281:            break;
                   1282:        case 0x0c:              /* FASIN */
                   1283:            regs.fp[reg] = asin (src);
1.1.1.8   root     1284:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1285:            break;
                   1286:        case 0x0d:              /* FATANH */
                   1287: #if 1                          /* The BeBox doesn't have atanh, and it isn't in the HPUX libm either */
                   1288:            regs.fp[reg] = log ((1 + src) / (1 - src)) / 2;
1.1       root     1289: #else
1.1.1.3   root     1290:            regs.fp[reg] = atanh (src);
1.1       root     1291: #endif
1.1.1.8   root     1292:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1293:            break;
                   1294:        case 0x0e:              /* FSIN */
                   1295:            regs.fp[reg] = sin (src);
1.1.1.8   root     1296:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1297:            break;
                   1298:        case 0x0f:              /* FTAN */
                   1299:            regs.fp[reg] = tan (src);
1.1.1.8   root     1300:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1301:            break;
                   1302:        case 0x10:              /* FETOX */
                   1303:            regs.fp[reg] = exp (src);
1.1.1.8   root     1304:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1305:            break;
                   1306:        case 0x11:              /* FTWOTOX */
1.1.1.5   root     1307:            regs.fp[reg] = pow (2.0, src);
1.1.1.8   root     1308:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1309:            break;
                   1310:        case 0x12:              /* FTENTOX */
1.1.1.5   root     1311:            regs.fp[reg] = pow (10.0, src);
1.1.1.8   root     1312:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1313:            break;
                   1314:        case 0x14:              /* FLOGN */
                   1315:            regs.fp[reg] = log (src);
1.1.1.8   root     1316:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1317:            break;
                   1318:        case 0x15:              /* FLOG10 */
                   1319:            regs.fp[reg] = log10 (src);
1.1.1.8   root     1320:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1321:            break;
                   1322:        case 0x16:              /* FLOG2 */
                   1323:            regs.fp[reg] = log (src) / log (2.0);
1.1.1.8   root     1324:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1325:            break;
                   1326:        case 0x18:              /* FABS */
1.1.1.7   root     1327:        case 0x58:
                   1328:        case 0x5c:
1.1.1.3   root     1329:            regs.fp[reg] = src < 0 ? -src : src;
1.1.1.7   root     1330:            if ((extra & 0x44) == 0x40)
                   1331:                regs.fp[reg] = (float)regs.fp[reg];
1.1.1.8   root     1332:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1333:            break;
                   1334:        case 0x19:              /* FCOSH */
1.1.1.5   root     1335:            regs.fp[reg] = cosh (src);
1.1.1.8   root     1336:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1337:            break;
                   1338:        case 0x1a:              /* FNEG */
1.1.1.7   root     1339:        case 0x5a:
                   1340:        case 0x5e:
1.1.1.3   root     1341:            regs.fp[reg] = -src;
1.1.1.7   root     1342:            if ((extra & 0x44) == 0x40)
                   1343:                regs.fp[reg] = (float)regs.fp[reg];
1.1.1.8   root     1344:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1345:            break;
                   1346:        case 0x1c:              /* FACOS */
1.1.1.5   root     1347:            regs.fp[reg] = acos (src);
1.1.1.8   root     1348:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1349:            break;
                   1350:        case 0x1d:              /* FCOS */
1.1.1.5   root     1351:            regs.fp[reg] = cos (src);
1.1.1.8   root     1352:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1353:            break;
                   1354:        case 0x1e:              /* FGETEXP */
1.1.1.7   root     1355:        {
                   1356:            int expon;
                   1357:            frexp (src, &expon);
                   1358:            regs.fp[reg] = (double) (expon - 1);
1.1.1.8   root     1359:            MAKE_FPSR (regs.fp[reg]);
1.1.1.7   root     1360:        }
                   1361:        break;
1.1.1.3   root     1362:        case 0x1f:              /* FGETMAN */
1.1.1.7   root     1363:        {
                   1364:            int expon;
                   1365:            regs.fp[reg] = frexp (src, &expon) * 2.0;
1.1.1.8   root     1366:            MAKE_FPSR (regs.fp[reg]);
1.1.1.7   root     1367:        }
                   1368:        break;
1.1.1.3   root     1369:        case 0x20:              /* FDIV */
1.1.1.7   root     1370:        case 0x60:
                   1371:        case 0x64:
1.1.1.3   root     1372:            regs.fp[reg] /= src;
1.1.1.7   root     1373:            if ((extra & 0x44) == 0x40)
                   1374:                regs.fp[reg] = (float)regs.fp[reg];
1.1.1.8   root     1375:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1376:            break;
                   1377:        case 0x21:              /* FMOD */
1.1.1.5   root     1378:            regs.fp[reg] = regs.fp[reg] - (double) ((int) (regs.fp[reg] / src)) * src;
1.1.1.8   root     1379:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1380:            break;
                   1381:        case 0x22:              /* FADD */
1.1.1.7   root     1382:        case 0x62:
                   1383:        case 0x66:
1.1.1.3   root     1384:            regs.fp[reg] += src;
1.1.1.7   root     1385:            if ((extra & 0x44) == 0x40)
                   1386:                regs.fp[reg] = (float)regs.fp[reg];
1.1.1.8   root     1387:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1388:            break;
                   1389:        case 0x23:              /* FMUL */
1.1.1.7   root     1390:        case 0x63:
                   1391:        case 0x67:
1.1.1.3   root     1392:            regs.fp[reg] *= src;
1.1.1.7   root     1393:            if ((extra & 0x44) == 0x40)
                   1394:                regs.fp[reg] = (float)regs.fp[reg];
1.1.1.8   root     1395:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1396:            break;
                   1397:        case 0x24:              /* FSGLDIV */
                   1398:            regs.fp[reg] /= src;
1.1.1.8   root     1399:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1400:            break;
                   1401:        case 0x25:              /* FREM */
1.1.1.5   root     1402:            regs.fp[reg] = regs.fp[reg] - (double) ((int) (regs.fp[reg] / src + 0.5)) * src;
1.1.1.8   root     1403:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1404:            break;
                   1405:        case 0x26:              /* FSCALE */
                   1406:            regs.fp[reg] *= exp (log (2.0) * src);
1.1.1.8   root     1407:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1408:            break;
                   1409:        case 0x27:              /* FSGLMUL */
                   1410:            regs.fp[reg] *= src;
1.1.1.8   root     1411:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1412:            break;
                   1413:        case 0x28:              /* FSUB */
1.1.1.7   root     1414:        case 0x68:
                   1415:        case 0x6c:
1.1.1.3   root     1416:            regs.fp[reg] -= src;
1.1.1.7   root     1417:            if ((extra & 0x44) == 0x40)
                   1418:                regs.fp[reg] = (float)regs.fp[reg];
1.1.1.8   root     1419:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1420:            break;
                   1421:        case 0x30:              /* FSINCOS */
                   1422:        case 0x31:
                   1423:        case 0x32:
                   1424:        case 0x33:
                   1425:        case 0x34:
                   1426:        case 0x35:
                   1427:        case 0x36:
                   1428:        case 0x37:
                   1429:            regs.fp[reg] = sin (src);
1.1.1.5   root     1430:            regs.fp[extra & 7] = cos (src);
1.1.1.8   root     1431:            MAKE_FPSR (regs.fp[reg]);
1.1.1.3   root     1432:            break;
                   1433:        case 0x38:              /* FCMP */
1.1.1.7   root     1434:        {
1.1.1.8   root     1435:            fptype tmp = regs.fp[reg] - src;
                   1436:            regs.fpsr = 0;
                   1437:            MAKE_FPSR (tmp);
1.1.1.7   root     1438:        }
                   1439:        break;
1.1.1.3   root     1440:        case 0x3a:              /* FTST */
1.1.1.8   root     1441:            regs.fpsr = 0;
                   1442:            MAKE_FPSR (src);
1.1.1.3   root     1443:            break;
                   1444:        default:
                   1445:            m68k_setpc (m68k_getpc () - 4);
                   1446:            op_illg (opcode);
                   1447:            break;
                   1448:        }
                   1449:        return;
                   1450:     }
                   1451:     m68k_setpc (m68k_getpc () - 4);
                   1452:     op_illg (opcode);
1.1       root     1453: }
                   1454: 
1.1.1.12! root     1455: const uae_u8 *restore_fpu (const uae_u8 *src)
        !          1456: {
        !          1457:     int i;
        !          1458:     uae_u32 flags;
        !          1459: 
        !          1460:     changed_prefs.fpu_model = currprefs.fpu_model = restore_u32();
        !          1461:     flags = restore_u32 ();
        !          1462:     for (i = 0; i < 8; i++) {
        !          1463:        uae_u32 w1 = restore_u32 ();
        !          1464:        uae_u32 w2 = restore_u32 ();
        !          1465:        uae_u32 w3 = restore_u16 ();
        !          1466:        regs.fp[i] = to_exten (w1, w2, w3);
        !          1467:     }
        !          1468:     regs.fpcr = restore_u32 ();
        !          1469:     regs.fpsr = restore_u32 ();
        !          1470:     regs.fpiar = restore_u32 ();
        !          1471:     if (flags & 0x80000000) {
        !          1472:        restore_u32();
        !          1473:        restore_u32();
        !          1474:     }
        !          1475:     write_log("FPU=%d\n", currprefs.fpu_model);
        !          1476:     return src;
        !          1477: }
        !          1478: 
        !          1479: uae_u8 *save_fpu (int *len, uae_u8 *dstptr)
        !          1480: {
        !          1481:     uae_u8 *dstbak, *dst;
        !          1482:     int i;
        !          1483: 
        !          1484:     *len = 0;
        !          1485:     if (currprefs.fpu_model == 0)
        !          1486:        return 0;
        !          1487:     if (dstptr)
        !          1488:        dstbak = dst = dstptr;
        !          1489:     else
        !          1490:        dstbak = dst = (uae_u8*)malloc(4+4+8*10+4+4+4+4+4);
        !          1491:     save_u32 (currprefs.fpu_model);
        !          1492:     save_u32 (0x80000000);
        !          1493:     for (i = 0; i < 8; i++) {
        !          1494:        uae_u32 w1, w2, w3;
        !          1495:        from_exten (regs.fp[i], &w1, &w2, &w3);
        !          1496:        save_u32 (w1);
        !          1497:        save_u32 (w2);
        !          1498:        save_u16 (w3);
        !          1499:     }
        !          1500:     save_u32 (regs.fpcr);
        !          1501:     save_u32 (regs.fpsr);
        !          1502:     save_u32 (regs.fpiar);
        !          1503:     save_u32 (-1);
        !          1504:     save_u32 (0);
        !          1505:     *len = dst - dstbak;
        !          1506:     return dstbak;
        !          1507: }
1.1       root     1508: #endif

unix.superglobalmegacorp.com

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