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

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

unix.superglobalmegacorp.com

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