| /* | 
 |     NetWinder Floating Point Emulator | 
 |     (c) Rebel.COM, 1998,1999 | 
 |  | 
 |     Direct questions, comments to Scott Bambrough <scottb@netwinder.org> | 
 |  | 
 |     This program is free software; you can redistribute it and/or modify | 
 |     it under the terms of the GNU General Public License as published by | 
 |     the Free Software Foundation; either version 2 of the License, or | 
 |     (at your option) any later version. | 
 |  | 
 |     This program is distributed in the hope that it will be useful, | 
 |     but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |     GNU General Public License for more details. | 
 |  | 
 |     You should have received a copy of the GNU General Public License | 
 |     along with this program; if not, see <http://www.gnu.org/licenses/>. | 
 | */ | 
 |  | 
 | #include "fpa11.h" | 
 | #include "fpu/softfloat.h" | 
 | #include "fpopcode.h" | 
 |  | 
 | floatx80 floatx80_exp(floatx80 Fm); | 
 | floatx80 floatx80_ln(floatx80 Fm); | 
 | floatx80 floatx80_sin(floatx80 rFm); | 
 | floatx80 floatx80_cos(floatx80 rFm); | 
 | floatx80 floatx80_arcsin(floatx80 rFm); | 
 | floatx80 floatx80_arctan(floatx80 rFm); | 
 | floatx80 floatx80_log(floatx80 rFm); | 
 | floatx80 floatx80_tan(floatx80 rFm); | 
 | floatx80 floatx80_arccos(floatx80 rFm); | 
 | floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm); | 
 | floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm); | 
 |  | 
 | unsigned int ExtendedCPDO(const unsigned int opcode) | 
 | { | 
 |    FPA11 *fpa11 = GET_FPA11(); | 
 |    floatx80 rFm, rFn; | 
 |    unsigned int Fd, Fm, Fn, nRc = 1; | 
 |  | 
 |    //printk("ExtendedCPDO(0x%08x)\n",opcode); | 
 |  | 
 |    Fm = getFm(opcode); | 
 |    if (CONSTANT_FM(opcode)) | 
 |    { | 
 |      rFm = getExtendedConstant(Fm); | 
 |    } | 
 |    else | 
 |    { | 
 |      switch (fpa11->fType[Fm]) | 
 |      { | 
 |         case typeSingle: | 
 |           rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status); | 
 |         break; | 
 |  | 
 |         case typeDouble: | 
 |           rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble, &fpa11->fp_status); | 
 |         break; | 
 |  | 
 |         case typeExtended: | 
 |           rFm = fpa11->fpreg[Fm].fExtended; | 
 |         break; | 
 |  | 
 |         default: return 0; | 
 |      } | 
 |    } | 
 |  | 
 |    if (!MONADIC_INSTRUCTION(opcode)) | 
 |    { | 
 |       Fn = getFn(opcode); | 
 |       switch (fpa11->fType[Fn]) | 
 |       { | 
 |         case typeSingle: | 
 |           rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status); | 
 |         break; | 
 |  | 
 |         case typeDouble: | 
 |           rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status); | 
 |         break; | 
 |  | 
 |         case typeExtended: | 
 |           rFn = fpa11->fpreg[Fn].fExtended; | 
 |         break; | 
 |  | 
 |         default: return 0; | 
 |       } | 
 |    } | 
 |  | 
 |    Fd = getFd(opcode); | 
 |    switch (opcode & MASK_ARITHMETIC_OPCODE) | 
 |    { | 
 |       /* dyadic opcodes */ | 
 |       case ADF_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_add(rFn,rFm, &fpa11->fp_status); | 
 |       break; | 
 |  | 
 |       case MUF_CODE: | 
 |       case FML_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_mul(rFn,rFm, &fpa11->fp_status); | 
 |       break; | 
 |  | 
 |       case SUF_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_sub(rFn,rFm, &fpa11->fp_status); | 
 |       break; | 
 |  | 
 |       case RSF_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_sub(rFm,rFn, &fpa11->fp_status); | 
 |       break; | 
 |  | 
 |       case DVF_CODE: | 
 |       case FDV_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_div(rFn,rFm, &fpa11->fp_status); | 
 |       break; | 
 |  | 
 |       case RDF_CODE: | 
 |       case FRD_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_div(rFm,rFn, &fpa11->fp_status); | 
 |       break; | 
 |  | 
 | #if 0 | 
 |       case POW_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_pow(rFn,rFm); | 
 |       break; | 
 |  | 
 |       case RPW_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_pow(rFm,rFn); | 
 |       break; | 
 | #endif | 
 |  | 
 |       case RMF_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_rem(rFn,rFm, &fpa11->fp_status); | 
 |       break; | 
 |  | 
 | #if 0 | 
 |       case POL_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_pol(rFn,rFm); | 
 |       break; | 
 | #endif | 
 |  | 
 |       /* monadic opcodes */ | 
 |       case MVF_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = rFm; | 
 |       break; | 
 |  | 
 |       case MNF_CODE: | 
 |          rFm.high ^= 0x8000; | 
 |          fpa11->fpreg[Fd].fExtended = rFm; | 
 |       break; | 
 |  | 
 |       case ABS_CODE: | 
 |          rFm.high &= 0x7fff; | 
 |          fpa11->fpreg[Fd].fExtended = rFm; | 
 |       break; | 
 |  | 
 |       case RND_CODE: | 
 |       case URD_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_round_to_int(rFm, &fpa11->fp_status); | 
 |       break; | 
 |  | 
 |       case SQT_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_sqrt(rFm, &fpa11->fp_status); | 
 |       break; | 
 |  | 
 | #if 0 | 
 |       case LOG_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_log(rFm); | 
 |       break; | 
 |  | 
 |       case LGN_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_ln(rFm); | 
 |       break; | 
 |  | 
 |       case EXP_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_exp(rFm); | 
 |       break; | 
 |  | 
 |       case SIN_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_sin(rFm); | 
 |       break; | 
 |  | 
 |       case COS_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_cos(rFm); | 
 |       break; | 
 |  | 
 |       case TAN_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_tan(rFm); | 
 |       break; | 
 |  | 
 |       case ASN_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_arcsin(rFm); | 
 |       break; | 
 |  | 
 |       case ACS_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_arccos(rFm); | 
 |       break; | 
 |  | 
 |       case ATN_CODE: | 
 |          fpa11->fpreg[Fd].fExtended = floatx80_arctan(rFm); | 
 |       break; | 
 | #endif | 
 |  | 
 |       case NRM_CODE: | 
 |       break; | 
 |  | 
 |       default: | 
 |       { | 
 |         nRc = 0; | 
 |       } | 
 |    } | 
 |  | 
 |    if (0 != nRc) fpa11->fType[Fd] = typeExtended; | 
 |    return nRc; | 
 | } | 
 |  | 
 | #if 0 | 
 | floatx80 floatx80_exp(floatx80 Fm) | 
 | { | 
 | //series | 
 | } | 
 |  | 
 | floatx80 floatx80_ln(floatx80 Fm) | 
 | { | 
 | //series | 
 | } | 
 |  | 
 | floatx80 floatx80_sin(floatx80 rFm) | 
 | { | 
 | //series | 
 | } | 
 |  | 
 | floatx80 floatx80_cos(floatx80 rFm) | 
 | { | 
 | //series | 
 | } | 
 |  | 
 | floatx80 floatx80_arcsin(floatx80 rFm) | 
 | { | 
 | //series | 
 | } | 
 |  | 
 | floatx80 floatx80_arctan(floatx80 rFm) | 
 | { | 
 |   //series | 
 | } | 
 |  | 
 | floatx80 floatx80_log(floatx80 rFm) | 
 | { | 
 |   return floatx80_div(floatx80_ln(rFm),getExtendedConstant(7)); | 
 | } | 
 |  | 
 | floatx80 floatx80_tan(floatx80 rFm) | 
 | { | 
 |   return floatx80_div(floatx80_sin(rFm),floatx80_cos(rFm)); | 
 | } | 
 |  | 
 | floatx80 floatx80_arccos(floatx80 rFm) | 
 | { | 
 |    //return floatx80_sub(halfPi,floatx80_arcsin(rFm)); | 
 | } | 
 |  | 
 | floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm) | 
 | { | 
 |   return floatx80_exp(floatx80_mul(rFm,floatx80_ln(rFn))); | 
 | } | 
 |  | 
 | floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm) | 
 | { | 
 |   return floatx80_arctan(floatx80_div(rFn,rFm)); | 
 | } | 
 | #endif |