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

unix.superglobalmegacorp.com

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