Annotation of hatari/src/uae-cpu/fpp.c, revision 1.1.1.6

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.6 ! root       13: const char FPP_rcsid[] = "Hatari $Id: fpp.c,v 1.9 2008/02/09 11:15:16 thothy Exp $";
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;
                    148:     sscanf (str, "%le", &d);
                    149:     return d;
                    150: }
                    151: 
1.1.1.2   root      152: STATIC_INLINE void from_pack (fptype src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
1.1       root      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: 
1.1.1.2   root      198: STATIC_INLINE int get_fp_value (uae_u32 opcode, uae_u16 extra, fptype *src)
1.1       root      199: {
                    200:     uaecptr tmppc;
                    201:     uae_u16 tmp;
                    202:     int size;
                    203:     int mode;
                    204:     int reg;
                    205:     uae_u32 ad = 0;
1.1.1.5   root      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 };
1.1       root      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:
1.1.1.2   root      220:            *src = (fptype) (uae_s8) m68k_dreg (regs, reg);
1.1       root      221:            break;
                    222:        case 4:
1.1.1.2   root      223:            *src = (fptype) (uae_s16) m68k_dreg (regs, reg);
1.1       root      224:            break;
                    225:        case 0:
1.1.1.2   root      226:            *src = (fptype) (uae_s32) m68k_dreg (regs, reg);
1.1       root      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:
1.1.1.2   root      281:        *src = (fptype) (uae_s32) get_long (ad);
1.1       root      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:
1.1.1.2   root      307:        *src = (fptype) (uae_s16) get_word (ad);
1.1       root      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:
1.1.1.2   root      318:        *src = (fptype) (uae_s8) get_byte (ad);
1.1       root      319:        break;
                    320:     default:
                    321:        return 0;
                    322:     }
                    323:     return 1;
                    324: }
                    325: 
