home *** CD-ROM | disk | FTP | other *** search
/ Amiga Dream 59 / CDDream59.ISO / Amiga / Emulation / vMac_src.lha / vMac / CPU / fpp.c < prev    next >
C/C++ Source or Header  |  1998-02-11  |  28KB  |  1,139 lines

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