Annotation of previous/src/uae-cpu/fpp.c, revision 1.1

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

unix.superglobalmegacorp.com

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