1.1.1.2   root      326: STATIC_INLINE int put_fp_value (fptype value, uae_u32 opcode, uae_u16 extra)
1.1       root      327: {
                    328:     uae_u16 tmp;
                    329:     uaecptr tmppc;
                    330:     int size;
                    331:     int mode;
                    332:     int reg;
                    333:     uae_u32 ad;
1.1.1.5   root      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 };
1.1       root      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;
1.1.1.2   root      345:     
1.1       root      346:     switch (mode) {
                    347:     case 0:
                    348:        switch (size) {
                    349:        case 6:
1.1.1.2   root      350:            m68k_dreg (regs, reg) = ((toint(value) & 0xff)
1.1       root      351:                                     | (m68k_dreg (regs, reg) & ~0xff));
                    352:            break;
                    353:        case 4:
1.1.1.2   root      354:            m68k_dreg (regs, reg) = ((toint(value) & 0xffff)
1.1       root      355:                                     | (m68k_dreg (regs, reg) & ~0xffff));
                    356:            break;
                    357:        case 0:
1.1.1.2   root      358:            m68k_dreg (regs, reg) = toint(value);
1.1       root      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:
1.1.1.2   root      413:        put_long (ad,toint(value));
1.1       root      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:
1.1.1.2   root      441:        put_word (ad, (uae_s16) toint(value));
1.1       root      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:
1.1.1.2   root      452:        put_byte (ad, (uae_s8)toint(value));
1.1       root      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: {
1.1.1.2   root      514:     int N = (regs.fp_result<0);
                    515:     int Z = (regs.fp_result==0);
1.1       root      516:     /* int I = (regs.fpsr & 0x2000000) != 0; */
1.1.1.2   root      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;
1.1       root      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:
1.1.1.2   root      584: #if 0
                    585:         return NotANumber || (Z && N); /* This is wrong, compare 0x0c */
                    586: #else
                    587:         return NotANumber || (N && !Z);  
                    588: #endif
1.1       root      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: {
1.1.1.4   root      625:     uae_u32 ad = 0;
1.1       root      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);
                    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: {
1.1.1.4   root      685:     uae_u32 ad = 0;
1.1       root      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: 
1.1.1.6 ! root      699:     if (currprefs.cpu_level == 4) {
1.1       root      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: {
1.1.1.4   root      737:     uae_u32 ad = 0;
1.1       root      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:     }
1.1.1.6 ! root      750:     if (currprefs.cpu_level == 4) {
1.1       root      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;
1.1.1.2   root      810:     fptype src;
1.1       root      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)
1.1.1.2   root      830:                    m68k_dreg (regs, opcode & 7) = get_fpsr ();
1.1       root      831:                if (extra & 0x0400)
                    832:                    m68k_dreg (regs, opcode & 7) = regs.fpiar;
                    833:            } else {
1.1.1.2   root      834:                if (extra & 0x1000) {
1.1       root      835:                    regs.fpcr = m68k_dreg (regs, opcode & 7);
1.1.1.2   root      836:                    native_set_fpucw (regs.fpcr);
                    837:                }
1.1       root      838:                if (extra & 0x0800)
1.1.1.2   root      839:                    set_fpsr (m68k_dreg (regs, opcode & 7));
1.1       root      840:                if (extra & 0x0400)
                    841:                    regs.fpiar = m68k_dreg (regs, opcode & 7);
                    842:            }
1.1.1.2   root      843:        } else if ((opcode & 0x38) == 0x08) {
1.1       root      844:            if (extra & 0x2000) {
                    845:                if (extra & 0x1000)
                    846:                    m68k_areg (regs, opcode & 7) = regs.fpcr;
                    847:                if (extra & 0x0800)
1.1.1.2   root      848:                    m68k_areg (regs, opcode & 7) = get_fpsr ();
1.1       root      849:                if (extra & 0x0400)
                    850:                    m68k_areg (regs, opcode & 7) = regs.fpiar;
                    851:            } else {
1.1.1.2   root      852:                if (extra & 0x1000) {
1.1       root      853:                    regs.fpcr = m68k_areg (regs, opcode & 7);
1.1.1.2   root      854:                    native_set_fpucw (regs.fpcr);
                    855:                }
1.1       root      856:                if (extra & 0x0800)
1.1.1.2   root      857:                    set_fpsr (m68k_areg (regs, opcode & 7));
1.1       root      858:                if (extra & 0x0400)
                    859:                    regs.fpiar = m68k_areg (regs, opcode & 7);
                    860:            }
                    861:        } else if ((opcode & 0x3f) == 0x3c) {
                    862:            if ((extra & 0x2000) == 0) {
1.1.1.2   root      863:                if (extra & 0x1000) {
1.1       root      864:                    regs.fpcr = next_ilong ();
1.1.1.2   root      865:                    native_set_fpucw (regs.fpcr);
                    866:                }
1.1       root      867:                if (extra & 0x0800)
1.1.1.2   root      868:                    set_fpsr (next_ilong ());
1.1       root      869:                if (extra & 0x0400)
                    870:                    regs.fpiar = next_ilong ();
                    871:            }
                    872:        } else if (extra & 0x2000) {
                    873:            /* FMOVEM FPP->memory */
1.1.1.4   root      874:            uae_u32 ad = 0;
1.1       root      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) {
1.1.1.2   root      896:                put_long (ad, get_fpsr());
1.1       root      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 */
1.1.1.4   root      910:            uae_u32 ad = 0;
1.1       root      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);
1.1.1.2   root      920:                native_set_fpucw(regs.fpcr);
1.1       root      921:                ad += 4;
                    922:            }
                    923:            if (extra & 0x0800) {
1.1.1.2   root      924:                set_fpsr(get_long (ad));
1.1       root      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:
1.1.1.2   root      939:     {
1.1.1.4   root      940:        uae_u32 ad = 0;
                    941:        uae_u32 list = 0;
1.1.1.2   root      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;
1.1       root      986:                }
1.1.1.2   root      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);
1.1       root     1036:                }
1.1.1.2   root     1037:                list = fpp_movem_next[list];
1.1       root     1038:            }
1.1.1.2   root     1039:            if ((opcode & 0x38) == 0x18)
                   1040:                m68k_areg (regs, opcode & 7) = ad;
                   1041:            if ((opcode & 0x38) == 0x20)
                   1042:                m68k_areg (regs, opcode & 7) = ad;
1.1       root     1043:        }
1.1.1.2   root     1044:     }
                   1045:     return;
1.1       root     1046:     case 0:
1.1.1.2   root     1047:     case 2: /* Extremely common */
1.1       root     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 */
1.1.1.2   root     1133:        case 0x40:  /* Explicit rounding. This is just a quick fix. Same
                   1134:                     * for all other cases that have three choices */
                   1135:        case 0x44:   
