linux/arch/arm/nwfpe/extended_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
  26floatx80 floatx80_exp(floatx80 Fm);
  27floatx80 floatx80_ln(floatx80 Fm);
  28floatx80 floatx80_sin(floatx80 rFm);
  29floatx80 floatx80_cos(floatx80 rFm);
  30floatx80 floatx80_arcsin(floatx80 rFm);
  31floatx80 floatx80_arctan(floatx80 rFm);
  32floatx80 floatx80_log(floatx80 rFm);
  33floatx80 floatx80_tan(floatx80 rFm);
  34floatx80 floatx80_arccos(floatx80 rFm);
  35floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm);
  36floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm);
  37
  38static floatx80 floatx80_rsf(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
  39{
  40        return floatx80_sub(roundData, rFm, rFn);
  41}
  42
  43static floatx80 floatx80_rdv(struct roundingData *roundData, floatx80 rFn, floatx80 rFm)
  44{
  45        return floatx80_div(roundData, rFm, rFn);
  46}
  47
  48static floatx80 (*const dyadic_extended[16])(struct roundingData*, floatx80 rFn, floatx80 rFm) = {
  49        [ADF_CODE >> 20] = floatx80_add,
  50        [MUF_CODE >> 20] = floatx80_mul,
  51        [SUF_CODE >> 20] = floatx80_sub,
  52        [RSF_CODE >> 20] = floatx80_rsf,
  53        [DVF_CODE >> 20] = floatx80_div,
  54        [RDF_CODE >> 20] = floatx80_rdv,
  55        [RMF_CODE >> 20] = floatx80_rem,
  56
  57        /* strictly, these opcodes should not be implemented */
  58        [FML_CODE >> 20] = floatx80_mul,
  59        [FDV_CODE >> 20] = floatx80_div,
  60        [FRD_CODE >> 20] = floatx80_rdv,
  61};
  62
  63static floatx80 floatx80_mvf(struct roundingData *roundData, floatx80 rFm)
  64{
  65        return rFm;
  66}
  67
  68static floatx80 floatx80_mnf(struct roundingData *roundData, floatx80 rFm)
  69{
  70        rFm.high ^= 0x8000;
  71        return rFm;
  72}
  73
  74static floatx80 floatx80_abs(struct roundingData *roundData, floatx80 rFm)
  75{
  76        rFm.high &= 0x7fff;
  77        return rFm;
  78}
  79
  80static floatx80 (*const monadic_extended[16])(struct roundingData*, floatx80 rFm) = {
  81        [MVF_CODE >> 20] = floatx80_mvf,
  82        [MNF_CODE >> 20] = floatx80_mnf,
  83        [ABS_CODE >> 20] = floatx80_abs,
  84        [RND_CODE >> 20] = floatx80_round_to_int,
  85        [URD_CODE >> 20] = floatx80_round_to_int,
  86        [SQT_CODE >> 20] = floatx80_sqrt,
  87        [NRM_CODE >> 20] = floatx80_mvf,
  88};
  89
  90unsigned int ExtendedCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
  91{
  92        FPA11 *fpa11 = GET_FPA11();
  93        floatx80 rFm;
  94        unsigned int Fm, opc_mask_shift;
  95
  96        Fm = getFm(opcode);
  97        if (CONSTANT_FM(opcode)) {
  98                rFm = getExtendedConstant(Fm);
  99        } else {
 100                switch (fpa11->fType[Fm]) {
 101                case typeSingle:
 102                        rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
 103                        break;
 104
 105                case typeDouble:
 106                        rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
 107                        break;
 108
 109                case typeExtended:
 110                        rFm = fpa11->fpreg[Fm].fExtended;
 111                        break;
 112
 113                default:
 114                        return 0;
 115                }
 116        }
 117
 118        opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
 119        if (!MONADIC_INSTRUCTION(opcode)) {
 120                unsigned int Fn = getFn(opcode);
 121                floatx80 rFn;
 122
 123                switch (fpa11->fType[Fn]) {
 124                case typeSingle:
 125                        rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
 126                        break;
 127
 128                case typeDouble:
 129                        rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
 130                        break;
 131
 132                case typeExtended:
 133                        rFn = fpa11->fpreg[Fn].fExtended;
 134                        break;
 135
 136                default:
 137                        return 0;
 138                }
 139
 140                if (dyadic_extended[opc_mask_shift]) {
 141                        rFd->fExtended = dyadic_extended[opc_mask_shift](roundData, rFn, rFm);
 142                } else {
 143                        return 0;
 144                }
 145        } else {
 146                if (monadic_extended[opc_mask_shift]) {
 147                        rFd->fExtended = monadic_extended[opc_mask_shift](roundData, rFm);
 148                } else {
 149                        return 0;
 150                }
 151        }
 152
 153        return 1;
 154}
 155