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

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

unix.superglobalmegacorp.com

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