1.1       root     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 */
1.1.1.2   root     1140:            if ((extra & 0x44) == 0x40)
                   1141:                regs.fp[reg] = (float)regs.fp[reg];
                   1142:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1143:            break;
                   1144:        case 0x01:              /* FINT */
                   1145:            /* need to take the current rounding mode into account */
1.1.1.2   root     1146:            regs.fp[reg] = toint(src);
1.1       root     1147:            break;
                   1148:        case 0x02:              /* FSINH */
                   1149:            regs.fp[reg] = sinh (src);
1.1.1.2   root     1150:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1151:            break;
                   1152:        case 0x03:              /* FINTRZ */
                   1153:            regs.fp[reg] = (int) src;
1.1.1.2   root     1154:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1155:            break;
                   1156:        case 0x04:              /* FSQRT */
1.1.1.2   root     1157:        case 0x41:
                   1158:        case 0x45:
1.1       root     1159:            regs.fp[reg] = sqrt (src);
1.1.1.2   root     1160:            if ((extra & 0x44) == 0x40)
                   1161:                regs.fp[reg] = (float)regs.fp[reg];
                   1162:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1163:            break;
                   1164:        case 0x06:              /* FLOGNP1 */
                   1165:            regs.fp[reg] = log (src + 1.0);
1.1.1.2   root     1166:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1167:            break;
                   1168:        case 0x08:              /* FETOXM1 */
                   1169:            regs.fp[reg] = exp (src) - 1.0;
1.1.1.2   root     1170:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1171:            break;
                   1172:        case 0x09:              /* FTANH */
                   1173:            regs.fp[reg] = tanh (src);
1.1.1.2   root     1174:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1175:            break;
                   1176:        case 0x0a:              /* FATAN */
                   1177:            regs.fp[reg] = atan (src);
1.1.1.2   root     1178:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1179:            break;
                   1180:        case 0x0c:              /* FASIN */
                   1181:            regs.fp[reg] = asin (src);
1.1.1.2   root     1182:            MAKE_FPSR (regs.fp[reg]);
1.1       root     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
1.1.1.2   root     1190:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1191:            break;
                   1192:        case 0x0e:              /* FSIN */
                   1193:            regs.fp[reg] = sin (src);
1.1.1.2   root     1194:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1195:            break;
                   1196:        case 0x0f:              /* FTAN */
                   1197:            regs.fp[reg] = tan (src);
1.1.1.2   root     1198:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1199:            break;
                   1200:        case 0x10:              /* FETOX */
                   1201:            regs.fp[reg] = exp (src);
1.1.1.2   root     1202:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1203:            break;
                   1204:        case 0x11:              /* FTWOTOX */
                   1205:            regs.fp[reg] = pow (2.0, src);
1.1.1.2   root     1206:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1207:            break;
                   1208:        case 0x12:              /* FTENTOX */
                   1209:            regs.fp[reg] = pow (10.0, src);
1.1.1.2   root     1210:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1211:            break;
                   1212:        case 0x14:              /* FLOGN */
                   1213:            regs.fp[reg] = log (src);
1.1.1.2   root     1214:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1215:            break;
                   1216:        case 0x15:              /* FLOG10 */
                   1217:            regs.fp[reg] = log10 (src);
1.1.1.2   root     1218:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1219:            break;
                   1220:        case 0x16:              /* FLOG2 */
                   1221:            regs.fp[reg] = log (src) / log (2.0);
1.1.1.2   root     1222:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1223:            break;
                   1224:        case 0x18:              /* FABS */
1.1.1.2   root     1225:        case 0x58:
                   1226:        case 0x5c:
1.1       root     1227:            regs.fp[reg] = src < 0 ? -src : src;
1.1.1.2   root     1228:            if ((extra & 0x44) == 0x40)
                   1229:                regs.fp[reg] = (float)regs.fp[reg];
                   1230:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1231:            break;
                   1232:        case 0x19:              /* FCOSH */
                   1233:            regs.fp[reg] = cosh (src);
1.1.1.2   root     1234:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1235:            break;
                   1236:        case 0x1a:              /* FNEG */
1.1.1.2   root     1237:        case 0x5a:
                   1238:        case 0x5e:
