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

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

unix.superglobalmegacorp.com

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