13ebdd119Saurel32 /*
23ebdd119Saurel32 NetWinder Floating Point Emulator
33ebdd119Saurel32 (c) Rebel.COM, 1998,1999
43ebdd119Saurel32
53ebdd119Saurel32 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
63ebdd119Saurel32
73ebdd119Saurel32 This program is free software; you can redistribute it and/or modify
83ebdd119Saurel32 it under the terms of the GNU General Public License as published by
93ebdd119Saurel32 the Free Software Foundation; either version 2 of the License, or
103ebdd119Saurel32 (at your option) any later version.
113ebdd119Saurel32
123ebdd119Saurel32 This program is distributed in the hope that it will be useful,
133ebdd119Saurel32 but WITHOUT ANY WARRANTY; without even the implied warranty of
143ebdd119Saurel32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
153ebdd119Saurel32 GNU General Public License for more details.
163ebdd119Saurel32
173ebdd119Saurel32 You should have received a copy of the GNU General Public License
1870539e18SBlue Swirl along with this program; if not, see <http://www.gnu.org/licenses/>.
193ebdd119Saurel32 */
203ebdd119Saurel32
21d39594e9SPeter Maydell #include "qemu/osdep.h"
223ebdd119Saurel32 #include "fpa11.h"
236b4c305cSPaolo Bonzini #include "fpu/softfloat.h"
243ebdd119Saurel32 #include "fpopcode.h"
253ebdd119Saurel32
263ebdd119Saurel32 float64 float64_exp(float64 Fm);
273ebdd119Saurel32 float64 float64_ln(float64 Fm);
283ebdd119Saurel32 float64 float64_sin(float64 rFm);
293ebdd119Saurel32 float64 float64_cos(float64 rFm);
303ebdd119Saurel32 float64 float64_arcsin(float64 rFm);
313ebdd119Saurel32 float64 float64_arctan(float64 rFm);
323ebdd119Saurel32 float64 float64_log(float64 rFm);
333ebdd119Saurel32 float64 float64_tan(float64 rFm);
343ebdd119Saurel32 float64 float64_arccos(float64 rFm);
353ebdd119Saurel32 float64 float64_pow(float64 rFn,float64 rFm);
363ebdd119Saurel32 float64 float64_pol(float64 rFn,float64 rFm);
373ebdd119Saurel32
DoubleCPDO(const unsigned int opcode)383ebdd119Saurel32 unsigned int DoubleCPDO(const unsigned int opcode)
393ebdd119Saurel32 {
403ebdd119Saurel32 FPA11 *fpa11 = GET_FPA11();
413ebdd119Saurel32 float64 rFm, rFn = float64_zero;
423ebdd119Saurel32 unsigned int Fd, Fm, Fn, nRc = 1;
433ebdd119Saurel32
443ebdd119Saurel32 //printk("DoubleCPDO(0x%08x)\n",opcode);
453ebdd119Saurel32
463ebdd119Saurel32 Fm = getFm(opcode);
473ebdd119Saurel32 if (CONSTANT_FM(opcode))
483ebdd119Saurel32 {
493ebdd119Saurel32 rFm = getDoubleConstant(Fm);
503ebdd119Saurel32 }
513ebdd119Saurel32 else
523ebdd119Saurel32 {
533ebdd119Saurel32 switch (fpa11->fType[Fm])
543ebdd119Saurel32 {
553ebdd119Saurel32 case typeSingle:
563ebdd119Saurel32 rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status);
573ebdd119Saurel32 break;
583ebdd119Saurel32
593ebdd119Saurel32 case typeDouble:
603ebdd119Saurel32 rFm = fpa11->fpreg[Fm].fDouble;
613ebdd119Saurel32 break;
623ebdd119Saurel32
633ebdd119Saurel32 case typeExtended:
643ebdd119Saurel32 // !! patb
653ebdd119Saurel32 //printk("not implemented! why not?\n");
663ebdd119Saurel32 //!! ScottB
673ebdd119Saurel32 // should never get here, if extended involved
683ebdd119Saurel32 // then other operand should be promoted then
693ebdd119Saurel32 // ExtendedCPDO called.
703ebdd119Saurel32 break;
713ebdd119Saurel32
723ebdd119Saurel32 default: return 0;
733ebdd119Saurel32 }
743ebdd119Saurel32 }
753ebdd119Saurel32
763ebdd119Saurel32 if (!MONADIC_INSTRUCTION(opcode))
773ebdd119Saurel32 {
783ebdd119Saurel32 Fn = getFn(opcode);
793ebdd119Saurel32 switch (fpa11->fType[Fn])
803ebdd119Saurel32 {
813ebdd119Saurel32 case typeSingle:
823ebdd119Saurel32 rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
833ebdd119Saurel32 break;
843ebdd119Saurel32
853ebdd119Saurel32 case typeDouble:
863ebdd119Saurel32 rFn = fpa11->fpreg[Fn].fDouble;
873ebdd119Saurel32 break;
883ebdd119Saurel32
893ebdd119Saurel32 default: return 0;
903ebdd119Saurel32 }
913ebdd119Saurel32 }
923ebdd119Saurel32
933ebdd119Saurel32 Fd = getFd(opcode);
943ebdd119Saurel32 /* !! this switch isn't optimized; better (opcode & MASK_ARITHMETIC_OPCODE)>>24, sort of */
953ebdd119Saurel32 switch (opcode & MASK_ARITHMETIC_OPCODE)
963ebdd119Saurel32 {
973ebdd119Saurel32 /* dyadic opcodes */
983ebdd119Saurel32 case ADF_CODE:
993ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_add(rFn,rFm, &fpa11->fp_status);
1003ebdd119Saurel32 break;
1013ebdd119Saurel32
1023ebdd119Saurel32 case MUF_CODE:
1033ebdd119Saurel32 case FML_CODE:
1043ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm, &fpa11->fp_status);
1053ebdd119Saurel32 break;
1063ebdd119Saurel32
1073ebdd119Saurel32 case SUF_CODE:
1083ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm, &fpa11->fp_status);
1093ebdd119Saurel32 break;
1103ebdd119Saurel32
1113ebdd119Saurel32 case RSF_CODE:
1123ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn, &fpa11->fp_status);
1133ebdd119Saurel32 break;
1143ebdd119Saurel32
1153ebdd119Saurel32 case DVF_CODE:
1163ebdd119Saurel32 case FDV_CODE:
1173ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm, &fpa11->fp_status);
1183ebdd119Saurel32 break;
1193ebdd119Saurel32
1203ebdd119Saurel32 case RDF_CODE:
1213ebdd119Saurel32 case FRD_CODE:
1223ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn, &fpa11->fp_status);
1233ebdd119Saurel32 break;
1243ebdd119Saurel32
1253ebdd119Saurel32 #if 0
1263ebdd119Saurel32 case POW_CODE:
1273ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_pow(rFn,rFm);
1283ebdd119Saurel32 break;
1293ebdd119Saurel32
1303ebdd119Saurel32 case RPW_CODE:
1313ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_pow(rFm,rFn);
1323ebdd119Saurel32 break;
1333ebdd119Saurel32 #endif
1343ebdd119Saurel32
1353ebdd119Saurel32 case RMF_CODE:
1363ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_rem(rFn,rFm, &fpa11->fp_status);
1373ebdd119Saurel32 break;
1383ebdd119Saurel32
1393ebdd119Saurel32 #if 0
1403ebdd119Saurel32 case POL_CODE:
1413ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_pol(rFn,rFm);
1423ebdd119Saurel32 break;
1433ebdd119Saurel32 #endif
1443ebdd119Saurel32
1453ebdd119Saurel32 /* monadic opcodes */
1463ebdd119Saurel32 case MVF_CODE:
1473ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = rFm;
1483ebdd119Saurel32 break;
1493ebdd119Saurel32
1503ebdd119Saurel32 case MNF_CODE:
1513ebdd119Saurel32 {
1523ebdd119Saurel32 unsigned int *p = (unsigned int*)&rFm;
153*e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN
1543ebdd119Saurel32 p[0] ^= 0x80000000;
1553ebdd119Saurel32 #else
1563ebdd119Saurel32 p[1] ^= 0x80000000;
1573ebdd119Saurel32 #endif
1583ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = rFm;
1593ebdd119Saurel32 }
1603ebdd119Saurel32 break;
1613ebdd119Saurel32
1623ebdd119Saurel32 case ABS_CODE:
1633ebdd119Saurel32 {
1643ebdd119Saurel32 unsigned int *p = (unsigned int*)&rFm;
165*e03b5686SMarc-André Lureau #if HOST_BIG_ENDIAN
1663ebdd119Saurel32 p[0] &= 0x7fffffff;
1673ebdd119Saurel32 #else
1683ebdd119Saurel32 p[1] &= 0x7fffffff;
1693ebdd119Saurel32 #endif
1703ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = rFm;
1713ebdd119Saurel32 }
1723ebdd119Saurel32 break;
1733ebdd119Saurel32
1743ebdd119Saurel32 case RND_CODE:
1753ebdd119Saurel32 case URD_CODE:
1763ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_round_to_int(rFm, &fpa11->fp_status);
1773ebdd119Saurel32 break;
1783ebdd119Saurel32
1793ebdd119Saurel32 case SQT_CODE:
1803ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm, &fpa11->fp_status);
1813ebdd119Saurel32 break;
1823ebdd119Saurel32
1833ebdd119Saurel32 #if 0
1843ebdd119Saurel32 case LOG_CODE:
1853ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_log(rFm);
1863ebdd119Saurel32 break;
1873ebdd119Saurel32
1883ebdd119Saurel32 case LGN_CODE:
1893ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_ln(rFm);
1903ebdd119Saurel32 break;
1913ebdd119Saurel32
1923ebdd119Saurel32 case EXP_CODE:
1933ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_exp(rFm);
1943ebdd119Saurel32 break;
1953ebdd119Saurel32
1963ebdd119Saurel32 case SIN_CODE:
1973ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_sin(rFm);
1983ebdd119Saurel32 break;
1993ebdd119Saurel32
2003ebdd119Saurel32 case COS_CODE:
2013ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_cos(rFm);
2023ebdd119Saurel32 break;
2033ebdd119Saurel32
2043ebdd119Saurel32 case TAN_CODE:
2053ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_tan(rFm);
2063ebdd119Saurel32 break;
2073ebdd119Saurel32
2083ebdd119Saurel32 case ASN_CODE:
2093ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_arcsin(rFm);
2103ebdd119Saurel32 break;
2113ebdd119Saurel32
2123ebdd119Saurel32 case ACS_CODE:
2133ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_arccos(rFm);
2143ebdd119Saurel32 break;
2153ebdd119Saurel32
2163ebdd119Saurel32 case ATN_CODE:
2173ebdd119Saurel32 fpa11->fpreg[Fd].fDouble = float64_arctan(rFm);
2183ebdd119Saurel32 break;
2193ebdd119Saurel32 #endif
2203ebdd119Saurel32
2213ebdd119Saurel32 case NRM_CODE:
2223ebdd119Saurel32 break;
2233ebdd119Saurel32
2243ebdd119Saurel32 default:
2253ebdd119Saurel32 {
2263ebdd119Saurel32 nRc = 0;
2273ebdd119Saurel32 }
2283ebdd119Saurel32 }
2293ebdd119Saurel32
2303ebdd119Saurel32 if (0 != nRc) fpa11->fType[Fd] = typeDouble;
2313ebdd119Saurel32 return nRc;
2323ebdd119Saurel32 }
2333ebdd119Saurel32
2343ebdd119Saurel32 #if 0
2353ebdd119Saurel32 float64 float64_exp(float64 rFm)
2363ebdd119Saurel32 {
2373ebdd119Saurel32 return rFm;
2383ebdd119Saurel32 //series
2393ebdd119Saurel32 }
2403ebdd119Saurel32
2413ebdd119Saurel32 float64 float64_ln(float64 rFm)
2423ebdd119Saurel32 {
2433ebdd119Saurel32 return rFm;
2443ebdd119Saurel32 //series
2453ebdd119Saurel32 }
2463ebdd119Saurel32
2473ebdd119Saurel32 float64 float64_sin(float64 rFm)
2483ebdd119Saurel32 {
2493ebdd119Saurel32 return rFm;
2503ebdd119Saurel32 //series
2513ebdd119Saurel32 }
2523ebdd119Saurel32
2533ebdd119Saurel32 float64 float64_cos(float64 rFm)
2543ebdd119Saurel32 {
2553ebdd119Saurel32 return rFm;
2563ebdd119Saurel32 //series
2573ebdd119Saurel32 }
2583ebdd119Saurel32
2593ebdd119Saurel32 #if 0
2603ebdd119Saurel32 float64 float64_arcsin(float64 rFm)
2613ebdd119Saurel32 {
2623ebdd119Saurel32 //series
2633ebdd119Saurel32 }
2643ebdd119Saurel32
2653ebdd119Saurel32 float64 float64_arctan(float64 rFm)
2663ebdd119Saurel32 {
2673ebdd119Saurel32 //series
2683ebdd119Saurel32 }
2693ebdd119Saurel32 #endif
2703ebdd119Saurel32
2713ebdd119Saurel32 float64 float64_log(float64 rFm)
2723ebdd119Saurel32 {
2733ebdd119Saurel32 return float64_div(float64_ln(rFm),getDoubleConstant(7));
2743ebdd119Saurel32 }
2753ebdd119Saurel32
2763ebdd119Saurel32 float64 float64_tan(float64 rFm)
2773ebdd119Saurel32 {
2783ebdd119Saurel32 return float64_div(float64_sin(rFm),float64_cos(rFm));
2793ebdd119Saurel32 }
2803ebdd119Saurel32
2813ebdd119Saurel32 float64 float64_arccos(float64 rFm)
2823ebdd119Saurel32 {
2833ebdd119Saurel32 return rFm;
2843ebdd119Saurel32 //return float64_sub(halfPi,float64_arcsin(rFm));
2853ebdd119Saurel32 }
2863ebdd119Saurel32
2873ebdd119Saurel32 float64 float64_pow(float64 rFn,float64 rFm)
2883ebdd119Saurel32 {
2893ebdd119Saurel32 return float64_exp(float64_mul(rFm,float64_ln(rFn)));
2903ebdd119Saurel32 }
2913ebdd119Saurel32
2923ebdd119Saurel32 float64 float64_pol(float64 rFn,float64 rFm)
2933ebdd119Saurel32 {
2943ebdd119Saurel32 return float64_arctan(float64_div(rFn,rFm));
2953ebdd119Saurel32 }
2963ebdd119Saurel32 #endif
297