xref: /openbmc/qemu/linux-user/arm/nwfpe/extended_cpdo.c (revision d39594e9d96b4f0be27bdbc02a5b1816b72fe1d2)
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 
21*d39594e9SPeter Maydell #include "qemu/osdep.h"
223ebdd119Saurel32 #include "fpa11.h"
236b4c305cSPaolo Bonzini #include "fpu/softfloat.h"
243ebdd119Saurel32 #include "fpopcode.h"
253ebdd119Saurel32 
263ebdd119Saurel32 floatx80 floatx80_exp(floatx80 Fm);
273ebdd119Saurel32 floatx80 floatx80_ln(floatx80 Fm);
283ebdd119Saurel32 floatx80 floatx80_sin(floatx80 rFm);
293ebdd119Saurel32 floatx80 floatx80_cos(floatx80 rFm);
303ebdd119Saurel32 floatx80 floatx80_arcsin(floatx80 rFm);
313ebdd119Saurel32 floatx80 floatx80_arctan(floatx80 rFm);
323ebdd119Saurel32 floatx80 floatx80_log(floatx80 rFm);
333ebdd119Saurel32 floatx80 floatx80_tan(floatx80 rFm);
343ebdd119Saurel32 floatx80 floatx80_arccos(floatx80 rFm);
353ebdd119Saurel32 floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm);
363ebdd119Saurel32 floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm);
373ebdd119Saurel32 
ExtendedCPDO(const unsigned int opcode)383ebdd119Saurel32 unsigned int ExtendedCPDO(const unsigned int opcode)
393ebdd119Saurel32 {
403ebdd119Saurel32    FPA11 *fpa11 = GET_FPA11();
413ebdd119Saurel32    floatx80 rFm, rFn;
423ebdd119Saurel32    unsigned int Fd, Fm, Fn, nRc = 1;
433ebdd119Saurel32 
443ebdd119Saurel32    //printk("ExtendedCPDO(0x%08x)\n",opcode);
453ebdd119Saurel32 
463ebdd119Saurel32    Fm = getFm(opcode);
473ebdd119Saurel32    if (CONSTANT_FM(opcode))
483ebdd119Saurel32    {
493ebdd119Saurel32      rFm = getExtendedConstant(Fm);
503ebdd119Saurel32    }
513ebdd119Saurel32    else
523ebdd119Saurel32    {
533ebdd119Saurel32      switch (fpa11->fType[Fm])
543ebdd119Saurel32      {
553ebdd119Saurel32         case typeSingle:
563ebdd119Saurel32           rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status);
573ebdd119Saurel32         break;
583ebdd119Saurel32 
593ebdd119Saurel32         case typeDouble:
603ebdd119Saurel32           rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble, &fpa11->fp_status);
613ebdd119Saurel32         break;
623ebdd119Saurel32 
633ebdd119Saurel32         case typeExtended:
643ebdd119Saurel32           rFm = fpa11->fpreg[Fm].fExtended;
653ebdd119Saurel32         break;
663ebdd119Saurel32 
673ebdd119Saurel32         default: return 0;
683ebdd119Saurel32      }
693ebdd119Saurel32    }
703ebdd119Saurel32 
713ebdd119Saurel32    if (!MONADIC_INSTRUCTION(opcode))
723ebdd119Saurel32    {
733ebdd119Saurel32       Fn = getFn(opcode);
743ebdd119Saurel32       switch (fpa11->fType[Fn])
753ebdd119Saurel32       {
763ebdd119Saurel32         case typeSingle:
773ebdd119Saurel32           rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
783ebdd119Saurel32         break;
793ebdd119Saurel32 
803ebdd119Saurel32         case typeDouble:
813ebdd119Saurel32           rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
823ebdd119Saurel32         break;
833ebdd119Saurel32 
843ebdd119Saurel32         case typeExtended:
853ebdd119Saurel32           rFn = fpa11->fpreg[Fn].fExtended;
863ebdd119Saurel32         break;
873ebdd119Saurel32 
883ebdd119Saurel32         default: return 0;
893ebdd119Saurel32       }
903ebdd119Saurel32    }
913ebdd119Saurel32 
923ebdd119Saurel32    Fd = getFd(opcode);
933ebdd119Saurel32    switch (opcode & MASK_ARITHMETIC_OPCODE)
943ebdd119Saurel32    {
953ebdd119Saurel32       /* dyadic opcodes */
963ebdd119Saurel32       case ADF_CODE:
973ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_add(rFn,rFm, &fpa11->fp_status);
983ebdd119Saurel32       break;
993ebdd119Saurel32 
1003ebdd119Saurel32       case MUF_CODE:
1013ebdd119Saurel32       case FML_CODE:
1023ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_mul(rFn,rFm, &fpa11->fp_status);
1033ebdd119Saurel32       break;
1043ebdd119Saurel32 
1053ebdd119Saurel32       case SUF_CODE:
1063ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_sub(rFn,rFm, &fpa11->fp_status);
1073ebdd119Saurel32       break;
1083ebdd119Saurel32 
1093ebdd119Saurel32       case RSF_CODE:
1103ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_sub(rFm,rFn, &fpa11->fp_status);
1113ebdd119Saurel32       break;
1123ebdd119Saurel32 
1133ebdd119Saurel32       case DVF_CODE:
1143ebdd119Saurel32       case FDV_CODE:
1153ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_div(rFn,rFm, &fpa11->fp_status);
1163ebdd119Saurel32       break;
1173ebdd119Saurel32 
1183ebdd119Saurel32       case RDF_CODE:
1193ebdd119Saurel32       case FRD_CODE:
1203ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_div(rFm,rFn, &fpa11->fp_status);
1213ebdd119Saurel32       break;
1223ebdd119Saurel32 
1233ebdd119Saurel32 #if 0
1243ebdd119Saurel32       case POW_CODE:
1253ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_pow(rFn,rFm);
1263ebdd119Saurel32       break;
1273ebdd119Saurel32 
1283ebdd119Saurel32       case RPW_CODE:
1293ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_pow(rFm,rFn);
1303ebdd119Saurel32       break;
1313ebdd119Saurel32 #endif
1323ebdd119Saurel32 
1333ebdd119Saurel32       case RMF_CODE:
1343ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_rem(rFn,rFm, &fpa11->fp_status);
1353ebdd119Saurel32       break;
1363ebdd119Saurel32 
1373ebdd119Saurel32 #if 0
1383ebdd119Saurel32       case POL_CODE:
1393ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_pol(rFn,rFm);
1403ebdd119Saurel32       break;
1413ebdd119Saurel32 #endif
1423ebdd119Saurel32 
1433ebdd119Saurel32       /* monadic opcodes */
1443ebdd119Saurel32       case MVF_CODE:
1453ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = rFm;
1463ebdd119Saurel32       break;
1473ebdd119Saurel32 
1483ebdd119Saurel32       case MNF_CODE:
1493ebdd119Saurel32          rFm.high ^= 0x8000;
1503ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = rFm;
1513ebdd119Saurel32       break;
1523ebdd119Saurel32 
1533ebdd119Saurel32       case ABS_CODE:
1543ebdd119Saurel32          rFm.high &= 0x7fff;
1553ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = rFm;
1563ebdd119Saurel32       break;
1573ebdd119Saurel32 
1583ebdd119Saurel32       case RND_CODE:
1593ebdd119Saurel32       case URD_CODE:
1603ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_round_to_int(rFm, &fpa11->fp_status);
1613ebdd119Saurel32       break;
1623ebdd119Saurel32 
1633ebdd119Saurel32       case SQT_CODE:
1643ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_sqrt(rFm, &fpa11->fp_status);
1653ebdd119Saurel32       break;
1663ebdd119Saurel32 
1673ebdd119Saurel32 #if 0
1683ebdd119Saurel32       case LOG_CODE:
1693ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_log(rFm);
1703ebdd119Saurel32       break;
1713ebdd119Saurel32 
1723ebdd119Saurel32       case LGN_CODE:
1733ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_ln(rFm);
1743ebdd119Saurel32       break;
1753ebdd119Saurel32 
1763ebdd119Saurel32       case EXP_CODE:
1773ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_exp(rFm);
1783ebdd119Saurel32       break;
1793ebdd119Saurel32 
1803ebdd119Saurel32       case SIN_CODE:
1813ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_sin(rFm);
1823ebdd119Saurel32       break;
1833ebdd119Saurel32 
1843ebdd119Saurel32       case COS_CODE:
1853ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_cos(rFm);
1863ebdd119Saurel32       break;
1873ebdd119Saurel32 
1883ebdd119Saurel32       case TAN_CODE:
1893ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_tan(rFm);
1903ebdd119Saurel32       break;
1913ebdd119Saurel32 
1923ebdd119Saurel32       case ASN_CODE:
1933ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_arcsin(rFm);
1943ebdd119Saurel32       break;
1953ebdd119Saurel32 
1963ebdd119Saurel32       case ACS_CODE:
1973ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_arccos(rFm);
1983ebdd119Saurel32       break;
1993ebdd119Saurel32 
2003ebdd119Saurel32       case ATN_CODE:
2013ebdd119Saurel32          fpa11->fpreg[Fd].fExtended = floatx80_arctan(rFm);
2023ebdd119Saurel32       break;
2033ebdd119Saurel32 #endif
2043ebdd119Saurel32 
2053ebdd119Saurel32       case NRM_CODE:
2063ebdd119Saurel32       break;
2073ebdd119Saurel32 
2083ebdd119Saurel32       default:
2093ebdd119Saurel32       {
2103ebdd119Saurel32         nRc = 0;
2113ebdd119Saurel32       }
2123ebdd119Saurel32    }
2133ebdd119Saurel32 
2143ebdd119Saurel32    if (0 != nRc) fpa11->fType[Fd] = typeExtended;
2153ebdd119Saurel32    return nRc;
2163ebdd119Saurel32 }
2173ebdd119Saurel32 
2183ebdd119Saurel32 #if 0
2193ebdd119Saurel32 floatx80 floatx80_exp(floatx80 Fm)
2203ebdd119Saurel32 {
2213ebdd119Saurel32 //series
2223ebdd119Saurel32 }
2233ebdd119Saurel32 
2243ebdd119Saurel32 floatx80 floatx80_ln(floatx80 Fm)
2253ebdd119Saurel32 {
2263ebdd119Saurel32 //series
2273ebdd119Saurel32 }
2283ebdd119Saurel32 
2293ebdd119Saurel32 floatx80 floatx80_sin(floatx80 rFm)
2303ebdd119Saurel32 {
2313ebdd119Saurel32 //series
2323ebdd119Saurel32 }
2333ebdd119Saurel32 
2343ebdd119Saurel32 floatx80 floatx80_cos(floatx80 rFm)
2353ebdd119Saurel32 {
2363ebdd119Saurel32 //series
2373ebdd119Saurel32 }
2383ebdd119Saurel32 
2393ebdd119Saurel32 floatx80 floatx80_arcsin(floatx80 rFm)
2403ebdd119Saurel32 {
2413ebdd119Saurel32 //series
2423ebdd119Saurel32 }
2433ebdd119Saurel32 
2443ebdd119Saurel32 floatx80 floatx80_arctan(floatx80 rFm)
2453ebdd119Saurel32 {
2463ebdd119Saurel32   //series
2473ebdd119Saurel32 }
2483ebdd119Saurel32 
2493ebdd119Saurel32 floatx80 floatx80_log(floatx80 rFm)
2503ebdd119Saurel32 {
2513ebdd119Saurel32   return floatx80_div(floatx80_ln(rFm),getExtendedConstant(7));
2523ebdd119Saurel32 }
2533ebdd119Saurel32 
2543ebdd119Saurel32 floatx80 floatx80_tan(floatx80 rFm)
2553ebdd119Saurel32 {
2563ebdd119Saurel32   return floatx80_div(floatx80_sin(rFm),floatx80_cos(rFm));
2573ebdd119Saurel32 }
2583ebdd119Saurel32 
2593ebdd119Saurel32 floatx80 floatx80_arccos(floatx80 rFm)
2603ebdd119Saurel32 {
2613ebdd119Saurel32    //return floatx80_sub(halfPi,floatx80_arcsin(rFm));
2623ebdd119Saurel32 }
2633ebdd119Saurel32 
2643ebdd119Saurel32 floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm)
2653ebdd119Saurel32 {
2663ebdd119Saurel32   return floatx80_exp(floatx80_mul(rFm,floatx80_ln(rFn)));
2673ebdd119Saurel32 }
2683ebdd119Saurel32 
2693ebdd119Saurel32 floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm)
2703ebdd119Saurel32 {
2713ebdd119Saurel32   return floatx80_arctan(floatx80_div(rFn,rFm));
2723ebdd119Saurel32 }
2733ebdd119Saurel32 #endif
274