1.1       root     1239:            regs.fp[reg] = -src;
1.1.1.2   root     1240:            if ((extra & 0x44) == 0x40)
                   1241:                regs.fp[reg] = (float)regs.fp[reg];
                   1242:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1243:            break;
                   1244:        case 0x1c:              /* FACOS */
                   1245:            regs.fp[reg] = acos (src);
1.1.1.2   root     1246:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1247:            break;
                   1248:        case 0x1d:              /* FCOS */
                   1249:            regs.fp[reg] = cos (src);
1.1.1.2   root     1250:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1251:            break;
                   1252:        case 0x1e:              /* FGETEXP */
1.1.1.2   root     1253:        {
                   1254:            int expon;
                   1255:            frexp (src, &expon);
                   1256:            regs.fp[reg] = (double) (expon - 1);
                   1257:            MAKE_FPSR (regs.fp[reg]);
                   1258:        }
                   1259:        break;
1.1       root     1260:        case 0x1f:              /* FGETMAN */
1.1.1.2   root     1261:        {
                   1262:            int expon;
                   1263:            regs.fp[reg] = frexp (src, &expon) * 2.0;
                   1264:            MAKE_FPSR (regs.fp[reg]);
                   1265:        }
                   1266:        break;
1.1       root     1267:        case 0x20:              /* FDIV */
1.1.1.2   root     1268:        case 0x60:
                   1269:        case 0x64:
1.1       root     1270:            regs.fp[reg] /= src;
1.1.1.2   root     1271:            if ((extra & 0x44) == 0x40)
                   1272:                regs.fp[reg] = (float)regs.fp[reg];
                   1273:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1274:            break;
                   1275:        case 0x21:              /* FMOD */
                   1276:            regs.fp[reg] = regs.fp[reg] - (double) ((int) (regs.fp[reg] / src)) * src;
1.1.1.2   root     1277:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1278:            break;
                   1279:        case 0x22:              /* FADD */
1.1.1.2   root     1280:        case 0x62:
                   1281:        case 0x66:
1.1       root     1282:            regs.fp[reg] += src;
1.1.1.2   root     1283:            if ((extra & 0x44) == 0x40)
                   1284:                regs.fp[reg] = (float)regs.fp[reg];
                   1285:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1286:            break;
                   1287:        case 0x23:              /* FMUL */
1.1.1.2   root     1288:        case 0x63:
                   1289:        case 0x67:
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 0x24:              /* FSGLDIV */
                   1296:            regs.fp[reg] /= src;
1.1.1.2   root     1297:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1298:            break;
                   1299:        case 0x25:              /* FREM */
                   1300:            regs.fp[reg] = regs.fp[reg] - (double) ((int) (regs.fp[reg] / src + 0.5)) * src;
1.1.1.2   root     1301:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1302:            break;
                   1303:        case 0x26:              /* FSCALE */
                   1304:            regs.fp[reg] *= exp (log (2.0) * src);
1.1.1.2   root     1305:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1306:            break;
                   1307:        case 0x27:              /* FSGLMUL */
                   1308:            regs.fp[reg] *= src;
1.1.1.2   root     1309:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1310:            break;
                   1311:        case 0x28:              /* FSUB */
1.1.1.2   root     1312:        case 0x68:
                   1313:        case 0x6c:
1.1       root     1314:            regs.fp[reg] -= src;
1.1.1.2   root     1315:            if ((extra & 0x44) == 0x40)
                   1316:                regs.fp[reg] = (float)regs.fp[reg];
                   1317:            MAKE_FPSR (regs.fp[reg]);
1.1       root     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);
1.1.1.2   root     1329:            MAKE_FPSR (regs.fp[reg]);
1.1       root     1330:            break;
                   1331:        case 0x38:              /* FCMP */
1.1.1.2   root     1332:        {
                   1333:            fptype tmp = regs.fp[reg] - src;
                   1334:            regs.fpsr = 0;
                   1335:            MAKE_FPSR (tmp);
                   1336:        }
                   1337:        break;
1.1       root     1338:        case 0x3a:              /* FTST */
1.1.1.2   root     1339:            regs.fpsr = 0;
                   1340:            MAKE_FPSR (src);
1.1       root     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
1.1.1.6 ! root     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.