Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003     NetWinder Floating Point Emulator
0004     (c) Rebel.COM, 1998,1999
0005 
0006     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
0007 
0008 */
0009 
0010 #include "fpa11.h"
0011 #include "softfloat.h"
0012 #include "fpopcode.h"
0013 
0014 union float64_components {
0015     float64 f64;
0016     unsigned int i[2];
0017 };
0018 
0019 float64 float64_exp(float64 Fm);
0020 float64 float64_ln(float64 Fm);
0021 float64 float64_sin(float64 rFm);
0022 float64 float64_cos(float64 rFm);
0023 float64 float64_arcsin(float64 rFm);
0024 float64 float64_arctan(float64 rFm);
0025 float64 float64_log(float64 rFm);
0026 float64 float64_tan(float64 rFm);
0027 float64 float64_arccos(float64 rFm);
0028 float64 float64_pow(float64 rFn, float64 rFm);
0029 float64 float64_pol(float64 rFn, float64 rFm);
0030 
0031 static float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm)
0032 {
0033     return float64_sub(roundData, rFm, rFn);
0034 }
0035 
0036 static float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm)
0037 {
0038     return float64_div(roundData, rFm, rFn);
0039 }
0040 
0041 static float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = {
0042     [ADF_CODE >> 20] = float64_add,
0043     [MUF_CODE >> 20] = float64_mul,
0044     [SUF_CODE >> 20] = float64_sub,
0045     [RSF_CODE >> 20] = float64_rsf,
0046     [DVF_CODE >> 20] = float64_div,
0047     [RDF_CODE >> 20] = float64_rdv,
0048     [RMF_CODE >> 20] = float64_rem,
0049 
0050     /* strictly, these opcodes should not be implemented */
0051     [FML_CODE >> 20] = float64_mul,
0052     [FDV_CODE >> 20] = float64_div,
0053     [FRD_CODE >> 20] = float64_rdv,
0054 };
0055 
0056 static float64 float64_mvf(struct roundingData *roundData,float64 rFm)
0057 {
0058     return rFm;
0059 }
0060 
0061 static float64 float64_mnf(struct roundingData *roundData,float64 rFm)
0062 {
0063     union float64_components u;
0064 
0065     u.f64 = rFm;
0066 #ifdef __ARMEB__
0067     u.i[0] ^= 0x80000000;
0068 #else
0069     u.i[1] ^= 0x80000000;
0070 #endif
0071 
0072     return u.f64;
0073 }
0074 
0075 static float64 float64_abs(struct roundingData *roundData,float64 rFm)
0076 {
0077     union float64_components u;
0078 
0079     u.f64 = rFm;
0080 #ifdef __ARMEB__
0081     u.i[0] &= 0x7fffffff;
0082 #else
0083     u.i[1] &= 0x7fffffff;
0084 #endif
0085 
0086     return u.f64;
0087 }
0088 
0089 static float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = {
0090     [MVF_CODE >> 20] = float64_mvf,
0091     [MNF_CODE >> 20] = float64_mnf,
0092     [ABS_CODE >> 20] = float64_abs,
0093     [RND_CODE >> 20] = float64_round_to_int,
0094     [URD_CODE >> 20] = float64_round_to_int,
0095     [SQT_CODE >> 20] = float64_sqrt,
0096     [NRM_CODE >> 20] = float64_mvf,
0097 };
0098 
0099 unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
0100 {
0101     FPA11 *fpa11 = GET_FPA11();
0102     float64 rFm;
0103     unsigned int Fm, opc_mask_shift;
0104 
0105     Fm = getFm(opcode);
0106     if (CONSTANT_FM(opcode)) {
0107         rFm = getDoubleConstant(Fm);
0108     } else {
0109         switch (fpa11->fType[Fm]) {
0110         case typeSingle:
0111             rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle);
0112             break;
0113 
0114         case typeDouble:
0115             rFm = fpa11->fpreg[Fm].fDouble;
0116             break;
0117 
0118         default:
0119             return 0;
0120         }
0121     }
0122 
0123     opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
0124     if (!MONADIC_INSTRUCTION(opcode)) {
0125         unsigned int Fn = getFn(opcode);
0126         float64 rFn;
0127 
0128         switch (fpa11->fType[Fn]) {
0129         case typeSingle:
0130             rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle);
0131             break;
0132 
0133         case typeDouble:
0134             rFn = fpa11->fpreg[Fn].fDouble;
0135             break;
0136 
0137         default:
0138             return 0;
0139         }
0140 
0141         if (dyadic_double[opc_mask_shift]) {
0142             rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm);
0143         } else {
0144             return 0;
0145         }
0146     } else {
0147         if (monadic_double[opc_mask_shift]) {
0148             rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm);
0149         } else {
0150             return 0;
0151         }
0152     }
0153 
0154     return 1;
0155 }