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

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

unix.superglobalmegacorp.com

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