linux/arch/arm/nwfpe/double_cpdo.c
<<
>>
Prefs
   1/*
   2    NetWinder Floating Point Emulator
   3    (c) Rebel.COM, 1998,1999
   4
   5    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
   6
   7    This program is free software; you can redistribute it and/or modify
   8    it under the terms of the GNU General Public License as published by
   9    the Free Software Foundation; either version 2 of the License, or
  10    (at your option) any later version.
  11
  12    This program is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15    GNU General Public License for more details.
  16
  17    You should have received a copy of the GNU General Public License
  18    along with this program; if not, write to the Free Software
  19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20*/
  21
  22#include "fpa11.h"
  23#include "softfloat.h"
  24#include "fpopcode.h"
  25
  26union float64_components {
  27        float64 f64;
  28        unsigned int i[2];
  29};
  30
  31float64 float64_exp(float64 Fm);
  32float64 float64_ln(float64 Fm);
  33float64 float64_sin(float64 rFm);
  34float64 float64_cos(float64 rFm);
  35float64 float64_arcsin(float64 rFm);
  36float64 float64_arctan(float64 rFm);
  37float64 float64_log(float64 rFm);
  38float64 float64_tan(float64 rFm);
  39float64 float64_arccos(float64 rFm);
  40float64 float64_pow(float64 rFn, float64 rFm);
  41float64 float64_pol(float64 rFn, float64 rFm);
  42
  43static float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm)
  44{
  45        return float64_sub(roundData, rFm, rFn);
  46}
  47
  48static float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm)
  49{
  50        return float64_div(roundData, rFm, rFn);
  51}
  52
  53static float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = {
  54        [ADF_CODE >> 20] = float64_add,
  55        [MUF_CODE >> 20] = float64_mul,
  56        [SUF_CODE >> 20] = float64_sub,
  57        [RSF_CODE >> 20] = float64_rsf,
  58        [DVF_CODE >> 20] = float64_div,
  59        [RDF_CODE >> 20] = float64_rdv,
  60        [RMF_CODE >> 20] = float64_rem,
  61
  62        /* strictly, these opcodes should not be implemented */
  63        [FML_CODE >> 20] = float64_mul,
  64        [FDV_CODE >> 20] = float64_div,
  65        [FRD_CODE >> 20] = float64_rdv,
  66};
  67
  68static float64 float64_mvf(struct roundingData *roundData,float64 rFm)
  69{
  70        return rFm;
  71}
  72
  73static float64 float64_mnf(struct roundingData *roundData,float64 rFm)
  74{
  75        union float64_components u;
  76
  77        u.f64 = rFm;
  78#ifdef __ARMEB__
  79        u.i[0] ^= 0x80000000;
  80#else
  81        u.i[1] ^= 0x80000000;
  82#endif
  83
  84        return u.f64;
  85}
  86
  87static float64 float64_abs(struct roundingData *roundData,float64 rFm)
  88{
  89        union float64_components u;
  90
  91        u.f64 = rFm;
  92#ifdef __ARMEB__
  93        u.i[0] &= 0x7fffffff;
  94#else
  95        u.i[1] &= 0x7fffffff;
  96#endif
  97
  98        return u.f64;
  99}
 100
 101static float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = {
 102        [MVF_CODE >> 20] = float64_mvf,
 103        [MNF_CODE >> 20] = float64_mnf,
 104        [ABS_CODE >> 20] = float64_abs,
 105        [RND_CODE >> 20] = float64_round_to_int,
 106        [URD_CODE >> 20] = float64_round_to_int,
 107        [SQT_CODE >> 20] = float64_sqrt,
 108        [NRM_CODE >> 20] = float64_mvf,
 109};
 110
 111unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
 112{
 113        FPA11 *fpa11 = GET_FPA11();
 114        float64 rFm;
 115        unsigned int Fm, opc_mask_shift;
 116
 117        Fm = getFm(opcode);
 118        if (CONSTANT_FM(opcode)) {
 119                rFm = getDoubleConstant(Fm);
 120        } else {
 121                switch (fpa11->fType[Fm]) {
 122                case typeSingle:
 123                        rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle);
 124                        break;
 125
 126                case typeDouble:
 127                        rFm = fpa11->fpreg[Fm].fDouble;
 128                        break;
 129
 130                default:
 131                        return 0;
 132                }
 133        }
 134
 135        opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
 136        if (!MONADIC_INSTRUCTION(opcode)) {
 137                unsigned int Fn = getFn(opcode);
 138                float64 rFn;
 139
 140                switch (fpa11->fType[Fn]) {
 141                case typeSingle:
 142                        rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle);
 143                        break;
 144
 145                case typeDouble:
 146                        rFn = fpa11->fpreg[Fn].fDouble;
 147                        break;
 148
 149                default:
 150                        return 0;
 151                }
 152
 153                if (dyadic_double[opc_mask_shift]) {
 154                        rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm);
 155                } else {
 156                        return 0;
 157                }
 158        } else {
 159                if (monadic_double[opc_mask_shift]) {
 160                        rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm);
 161                } else {
 162                        return 0;
 163                }
 164        }
 165
 166        return 1;
 167}
 168