Commit 00406dff19893a4fb9fb582792a249b770eb1d11

Authored by bellard
1 parent 69de927c

added arm nwfpe support (initial patch by Ulrich Hecht)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@609 c046a42c-6fe2-441c-8c8c-71466251a162

Too many changes to show.

To preserve performance only 16 of 18 files are displayed.

target-arm/nwfpe/ARM-gcc.h 0 → 100644
  1 +/*
  2 +-------------------------------------------------------------------------------
  3 +The macro `BITS64' can be defined to indicate that 64-bit integer types are
  4 +supported by the compiler.
  5 +-------------------------------------------------------------------------------
  6 +*/
  7 +#define BITS64
  8 +
  9 +/*
  10 +-------------------------------------------------------------------------------
  11 +Each of the following `typedef's defines the most convenient type that holds
  12 +integers of at least as many bits as specified. For example, `uint8' should
  13 +be the most convenient type that can hold unsigned integers of as many as
  14 +8 bits. The `flag' type must be able to hold either a 0 or 1. For most
  15 +implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
  16 +to the same as `int'.
  17 +-------------------------------------------------------------------------------
  18 +*/
  19 +typedef char flag;
  20 +typedef unsigned char uint8;
  21 +typedef signed char int8;
  22 +typedef int uint16;
  23 +typedef int int16;
  24 +typedef unsigned int uint32;
  25 +typedef signed int int32;
  26 +#ifdef BITS64
  27 +typedef unsigned long long int bits64;
  28 +typedef signed long long int sbits64;
  29 +#endif
  30 +
  31 +/*
  32 +-------------------------------------------------------------------------------
  33 +Each of the following `typedef's defines a type that holds integers
  34 +of _exactly_ the number of bits specified. For instance, for most
  35 +implementation of C, `bits16' and `sbits16' should be `typedef'ed to
  36 +`unsigned short int' and `signed short int' (or `short int'), respectively.
  37 +-------------------------------------------------------------------------------
  38 +*/
  39 +typedef unsigned char bits8;
  40 +typedef signed char sbits8;
  41 +typedef unsigned short int bits16;
  42 +typedef signed short int sbits16;
  43 +typedef unsigned int bits32;
  44 +typedef signed int sbits32;
  45 +#ifdef BITS64
  46 +typedef unsigned long long int uint64;
  47 +typedef signed long long int int64;
  48 +#endif
  49 +
  50 +#ifdef BITS64
  51 +/*
  52 +-------------------------------------------------------------------------------
  53 +The `LIT64' macro takes as its argument a textual integer literal and if
  54 +necessary ``marks'' the literal as having a 64-bit integer type. For
  55 +example, the Gnu C Compiler (`gcc') requires that 64-bit literals be
  56 +appended with the letters `LL' standing for `long long', which is `gcc's
  57 +name for the 64-bit integer type. Some compilers may allow `LIT64' to be
  58 +defined as the identity macro: `#define LIT64( a ) a'.
  59 +-------------------------------------------------------------------------------
  60 +*/
  61 +#define LIT64( a ) a##LL
  62 +#endif
  63 +
  64 +/*
  65 +-------------------------------------------------------------------------------
  66 +The macro `INLINE' can be used before functions that should be inlined. If
  67 +a compiler does not support explicit inlining, this macro should be defined
  68 +to be `static'.
  69 +-------------------------------------------------------------------------------
  70 +*/
  71 +#define INLINE extern __inline__
  72 +
  73 +
  74 +/* For use as a GCC soft-float library we need some special function names. */
  75 +
  76 +#ifdef __LIBFLOAT__
  77 +
  78 +/* Some 32-bit ops can be mapped straight across by just changing the name. */
  79 +#define float32_add __addsf3
  80 +#define float32_sub __subsf3
  81 +#define float32_mul __mulsf3
  82 +#define float32_div __divsf3
  83 +#define int32_to_float32 __floatsisf
  84 +#define float32_to_int32_round_to_zero __fixsfsi
  85 +#define float32_to_uint32_round_to_zero __fixunssfsi
  86 +
  87 +/* These ones go through the glue code. To avoid namespace pollution
  88 + we rename the internal functions too. */
  89 +#define float32_eq ___float32_eq
  90 +#define float32_le ___float32_le
  91 +#define float32_lt ___float32_lt
  92 +
  93 +/* All the 64-bit ops have to go through the glue, so we pull the same
  94 + trick. */
  95 +#define float64_add ___float64_add
  96 +#define float64_sub ___float64_sub
  97 +#define float64_mul ___float64_mul
  98 +#define float64_div ___float64_div
  99 +#define int32_to_float64 ___int32_to_float64
  100 +#define float64_to_int32_round_to_zero ___float64_to_int32_round_to_zero
  101 +#define float64_to_uint32_round_to_zero ___float64_to_uint32_round_to_zero
  102 +#define float64_to_float32 ___float64_to_float32
  103 +#define float32_to_float64 ___float32_to_float64
  104 +#define float64_eq ___float64_eq
  105 +#define float64_le ___float64_le
  106 +#define float64_lt ___float64_lt
  107 +
  108 +#if 0
  109 +#define float64_add __adddf3
  110 +#define float64_sub __subdf3
  111 +#define float64_mul __muldf3
  112 +#define float64_div __divdf3
  113 +#define int32_to_float64 __floatsidf
  114 +#define float64_to_int32_round_to_zero __fixdfsi
  115 +#define float64_to_uint32_round_to_zero __fixunsdfsi
  116 +#define float64_to_float32 __truncdfsf2
  117 +#define float32_to_float64 __extendsfdf2
  118 +#endif
  119 +
  120 +#endif
... ...
target-arm/nwfpe/double_cpdo.c 0 → 100644
  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 +
  26 +float64 float64_exp(float64 Fm);
  27 +float64 float64_ln(float64 Fm);
  28 +float64 float64_sin(float64 rFm);
  29 +float64 float64_cos(float64 rFm);
  30 +float64 float64_arcsin(float64 rFm);
  31 +float64 float64_arctan(float64 rFm);
  32 +float64 float64_log(float64 rFm);
  33 +float64 float64_tan(float64 rFm);
  34 +float64 float64_arccos(float64 rFm);
  35 +float64 float64_pow(float64 rFn,float64 rFm);
  36 +float64 float64_pol(float64 rFn,float64 rFm);
  37 +
  38 +unsigned int DoubleCPDO(const unsigned int opcode)
  39 +{
  40 + FPA11 *fpa11 = GET_FPA11();
  41 + float64 rFm, rFn;
  42 + unsigned int Fd, Fm, Fn, nRc = 1;
  43 +
  44 + //printk("DoubleCPDO(0x%08x)\n",opcode);
  45 +
  46 + Fm = getFm(opcode);
  47 + if (CONSTANT_FM(opcode))
  48 + {
  49 + rFm = getDoubleConstant(Fm);
  50 + }
  51 + else
  52 + {
  53 + switch (fpa11->fType[Fm])
  54 + {
  55 + case typeSingle:
  56 + rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle);
  57 + break;
  58 +
  59 + case typeDouble:
  60 + rFm = fpa11->fpreg[Fm].fDouble;
  61 + break;
  62 +
  63 + case typeExtended:
  64 + // !! patb
  65 + //printk("not implemented! why not?\n");
  66 + //!! ScottB
  67 + // should never get here, if extended involved
  68 + // then other operand should be promoted then
  69 + // ExtendedCPDO called.
  70 + break;
  71 +
  72 + default: return 0;
  73 + }
  74 + }
  75 +
  76 + if (!MONADIC_INSTRUCTION(opcode))
  77 + {
  78 + Fn = getFn(opcode);
  79 + switch (fpa11->fType[Fn])
  80 + {
  81 + case typeSingle:
  82 + rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle);
  83 + break;
  84 +
  85 + case typeDouble:
  86 + rFn = fpa11->fpreg[Fn].fDouble;
  87 + break;
  88 +
  89 + default: return 0;
  90 + }
  91 + }
  92 +
  93 + Fd = getFd(opcode);
  94 + /* !! this switch isn't optimized; better (opcode & MASK_ARITHMETIC_OPCODE)>>24, sort of */
  95 + switch (opcode & MASK_ARITHMETIC_OPCODE)
  96 + {
  97 + /* dyadic opcodes */
  98 + case ADF_CODE:
  99 + fpa11->fpreg[Fd].fDouble = float64_add(rFn,rFm);
  100 + break;
  101 +
  102 + case MUF_CODE:
  103 + case FML_CODE:
  104 + fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm);
  105 + break;
  106 +
  107 + case SUF_CODE:
  108 + fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm);
  109 + break;
  110 +
  111 + case RSF_CODE:
  112 + fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn);
  113 + break;
  114 +
  115 + case DVF_CODE:
  116 + case FDV_CODE:
  117 + fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm);
  118 + break;
  119 +
  120 + case RDF_CODE:
  121 + case FRD_CODE:
  122 + fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn);
  123 + break;
  124 +
  125 +#if 0
  126 + case POW_CODE:
  127 + fpa11->fpreg[Fd].fDouble = float64_pow(rFn,rFm);
  128 + break;
  129 +
  130 + case RPW_CODE:
  131 + fpa11->fpreg[Fd].fDouble = float64_pow(rFm,rFn);
  132 + break;
  133 +#endif
  134 +
  135 + case RMF_CODE:
  136 + fpa11->fpreg[Fd].fDouble = float64_rem(rFn,rFm);
  137 + break;
  138 +
  139 +#if 0
  140 + case POL_CODE:
  141 + fpa11->fpreg[Fd].fDouble = float64_pol(rFn,rFm);
  142 + break;
  143 +#endif
  144 +
  145 + /* monadic opcodes */
  146 + case MVF_CODE:
  147 + fpa11->fpreg[Fd].fDouble = rFm;
  148 + break;
  149 +
  150 + case MNF_CODE:
  151 + {
  152 + unsigned int *p = (unsigned int*)&rFm;
  153 + p[1] ^= 0x80000000;
  154 + fpa11->fpreg[Fd].fDouble = rFm;
  155 + }
  156 + break;
  157 +
  158 + case ABS_CODE:
  159 + {
  160 + unsigned int *p = (unsigned int*)&rFm;
  161 + p[1] &= 0x7fffffff;
  162 + fpa11->fpreg[Fd].fDouble = rFm;
  163 + }
  164 + break;
  165 +
  166 + case RND_CODE:
  167 + case URD_CODE:
  168 + fpa11->fpreg[Fd].fDouble = float64_round_to_int(rFm);
  169 + break;
  170 +
  171 + case SQT_CODE:
  172 + fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm);
  173 + break;
  174 +
  175 +#if 0
  176 + case LOG_CODE:
  177 + fpa11->fpreg[Fd].fDouble = float64_log(rFm);
  178 + break;
  179 +
  180 + case LGN_CODE:
  181 + fpa11->fpreg[Fd].fDouble = float64_ln(rFm);
  182 + break;
  183 +
  184 + case EXP_CODE:
  185 + fpa11->fpreg[Fd].fDouble = float64_exp(rFm);
  186 + break;
  187 +
  188 + case SIN_CODE:
  189 + fpa11->fpreg[Fd].fDouble = float64_sin(rFm);
  190 + break;
  191 +
  192 + case COS_CODE:
  193 + fpa11->fpreg[Fd].fDouble = float64_cos(rFm);
  194 + break;
  195 +
  196 + case TAN_CODE:
  197 + fpa11->fpreg[Fd].fDouble = float64_tan(rFm);
  198 + break;
  199 +
  200 + case ASN_CODE:
  201 + fpa11->fpreg[Fd].fDouble = float64_arcsin(rFm);
  202 + break;
  203 +
  204 + case ACS_CODE:
  205 + fpa11->fpreg[Fd].fDouble = float64_arccos(rFm);
  206 + break;
  207 +
  208 + case ATN_CODE:
  209 + fpa11->fpreg[Fd].fDouble = float64_arctan(rFm);
  210 + break;
  211 +#endif
  212 +
  213 + case NRM_CODE:
  214 + break;
  215 +
  216 + default:
  217 + {
  218 + nRc = 0;
  219 + }
  220 + }
  221 +
  222 + if (0 != nRc) fpa11->fType[Fd] = typeDouble;
  223 + return nRc;
  224 +}
  225 +
  226 +#if 0
  227 +float64 float64_exp(float64 rFm)
  228 +{
  229 + return rFm;
  230 +//series
  231 +}
  232 +
  233 +float64 float64_ln(float64 rFm)
  234 +{
  235 + return rFm;
  236 +//series
  237 +}
  238 +
  239 +float64 float64_sin(float64 rFm)
  240 +{
  241 + return rFm;
  242 +//series
  243 +}
  244 +
  245 +float64 float64_cos(float64 rFm)
  246 +{
  247 + return rFm;
  248 + //series
  249 +}
  250 +
  251 +#if 0
  252 +float64 float64_arcsin(float64 rFm)
  253 +{
  254 +//series
  255 +}
  256 +
  257 +float64 float64_arctan(float64 rFm)
  258 +{
  259 + //series
  260 +}
  261 +#endif
  262 +
  263 +float64 float64_log(float64 rFm)
  264 +{
  265 + return float64_div(float64_ln(rFm),getDoubleConstant(7));
  266 +}
  267 +
  268 +float64 float64_tan(float64 rFm)
  269 +{
  270 + return float64_div(float64_sin(rFm),float64_cos(rFm));
  271 +}
  272 +
  273 +float64 float64_arccos(float64 rFm)
  274 +{
  275 +return rFm;
  276 + //return float64_sub(halfPi,float64_arcsin(rFm));
  277 +}
  278 +
  279 +float64 float64_pow(float64 rFn,float64 rFm)
  280 +{
  281 + return float64_exp(float64_mul(rFm,float64_ln(rFn)));
  282 +}
  283 +
  284 +float64 float64_pol(float64 rFn,float64 rFm)
  285 +{
  286 + return float64_arctan(float64_div(rFn,rFm));
  287 +}
  288 +#endif
... ...
target-arm/nwfpe/extended_cpdo.c 0 → 100644
  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 +
  26 +floatx80 floatx80_exp(floatx80 Fm);
  27 +floatx80 floatx80_ln(floatx80 Fm);
  28 +floatx80 floatx80_sin(floatx80 rFm);
  29 +floatx80 floatx80_cos(floatx80 rFm);
  30 +floatx80 floatx80_arcsin(floatx80 rFm);
  31 +floatx80 floatx80_arctan(floatx80 rFm);
  32 +floatx80 floatx80_log(floatx80 rFm);
  33 +floatx80 floatx80_tan(floatx80 rFm);
  34 +floatx80 floatx80_arccos(floatx80 rFm);
  35 +floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm);
  36 +floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm);
  37 +
  38 +unsigned int ExtendedCPDO(const unsigned int opcode)
  39 +{
  40 + FPA11 *fpa11 = GET_FPA11();
  41 + floatx80 rFm, rFn;
  42 + unsigned int Fd, Fm, Fn, nRc = 1;
  43 +
  44 + //printk("ExtendedCPDO(0x%08x)\n",opcode);
  45 +
  46 + Fm = getFm(opcode);
  47 + if (CONSTANT_FM(opcode))
  48 + {
  49 + rFm = getExtendedConstant(Fm);
  50 + }
  51 + else
  52 + {
  53 + switch (fpa11->fType[Fm])
  54 + {
  55 + case typeSingle:
  56 + rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
  57 + break;
  58 +
  59 + case typeDouble:
  60 + rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
  61 + break;
  62 +
  63 + case typeExtended:
  64 + rFm = fpa11->fpreg[Fm].fExtended;
  65 + break;
  66 +
  67 + default: return 0;
  68 + }
  69 + }
  70 +
  71 + if (!MONADIC_INSTRUCTION(opcode))
  72 + {
  73 + Fn = getFn(opcode);
  74 + switch (fpa11->fType[Fn])
  75 + {
  76 + case typeSingle:
  77 + rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
  78 + break;
  79 +
  80 + case typeDouble:
  81 + rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
  82 + break;
  83 +
  84 + case typeExtended:
  85 + rFn = fpa11->fpreg[Fn].fExtended;
  86 + break;
  87 +
  88 + default: return 0;
  89 + }
  90 + }
  91 +
  92 + Fd = getFd(opcode);
  93 + switch (opcode & MASK_ARITHMETIC_OPCODE)
  94 + {
  95 + /* dyadic opcodes */
  96 + case ADF_CODE:
  97 + fpa11->fpreg[Fd].fExtended = floatx80_add(rFn,rFm);
  98 + break;
  99 +
  100 + case MUF_CODE:
  101 + case FML_CODE:
  102 + fpa11->fpreg[Fd].fExtended = floatx80_mul(rFn,rFm);
  103 + break;
  104 +
  105 + case SUF_CODE:
  106 + fpa11->fpreg[Fd].fExtended = floatx80_sub(rFn,rFm);
  107 + break;
  108 +
  109 + case RSF_CODE:
  110 + fpa11->fpreg[Fd].fExtended = floatx80_sub(rFm,rFn);
  111 + break;
  112 +
  113 + case DVF_CODE:
  114 + case FDV_CODE:
  115 + fpa11->fpreg[Fd].fExtended = floatx80_div(rFn,rFm);
  116 + break;
  117 +
  118 + case RDF_CODE:
  119 + case FRD_CODE:
  120 + fpa11->fpreg[Fd].fExtended = floatx80_div(rFm,rFn);
  121 + break;
  122 +
  123 +#if 0
  124 + case POW_CODE:
  125 + fpa11->fpreg[Fd].fExtended = floatx80_pow(rFn,rFm);
  126 + break;
  127 +
  128 + case RPW_CODE:
  129 + fpa11->fpreg[Fd].fExtended = floatx80_pow(rFm,rFn);
  130 + break;
  131 +#endif
  132 +
  133 + case RMF_CODE:
  134 + fpa11->fpreg[Fd].fExtended = floatx80_rem(rFn,rFm);
  135 + break;
  136 +
  137 +#if 0
  138 + case POL_CODE:
  139 + fpa11->fpreg[Fd].fExtended = floatx80_pol(rFn,rFm);
  140 + break;
  141 +#endif
  142 +
  143 + /* monadic opcodes */
  144 + case MVF_CODE:
  145 + fpa11->fpreg[Fd].fExtended = rFm;
  146 + break;
  147 +
  148 + case MNF_CODE:
  149 + rFm.high ^= 0x8000;
  150 + fpa11->fpreg[Fd].fExtended = rFm;
  151 + break;
  152 +
  153 + case ABS_CODE:
  154 + rFm.high &= 0x7fff;
  155 + fpa11->fpreg[Fd].fExtended = rFm;
  156 + break;
  157 +
  158 + case RND_CODE:
  159 + case URD_CODE:
  160 + fpa11->fpreg[Fd].fExtended = floatx80_round_to_int(rFm);
  161 + break;
  162 +
  163 + case SQT_CODE:
  164 + fpa11->fpreg[Fd].fExtended = floatx80_sqrt(rFm);
  165 + break;
  166 +
  167 +#if 0
  168 + case LOG_CODE:
  169 + fpa11->fpreg[Fd].fExtended = floatx80_log(rFm);
  170 + break;
  171 +
  172 + case LGN_CODE:
  173 + fpa11->fpreg[Fd].fExtended = floatx80_ln(rFm);
  174 + break;
  175 +
  176 + case EXP_CODE:
  177 + fpa11->fpreg[Fd].fExtended = floatx80_exp(rFm);
  178 + break;
  179 +
  180 + case SIN_CODE:
  181 + fpa11->fpreg[Fd].fExtended = floatx80_sin(rFm);
  182 + break;
  183 +
  184 + case COS_CODE:
  185 + fpa11->fpreg[Fd].fExtended = floatx80_cos(rFm);
  186 + break;
  187 +
  188 + case TAN_CODE:
  189 + fpa11->fpreg[Fd].fExtended = floatx80_tan(rFm);
  190 + break;
  191 +
  192 + case ASN_CODE:
  193 + fpa11->fpreg[Fd].fExtended = floatx80_arcsin(rFm);
  194 + break;
  195 +
  196 + case ACS_CODE:
  197 + fpa11->fpreg[Fd].fExtended = floatx80_arccos(rFm);
  198 + break;
  199 +
  200 + case ATN_CODE:
  201 + fpa11->fpreg[Fd].fExtended = floatx80_arctan(rFm);
  202 + break;
  203 +#endif
  204 +
  205 + case NRM_CODE:
  206 + break;
  207 +
  208 + default:
  209 + {
  210 + nRc = 0;
  211 + }
  212 + }
  213 +
  214 + if (0 != nRc) fpa11->fType[Fd] = typeExtended;
  215 + return nRc;
  216 +}
  217 +
  218 +#if 0
  219 +floatx80 floatx80_exp(floatx80 Fm)
  220 +{
  221 +//series
  222 +}
  223 +
  224 +floatx80 floatx80_ln(floatx80 Fm)
  225 +{
  226 +//series
  227 +}
  228 +
  229 +floatx80 floatx80_sin(floatx80 rFm)
  230 +{
  231 +//series
  232 +}
  233 +
  234 +floatx80 floatx80_cos(floatx80 rFm)
  235 +{
  236 +//series
  237 +}
  238 +
  239 +floatx80 floatx80_arcsin(floatx80 rFm)
  240 +{
  241 +//series
  242 +}
  243 +
  244 +floatx80 floatx80_arctan(floatx80 rFm)
  245 +{
  246 + //series
  247 +}
  248 +
  249 +floatx80 floatx80_log(floatx80 rFm)
  250 +{
  251 + return floatx80_div(floatx80_ln(rFm),getExtendedConstant(7));
  252 +}
  253 +
  254 +floatx80 floatx80_tan(floatx80 rFm)
  255 +{
  256 + return floatx80_div(floatx80_sin(rFm),floatx80_cos(rFm));
  257 +}
  258 +
  259 +floatx80 floatx80_arccos(floatx80 rFm)
  260 +{
  261 + //return floatx80_sub(halfPi,floatx80_arcsin(rFm));
  262 +}
  263 +
  264 +floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm)
  265 +{
  266 + return floatx80_exp(floatx80_mul(rFm,floatx80_ln(rFn)));
  267 +}
  268 +
  269 +floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm)
  270 +{
  271 + return floatx80_arctan(floatx80_div(rFn,rFm));
  272 +}
  273 +#endif
... ...
target-arm/nwfpe/fpa11.c 0 → 100644
  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 +
  24 +#include "fpopcode.h"
  25 +
  26 +//#include "fpmodule.h"
  27 +//#include "fpmodule.inl"
  28 +
  29 +//#include <asm/system.h>
  30 +
  31 +#include <stdio.h>
  32 +
  33 +/* forward declarations */
  34 +unsigned int EmulateCPDO(const unsigned int);
  35 +unsigned int EmulateCPDT(const unsigned int);
  36 +unsigned int EmulateCPRT(const unsigned int);
  37 +
  38 +FPA11* qemufpa=0;
  39 +unsigned int* user_registers=0;
  40 +
  41 +/* Reset the FPA11 chip. Called to initialize and reset the emulator. */
  42 +void resetFPA11(void)
  43 +{
  44 + int i;
  45 + FPA11 *fpa11 = GET_FPA11();
  46 +
  47 + /* initialize the register type array */
  48 + for (i=0;i<=7;i++)
  49 + {
  50 + fpa11->fType[i] = typeNone;
  51 + }
  52 +
  53 + /* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */
  54 + fpa11->fpsr = FP_EMULATOR | BIT_AC;
  55 +
  56 + /* FPCR: set SB, AB and DA bits, clear all others */
  57 +#if MAINTAIN_FPCR
  58 + fpa11->fpcr = MASK_RESET;
  59 +#endif
  60 +}
  61 +
  62 +void SetRoundingMode(const unsigned int opcode)
  63 +{
  64 +#if MAINTAIN_FPCR
  65 + FPA11 *fpa11 = GET_FPA11();
  66 + fpa11->fpcr &= ~MASK_ROUNDING_MODE;
  67 +#endif
  68 + switch (opcode & MASK_ROUNDING_MODE)
  69 + {
  70 + default:
  71 + case ROUND_TO_NEAREST:
  72 + float_rounding_mode = float_round_nearest_even;
  73 +#if MAINTAIN_FPCR
  74 + fpa11->fpcr |= ROUND_TO_NEAREST;
  75 +#endif
  76 + break;
  77 +
  78 + case ROUND_TO_PLUS_INFINITY:
  79 + float_rounding_mode = float_round_up;
  80 +#if MAINTAIN_FPCR
  81 + fpa11->fpcr |= ROUND_TO_PLUS_INFINITY;
  82 +#endif
  83 + break;
  84 +
  85 + case ROUND_TO_MINUS_INFINITY:
  86 + float_rounding_mode = float_round_down;
  87 +#if MAINTAIN_FPCR
  88 + fpa11->fpcr |= ROUND_TO_MINUS_INFINITY;
  89 +#endif
  90 + break;
  91 +
  92 + case ROUND_TO_ZERO:
  93 + float_rounding_mode = float_round_to_zero;
  94 +#if MAINTAIN_FPCR
  95 + fpa11->fpcr |= ROUND_TO_ZERO;
  96 +#endif
  97 + break;
  98 + }
  99 +}
  100 +
  101 +void SetRoundingPrecision(const unsigned int opcode)
  102 +{
  103 +#if MAINTAIN_FPCR
  104 + FPA11 *fpa11 = GET_FPA11();
  105 + fpa11->fpcr &= ~MASK_ROUNDING_PRECISION;
  106 +#endif
  107 + switch (opcode & MASK_ROUNDING_PRECISION)
  108 + {
  109 + case ROUND_SINGLE:
  110 + floatx80_rounding_precision = 32;
  111 +#if MAINTAIN_FPCR
  112 + fpa11->fpcr |= ROUND_SINGLE;
  113 +#endif
  114 + break;
  115 +
  116 + case ROUND_DOUBLE:
  117 + floatx80_rounding_precision = 64;
  118 +#if MAINTAIN_FPCR
  119 + fpa11->fpcr |= ROUND_DOUBLE;
  120 +#endif
  121 + break;
  122 +
  123 + case ROUND_EXTENDED:
  124 + floatx80_rounding_precision = 80;
  125 +#if MAINTAIN_FPCR
  126 + fpa11->fpcr |= ROUND_EXTENDED;
  127 +#endif
  128 + break;
  129 +
  130 + default: floatx80_rounding_precision = 80;
  131 + }
  132 +}
  133 +
  134 +/* Emulate the instruction in the opcode. */
  135 +unsigned int EmulateAll(unsigned int opcode, FPA11* qfpa, unsigned int* qregs)
  136 +{
  137 + unsigned int nRc = 0;
  138 +// unsigned long flags;
  139 + FPA11 *fpa11;
  140 +// save_flags(flags); sti();
  141 +
  142 + qemufpa=qfpa;
  143 + user_registers=qregs;
  144 +
  145 +#if 0
  146 + fprintf(stderr,"emulating FP insn 0x%08x, PC=0x%08x\n",
  147 + opcode, qregs[REG_PC]);
  148 +#endif
  149 + fpa11 = GET_FPA11();
  150 +
  151 + if (fpa11->initflag == 0) /* good place for __builtin_expect */
  152 + {
  153 + resetFPA11();
  154 + SetRoundingMode(ROUND_TO_NEAREST);
  155 + SetRoundingPrecision(ROUND_EXTENDED);
  156 + fpa11->initflag = 1;
  157 + }
  158 +
  159 + if (TEST_OPCODE(opcode,MASK_CPRT))
  160 + {
  161 + //fprintf(stderr,"emulating CPRT\n");
  162 + /* Emulate conversion opcodes. */
  163 + /* Emulate register transfer opcodes. */
  164 + /* Emulate comparison opcodes. */
  165 + nRc = EmulateCPRT(opcode);
  166 + }
  167 + else if (TEST_OPCODE(opcode,MASK_CPDO))
  168 + {
  169 + //fprintf(stderr,"emulating CPDO\n");
  170 + /* Emulate monadic arithmetic opcodes. */
  171 + /* Emulate dyadic arithmetic opcodes. */
  172 + nRc = EmulateCPDO(opcode);
  173 + }
  174 + else if (TEST_OPCODE(opcode,MASK_CPDT))
  175 + {
  176 + //fprintf(stderr,"emulating CPDT\n");
  177 + /* Emulate load/store opcodes. */
  178 + /* Emulate load/store multiple opcodes. */
  179 + nRc = EmulateCPDT(opcode);
  180 + }
  181 + else
  182 + {
  183 + /* Invalid instruction detected. Return FALSE. */
  184 + nRc = 0;
  185 + }
  186 +
  187 +// restore_flags(flags);
  188 +
  189 + //printf("returning %d\n",nRc);
  190 + return(nRc);
  191 +}
  192 +
  193 +#if 0
  194 +unsigned int EmulateAll1(unsigned int opcode)
  195 +{
  196 + switch ((opcode >> 24) & 0xf)
  197 + {
  198 + case 0xc:
  199 + case 0xd:
  200 + if ((opcode >> 20) & 0x1)
  201 + {
  202 + switch ((opcode >> 8) & 0xf)
  203 + {
  204 + case 0x1: return PerformLDF(opcode); break;
  205 + case 0x2: return PerformLFM(opcode); break;
  206 + default: return 0;
  207 + }
  208 + }
  209 + else
  210 + {
  211 + switch ((opcode >> 8) & 0xf)
  212 + {
  213 + case 0x1: return PerformSTF(opcode); break;
  214 + case 0x2: return PerformSFM(opcode); break;
  215 + default: return 0;
  216 + }
  217 + }
  218 + break;
  219 +
  220 + case 0xe:
  221 + if (opcode & 0x10)
  222 + return EmulateCPDO(opcode);
  223 + else
  224 + return EmulateCPRT(opcode);
  225 + break;
  226 +
  227 + default: return 0;
  228 + }
  229 +}
  230 +#endif
  231 +
... ...
target-arm/nwfpe/fpa11.h 0 → 100644
  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 +#ifndef __FPA11_H__
  23 +#define __FPA11_H__
  24 +
  25 +#define GET_FPA11() (qemufpa)
  26 +
  27 +/*
  28 + * The processes registers are always at the very top of the 8K
  29 + * stack+task struct. Use the same method as 'current' uses to
  30 + * reach them.
  31 + */
  32 +extern unsigned int *user_registers;
  33 +
  34 +#define GET_USERREG() (user_registers)
  35 +
  36 +/* Need task_struct */
  37 +//#include <linux/sched.h>
  38 +
  39 +/* includes */
  40 +#include "fpsr.h" /* FP control and status register definitions */
  41 +#include "softfloat.h"
  42 +
  43 +#define typeNone 0x00
  44 +#define typeSingle 0x01
  45 +#define typeDouble 0x02
  46 +#define typeExtended 0x03
  47 +
  48 +/*
  49 + * This must be no more and no less than 12 bytes.
  50 + */
  51 +typedef union tagFPREG {
  52 + floatx80 fExtended;
  53 + float64 fDouble;
  54 + float32 fSingle;
  55 +} FPREG;
  56 +
  57 +/*
  58 + * FPA11 device model.
  59 + *
  60 + * This structure is exported to user space. Do not re-order.
  61 + * Only add new stuff to the end, and do not change the size of
  62 + * any element. Elements of this structure are used by user
  63 + * space, and must match struct user_fp in include/asm-arm/user.h.
  64 + * We include the byte offsets below for documentation purposes.
  65 + *
  66 + * The size of this structure and FPREG are checked by fpmodule.c
  67 + * on initialisation. If the rules have been broken, NWFPE will
  68 + * not initialise.
  69 + */
  70 +typedef struct tagFPA11 {
  71 +/* 0 */ FPREG fpreg[8]; /* 8 floating point registers */
  72 +/* 96 */ FPSR fpsr; /* floating point status register */
  73 +/* 100 */ FPCR fpcr; /* floating point control register */
  74 +/* 104 */ unsigned char fType[8]; /* type of floating point value held in
  75 + floating point registers. One of none
  76 + single, double or extended. */
  77 +/* 112 */ int initflag; /* this is special. The kernel guarantees
  78 + to set it to 0 when a thread is launched,
  79 + so we can use it to detect whether this
  80 + instance of the emulator needs to be
  81 + initialised. */
  82 +} FPA11;
  83 +
  84 +extern FPA11* qemufpa;
  85 +
  86 +extern void resetFPA11(void);
  87 +extern void SetRoundingMode(const unsigned int);
  88 +extern void SetRoundingPrecision(const unsigned int);
  89 +
  90 +#define get_user(x,y) ((x)=*(y))
  91 +#define put_user(x,y) (*(y)=(x))
  92 +static inline unsigned int readRegister(unsigned int reg)
  93 +{
  94 + return (user_registers[(reg)]);
  95 +}
  96 +
  97 +static inline void writeRegister(unsigned int x, unsigned int y)
  98 +{
  99 +#if 0
  100 + printf("writing %d to r%d\n",y,x);
  101 +#endif
  102 + user_registers[(x)]=(y);
  103 +}
  104 +
  105 +static inline void writeConditionCodes(unsigned int x)
  106 +{
  107 +#if 0
  108 +unsigned int y;
  109 +unsigned int ZF;
  110 + printf("setting flags to %x from %x\n",x,user_registers[16]);
  111 +#endif
  112 + user_registers[16]=(x); // cpsr
  113 + user_registers[17]=(x>>29)&1; // cf
  114 + user_registers[18]=(x<<3)&(1<<31); // vf
  115 + user_registers[19]=x&(1<<31); // nzf
  116 + if(!(x&(1<<30))) user_registers[19]++; // nzf must be non-zero for zf to be cleared
  117 +
  118 +#if 0
  119 + ZF = (user_registers[19] == 0);
  120 + y=user_registers[16] | (user_registers[19] & 0x80000000) | (ZF << 30) |
  121 + (user_registers[17] << 29) | ((user_registers[18] & 0x80000000) >> 3);
  122 + if(y != x)
  123 + printf("GODDAM SHIIIIIIIIIIIIIIIIT! %x %x nzf %x zf %x\n",x,y,user_registers[19],ZF);
  124 +#endif
  125 +}
  126 +
  127 +#define REG_PC 15
  128 +
  129 +unsigned int EmulateAll(unsigned int opcode, FPA11* qfpa, unsigned int* qregs);
  130 +
  131 +#endif
... ...
target-arm/nwfpe/fpa11.inl 0 → 100644
  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 +
  24 +/* Read and write floating point status register */
  25 +extern __inline__ unsigned int readFPSR(void)
  26 +{
  27 + FPA11 *fpa11 = GET_FPA11();
  28 + return(fpa11->fpsr);
  29 +}
  30 +
  31 +extern __inline__ void writeFPSR(FPSR reg)
  32 +{
  33 + FPA11 *fpa11 = GET_FPA11();
  34 + /* the sysid byte in the status register is readonly */
  35 + fpa11->fpsr = (fpa11->fpsr & MASK_SYSID) | (reg & ~MASK_SYSID);
  36 +}
  37 +
  38 +/* Read and write floating point control register */
  39 +extern __inline__ FPCR readFPCR(void)
  40 +{
  41 + FPA11 *fpa11 = GET_FPA11();
  42 + /* clear SB, AB and DA bits before returning FPCR */
  43 + return(fpa11->fpcr & ~MASK_RFC);
  44 +}
  45 +
  46 +extern __inline__ void writeFPCR(FPCR reg)
  47 +{
  48 + FPA11 *fpa11 = GET_FPA11();
  49 + fpa11->fpcr &= ~MASK_WFC; /* clear SB, AB and DA bits */
  50 + fpa11->fpcr |= (reg & MASK_WFC); /* write SB, AB and DA bits */
  51 +}
... ...
target-arm/nwfpe/fpa11_cpdo.c 0 → 100644
  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 "fpopcode.h"
  24 +
  25 +unsigned int SingleCPDO(const unsigned int opcode);
  26 +unsigned int DoubleCPDO(const unsigned int opcode);
  27 +unsigned int ExtendedCPDO(const unsigned int opcode);
  28 +
  29 +unsigned int EmulateCPDO(const unsigned int opcode)
  30 +{
  31 + FPA11 *fpa11 = GET_FPA11();
  32 + unsigned int Fd, nType, nDest, nRc = 1;
  33 +
  34 + //printk("EmulateCPDO(0x%08x)\n",opcode);
  35 +
  36 + /* Get the destination size. If not valid let Linux perform
  37 + an invalid instruction trap. */
  38 + nDest = getDestinationSize(opcode);
  39 + if (typeNone == nDest) return 0;
  40 +
  41 + SetRoundingMode(opcode);
  42 +
  43 + /* Compare the size of the operands in Fn and Fm.
  44 + Choose the largest size and perform operations in that size,
  45 + in order to make use of all the precision of the operands.
  46 + If Fm is a constant, we just grab a constant of a size
  47 + matching the size of the operand in Fn. */
  48 + if (MONADIC_INSTRUCTION(opcode))
  49 + nType = nDest;
  50 + else
  51 + nType = fpa11->fType[getFn(opcode)];
  52 +
  53 + if (!CONSTANT_FM(opcode))
  54 + {
  55 + register unsigned int Fm = getFm(opcode);
  56 + if (nType < fpa11->fType[Fm])
  57 + {
  58 + nType = fpa11->fType[Fm];
  59 + }
  60 + }
  61 +
  62 + switch (nType)
  63 + {
  64 + case typeSingle : nRc = SingleCPDO(opcode); break;
  65 + case typeDouble : nRc = DoubleCPDO(opcode); break;
  66 + case typeExtended : nRc = ExtendedCPDO(opcode); break;
  67 + default : nRc = 0;
  68 + }
  69 +
  70 + /* If the operation succeeded, check to see if the result in the
  71 + destination register is the correct size. If not force it
  72 + to be. */
  73 + Fd = getFd(opcode);
  74 + nType = fpa11->fType[Fd];
  75 + if ((0 != nRc) && (nDest != nType))
  76 + {
  77 + switch (nDest)
  78 + {
  79 + case typeSingle:
  80 + {
  81 + if (typeDouble == nType)
  82 + fpa11->fpreg[Fd].fSingle =
  83 + float64_to_float32(fpa11->fpreg[Fd].fDouble);
  84 + else
  85 + fpa11->fpreg[Fd].fSingle =
  86 + floatx80_to_float32(fpa11->fpreg[Fd].fExtended);
  87 + }
  88 + break;
  89 +
  90 + case typeDouble:
  91 + {
  92 + if (typeSingle == nType)
  93 + fpa11->fpreg[Fd].fDouble =
  94 + float32_to_float64(fpa11->fpreg[Fd].fSingle);
  95 + else
  96 + fpa11->fpreg[Fd].fDouble =
  97 + floatx80_to_float64(fpa11->fpreg[Fd].fExtended);
  98 + }
  99 + break;
  100 +
  101 + case typeExtended:
  102 + {
  103 + if (typeSingle == nType)
  104 + fpa11->fpreg[Fd].fExtended =
  105 + float32_to_floatx80(fpa11->fpreg[Fd].fSingle);
  106 + else
  107 + fpa11->fpreg[Fd].fExtended =
  108 + float64_to_floatx80(fpa11->fpreg[Fd].fDouble);
  109 + }
  110 + break;
  111 + }
  112 +
  113 + fpa11->fType[Fd] = nDest;
  114 + }
  115 +
  116 + return nRc;
  117 +}
... ...
target-arm/nwfpe/fpa11_cpdt.c 0 → 100644
  1 +/*
  2 + NetWinder Floating Point Emulator
  3 + (c) Rebel.com, 1998-1999
  4 + (c) Philip Blundell, 1998
  5 +
  6 + Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
  7 +
  8 + This program is free software; you can redistribute it and/or modify
  9 + it under the terms of the GNU General Public License as published by
  10 + the Free Software Foundation; either version 2 of the License, or
  11 + (at your option) any later version.
  12 +
  13 + This program is distributed in the hope that it will be useful,
  14 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + GNU General Public License for more details.
  17 +
  18 + You should have received a copy of the GNU General Public License
  19 + along with this program; if not, write to the Free Software
  20 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21 +*/
  22 +
  23 +#include "fpa11.h"
  24 +#include "softfloat.h"
  25 +#include "fpopcode.h"
  26 +//#include "fpmodule.h"
  27 +//#include "fpmodule.inl"
  28 +
  29 +//#include <asm/uaccess.h>
  30 +
  31 +static inline
  32 +void loadSingle(const unsigned int Fn,const unsigned int *pMem)
  33 +{
  34 + FPA11 *fpa11 = GET_FPA11();
  35 + fpa11->fType[Fn] = typeSingle;
  36 + get_user(fpa11->fpreg[Fn].fSingle, pMem);
  37 +}
  38 +
  39 +static inline
  40 +void loadDouble(const unsigned int Fn,const unsigned int *pMem)
  41 +{
  42 + FPA11 *fpa11 = GET_FPA11();
  43 + unsigned int *p;
  44 + p = (unsigned int*)&fpa11->fpreg[Fn].fDouble;
  45 + fpa11->fType[Fn] = typeDouble;
  46 + get_user(p[0], &pMem[1]);
  47 + get_user(p[1], &pMem[0]); /* sign & exponent */
  48 +}
  49 +
  50 +static inline
  51 +void loadExtended(const unsigned int Fn,const unsigned int *pMem)
  52 +{
  53 + FPA11 *fpa11 = GET_FPA11();
  54 + unsigned int *p;
  55 + p = (unsigned int*)&fpa11->fpreg[Fn].fExtended;
  56 + fpa11->fType[Fn] = typeExtended;
  57 + get_user(p[0], &pMem[0]); /* sign & exponent */
  58 + get_user(p[1], &pMem[2]); /* ls bits */
  59 + get_user(p[2], &pMem[1]); /* ms bits */
  60 +}
  61 +
  62 +static inline
  63 +void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
  64 +{
  65 + FPA11 *fpa11 = GET_FPA11();
  66 + register unsigned int *p;
  67 + unsigned long x;
  68 +
  69 + p = (unsigned int*)&(fpa11->fpreg[Fn]);
  70 + get_user(x, &pMem[0]);
  71 + fpa11->fType[Fn] = (x >> 14) & 0x00000003;
  72 +
  73 + switch (fpa11->fType[Fn])
  74 + {
  75 + case typeSingle:
  76 + case typeDouble:
  77 + {
  78 + get_user(p[0], &pMem[2]); /* Single */
  79 + get_user(p[1], &pMem[1]); /* double msw */
  80 + p[2] = 0; /* empty */
  81 + }
  82 + break;
  83 +
  84 + case typeExtended:
  85 + {
  86 + get_user(p[1], &pMem[2]);
  87 + get_user(p[2], &pMem[1]); /* msw */
  88 + p[0] = (x & 0x80003fff);
  89 + }
  90 + break;
  91 + }
  92 +}
  93 +
  94 +static inline
  95 +void storeSingle(const unsigned int Fn,unsigned int *pMem)
  96 +{
  97 + FPA11 *fpa11 = GET_FPA11();
  98 + float32 val;
  99 + register unsigned int *p = (unsigned int*)&val;
  100 +
  101 + switch (fpa11->fType[Fn])
  102 + {
  103 + case typeDouble:
  104 + val = float64_to_float32(fpa11->fpreg[Fn].fDouble);
  105 + break;
  106 +
  107 + case typeExtended:
  108 + val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
  109 + break;
  110 +
  111 + default: val = fpa11->fpreg[Fn].fSingle;
  112 + }
  113 +
  114 + put_user(p[0], pMem);
  115 +}
  116 +
  117 +static inline
  118 +void storeDouble(const unsigned int Fn,unsigned int *pMem)
  119 +{
  120 + FPA11 *fpa11 = GET_FPA11();
  121 + float64 val;
  122 + register unsigned int *p = (unsigned int*)&val;
  123 +
  124 + switch (fpa11->fType[Fn])
  125 + {
  126 + case typeSingle:
  127 + val = float32_to_float64(fpa11->fpreg[Fn].fSingle);
  128 + break;
  129 +
  130 + case typeExtended:
  131 + val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
  132 + break;
  133 +
  134 + default: val = fpa11->fpreg[Fn].fDouble;
  135 + }
  136 + put_user(p[1], &pMem[0]); /* msw */
  137 + put_user(p[0], &pMem[1]); /* lsw */
  138 +}
  139 +
  140 +static inline
  141 +void storeExtended(const unsigned int Fn,unsigned int *pMem)
  142 +{
  143 + FPA11 *fpa11 = GET_FPA11();
  144 + floatx80 val;
  145 + register unsigned int *p = (unsigned int*)&val;
  146 +
  147 + switch (fpa11->fType[Fn])
  148 + {
  149 + case typeSingle:
  150 + val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
  151 + break;
  152 +
  153 + case typeDouble:
  154 + val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
  155 + break;
  156 +
  157 + default: val = fpa11->fpreg[Fn].fExtended;
  158 + }
  159 +
  160 + put_user(p[0], &pMem[0]); /* sign & exp */
  161 + put_user(p[1], &pMem[2]);
  162 + put_user(p[2], &pMem[1]); /* msw */
  163 +}
  164 +
  165 +static inline
  166 +void storeMultiple(const unsigned int Fn,unsigned int *pMem)
  167 +{
  168 + FPA11 *fpa11 = GET_FPA11();
  169 + register unsigned int nType, *p;
  170 +
  171 + p = (unsigned int*)&(fpa11->fpreg[Fn]);
  172 + nType = fpa11->fType[Fn];
  173 +
  174 + switch (nType)
  175 + {
  176 + case typeSingle:
  177 + case typeDouble:
  178 + {
  179 + put_user(p[0], &pMem[2]); /* single */
  180 + put_user(p[1], &pMem[1]); /* double msw */
  181 + put_user(nType << 14, &pMem[0]);
  182 + }
  183 + break;
  184 +
  185 + case typeExtended:
  186 + {
  187 + put_user(p[2], &pMem[1]); /* msw */
  188 + put_user(p[1], &pMem[2]);
  189 + put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]);
  190 + }
  191 + break;
  192 + }
  193 +}
  194 +
  195 +unsigned int PerformLDF(const unsigned int opcode)
  196 +{
  197 + unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
  198 + write_back = WRITE_BACK(opcode);
  199 +
  200 + //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
  201 +
  202 + pBase = (unsigned int*)readRegister(getRn(opcode));
  203 + if (REG_PC == getRn(opcode))
  204 + {
  205 + pBase += 2;
  206 + write_back = 0;
  207 + }
  208 +
  209 + pFinal = pBase;
  210 + if (BIT_UP_SET(opcode))
  211 + pFinal += getOffset(opcode);
  212 + else
  213 + pFinal -= getOffset(opcode);
  214 +
  215 + if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
  216 +
  217 + switch (opcode & MASK_TRANSFER_LENGTH)
  218 + {
  219 + case TRANSFER_SINGLE : loadSingle(getFd(opcode),pAddress); break;
  220 + case TRANSFER_DOUBLE : loadDouble(getFd(opcode),pAddress); break;
  221 + case TRANSFER_EXTENDED: loadExtended(getFd(opcode),pAddress); break;
  222 + default: nRc = 0;
  223 + }
  224 +
  225 + if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
  226 + return nRc;
  227 +}
  228 +
  229 +unsigned int PerformSTF(const unsigned int opcode)
  230 +{
  231 + unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
  232 + write_back = WRITE_BACK(opcode);
  233 +
  234 + //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
  235 + SetRoundingMode(ROUND_TO_NEAREST);
  236 +
  237 + pBase = (unsigned int*)readRegister(getRn(opcode));
  238 + if (REG_PC == getRn(opcode))
  239 + {
  240 + pBase += 2;
  241 + write_back = 0;
  242 + }
  243 +
  244 + pFinal = pBase;
  245 + if (BIT_UP_SET(opcode))
  246 + pFinal += getOffset(opcode);
  247 + else
  248 + pFinal -= getOffset(opcode);
  249 +
  250 + if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
  251 +
  252 + switch (opcode & MASK_TRANSFER_LENGTH)
  253 + {
  254 + case TRANSFER_SINGLE : storeSingle(getFd(opcode),pAddress); break;
  255 + case TRANSFER_DOUBLE : storeDouble(getFd(opcode),pAddress); break;
  256 + case TRANSFER_EXTENDED: storeExtended(getFd(opcode),pAddress); break;
  257 + default: nRc = 0;
  258 + }
  259 +
  260 + if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
  261 + return nRc;
  262 +}
  263 +
  264 +unsigned int PerformLFM(const unsigned int opcode)
  265 +{
  266 + unsigned int i, Fd, *pBase, *pAddress, *pFinal,
  267 + write_back = WRITE_BACK(opcode);
  268 +
  269 + pBase = (unsigned int*)readRegister(getRn(opcode));
  270 + if (REG_PC == getRn(opcode))
  271 + {
  272 + pBase += 2;
  273 + write_back = 0;
  274 + }
  275 +
  276 + pFinal = pBase;
  277 + if (BIT_UP_SET(opcode))
  278 + pFinal += getOffset(opcode);
  279 + else
  280 + pFinal -= getOffset(opcode);
  281 +
  282 + if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
  283 +
  284 + Fd = getFd(opcode);
  285 + for (i=getRegisterCount(opcode);i>0;i--)
  286 + {
  287 + loadMultiple(Fd,pAddress);
  288 + pAddress += 3; Fd++;
  289 + if (Fd == 8) Fd = 0;
  290 + }
  291 +
  292 + if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
  293 + return 1;
  294 +}
  295 +
  296 +unsigned int PerformSFM(const unsigned int opcode)
  297 +{
  298 + unsigned int i, Fd, *pBase, *pAddress, *pFinal,
  299 + write_back = WRITE_BACK(opcode);
  300 +
  301 + pBase = (unsigned int*)readRegister(getRn(opcode));
  302 + if (REG_PC == getRn(opcode))
  303 + {
  304 + pBase += 2;
  305 + write_back = 0;
  306 + }
  307 +
  308 + pFinal = pBase;
  309 + if (BIT_UP_SET(opcode))
  310 + pFinal += getOffset(opcode);
  311 + else
  312 + pFinal -= getOffset(opcode);
  313 +
  314 + if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
  315 +
  316 + Fd = getFd(opcode);
  317 + for (i=getRegisterCount(opcode);i>0;i--)
  318 + {
  319 + storeMultiple(Fd,pAddress);
  320 + pAddress += 3; Fd++;
  321 + if (Fd == 8) Fd = 0;
  322 + }
  323 +
  324 + if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
  325 + return 1;
  326 +}
  327 +
  328 +#if 1
  329 +unsigned int EmulateCPDT(const unsigned int opcode)
  330 +{
  331 + unsigned int nRc = 0;
  332 +
  333 + //printk("EmulateCPDT(0x%08x)\n",opcode);
  334 +
  335 + if (LDF_OP(opcode))
  336 + {
  337 + nRc = PerformLDF(opcode);
  338 + }
  339 + else if (LFM_OP(opcode))
  340 + {
  341 + nRc = PerformLFM(opcode);
  342 + }
  343 + else if (STF_OP(opcode))
  344 + {
  345 + nRc = PerformSTF(opcode);
  346 + }
  347 + else if (SFM_OP(opcode))
  348 + {
  349 + nRc = PerformSFM(opcode);
  350 + }
  351 + else
  352 + {
  353 + nRc = 0;
  354 + }
  355 +
  356 + return nRc;
  357 +}
  358 +#endif
... ...
target-arm/nwfpe/fpa11_cprt.c 0 → 100644
  1 +/*
  2 + NetWinder Floating Point Emulator
  3 + (c) Rebel.COM, 1998,1999
  4 + (c) Philip Blundell, 1999
  5 +
  6 + Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
  7 +
  8 + This program is free software; you can redistribute it and/or modify
  9 + it under the terms of the GNU General Public License as published by
  10 + the Free Software Foundation; either version 2 of the License, or
  11 + (at your option) any later version.
  12 +
  13 + This program is distributed in the hope that it will be useful,
  14 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 + GNU General Public License for more details.
  17 +
  18 + You should have received a copy of the GNU General Public License
  19 + along with this program; if not, write to the Free Software
  20 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21 +*/
  22 +
  23 +#include "fpa11.h"
  24 +#include "milieu.h"
  25 +#include "softfloat.h"
  26 +#include "fpopcode.h"
  27 +#include "fpa11.inl"
  28 +//#include "fpmodule.h"
  29 +//#include "fpmodule.inl"
  30 +
  31 +extern flag floatx80_is_nan(floatx80);
  32 +extern flag float64_is_nan( float64);
  33 +extern flag float32_is_nan( float32);
  34 +
  35 +void SetRoundingMode(const unsigned int opcode);
  36 +
  37 +unsigned int PerformFLT(const unsigned int opcode);
  38 +unsigned int PerformFIX(const unsigned int opcode);
  39 +
  40 +static unsigned int
  41 +PerformComparison(const unsigned int opcode);
  42 +
  43 +unsigned int EmulateCPRT(const unsigned int opcode)
  44 +{
  45 + unsigned int nRc = 1;
  46 +
  47 + //printk("EmulateCPRT(0x%08x)\n",opcode);
  48 +
  49 + if (opcode & 0x800000)
  50 + {
  51 + /* This is some variant of a comparison (PerformComparison will
  52 + sort out which one). Since most of the other CPRT
  53 + instructions are oddball cases of some sort or other it makes
  54 + sense to pull this out into a fast path. */
  55 + return PerformComparison(opcode);
  56 + }
  57 +
  58 + /* Hint to GCC that we'd like a jump table rather than a load of CMPs */
  59 + switch ((opcode & 0x700000) >> 20)
  60 + {
  61 + case FLT_CODE >> 20: nRc = PerformFLT(opcode); break;
  62 + case FIX_CODE >> 20: nRc = PerformFIX(opcode); break;
  63 +
  64 + case WFS_CODE >> 20: writeFPSR(readRegister(getRd(opcode))); break;
  65 + case RFS_CODE >> 20: writeRegister(getRd(opcode),readFPSR()); break;
  66 +
  67 +#if 0 /* We currently have no use for the FPCR, so there's no point
  68 + in emulating it. */
  69 + case WFC_CODE >> 20: writeFPCR(readRegister(getRd(opcode)));
  70 + case RFC_CODE >> 20: writeRegister(getRd(opcode),readFPCR()); break;
  71 +#endif
  72 +
  73 + default: nRc = 0;
  74 + }
  75 +
  76 + return nRc;
  77 +}
  78 +
  79 +unsigned int PerformFLT(const unsigned int opcode)
  80 +{
  81 + FPA11 *fpa11 = GET_FPA11();
  82 +
  83 + unsigned int nRc = 1;
  84 + SetRoundingMode(opcode);
  85 +
  86 + switch (opcode & MASK_ROUNDING_PRECISION)
  87 + {
  88 + case ROUND_SINGLE:
  89 + {
  90 + fpa11->fType[getFn(opcode)] = typeSingle;
  91 + fpa11->fpreg[getFn(opcode)].fSingle =
  92 + int32_to_float32(readRegister(getRd(opcode)));
  93 + }
  94 + break;
  95 +
  96 + case ROUND_DOUBLE:
  97 + {
  98 + fpa11->fType[getFn(opcode)] = typeDouble;
  99 + fpa11->fpreg[getFn(opcode)].fDouble =
  100 + int32_to_float64(readRegister(getRd(opcode)));
  101 + }
  102 + break;
  103 +
  104 + case ROUND_EXTENDED:
  105 + {
  106 + fpa11->fType[getFn(opcode)] = typeExtended;
  107 + fpa11->fpreg[getFn(opcode)].fExtended =
  108 + int32_to_floatx80(readRegister(getRd(opcode)));
  109 + }
  110 + break;
  111 +
  112 + default: nRc = 0;
  113 + }
  114 +
  115 + return nRc;
  116 +}
  117 +
  118 +unsigned int PerformFIX(const unsigned int opcode)
  119 +{
  120 + FPA11 *fpa11 = GET_FPA11();
  121 + unsigned int nRc = 1;
  122 + unsigned int Fn = getFm(opcode);
  123 +
  124 + SetRoundingMode(opcode);
  125 +
  126 + switch (fpa11->fType[Fn])
  127 + {
  128 + case typeSingle:
  129 + {
  130 + writeRegister(getRd(opcode),
  131 + float32_to_int32(fpa11->fpreg[Fn].fSingle));
  132 + }
  133 + break;
  134 +
  135 + case typeDouble:
  136 + {
  137 + //printf("F%d is 0x%llx\n",Fn,fpa11->fpreg[Fn].fDouble);
  138 + writeRegister(getRd(opcode),
  139 + float64_to_int32(fpa11->fpreg[Fn].fDouble));
  140 + }
  141 + break;
  142 +
  143 + case typeExtended:
  144 + {
  145 + writeRegister(getRd(opcode),
  146 + floatx80_to_int32(fpa11->fpreg[Fn].fExtended));
  147 + }
  148 + break;
  149 +
  150 + default: nRc = 0;
  151 + }
  152 +
  153 + return nRc;
  154 +}
  155 +
  156 +
  157 +static unsigned int __inline__
  158 +PerformComparisonOperation(floatx80 Fn, floatx80 Fm)
  159 +{
  160 + unsigned int flags = 0;
  161 +
  162 + /* test for less than condition */
  163 + if (floatx80_lt(Fn,Fm))
  164 + {
  165 + flags |= CC_NEGATIVE;
  166 + }
  167 +
  168 + /* test for equal condition */
  169 + if (floatx80_eq(Fn,Fm))
  170 + {
  171 + flags |= CC_ZERO;
  172 + }
  173 +
  174 + /* test for greater than or equal condition */
  175 + if (floatx80_lt(Fm,Fn))
  176 + {
  177 + flags |= CC_CARRY;
  178 + }
  179 +
  180 + writeConditionCodes(flags);
  181 + return 1;
  182 +}
  183 +
  184 +/* This instruction sets the flags N, Z, C, V in the FPSR. */
  185 +
  186 +static unsigned int PerformComparison(const unsigned int opcode)
  187 +{
  188 + FPA11 *fpa11 = GET_FPA11();
  189 + unsigned int Fn, Fm;
  190 + floatx80 rFn, rFm;
  191 + int e_flag = opcode & 0x400000; /* 1 if CxFE */
  192 + int n_flag = opcode & 0x200000; /* 1 if CNxx */
  193 + unsigned int flags = 0;
  194 +
  195 + //printk("PerformComparison(0x%08x)\n",opcode);
  196 +
  197 + Fn = getFn(opcode);
  198 + Fm = getFm(opcode);
  199 +
  200 + /* Check for unordered condition and convert all operands to 80-bit
  201 + format.
  202 + ?? Might be some mileage in avoiding this conversion if possible.
  203 + Eg, if both operands are 32-bit, detect this and do a 32-bit
  204 + comparison (cheaper than an 80-bit one). */
  205 + switch (fpa11->fType[Fn])
  206 + {
  207 + case typeSingle:
  208 + //printk("single.\n");
  209 + if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
  210 + goto unordered;
  211 + rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
  212 + break;
  213 +
  214 + case typeDouble:
  215 + //printk("double.\n");
  216 + if (float64_is_nan(fpa11->fpreg[Fn].fDouble))
  217 + goto unordered;
  218 + rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
  219 + break;
  220 +
  221 + case typeExtended:
  222 + //printk("extended.\n");
  223 + if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended))
  224 + goto unordered;
  225 + rFn = fpa11->fpreg[Fn].fExtended;
  226 + break;
  227 +
  228 + default: return 0;
  229 + }
  230 +
  231 + if (CONSTANT_FM(opcode))
  232 + {
  233 + //printk("Fm is a constant: #%d.\n",Fm);
  234 + rFm = getExtendedConstant(Fm);
  235 + if (floatx80_is_nan(rFm))
  236 + goto unordered;
  237 + }
  238 + else
  239 + {
  240 + //printk("Fm = r%d which contains a ",Fm);
  241 + switch (fpa11->fType[Fm])
  242 + {
  243 + case typeSingle:
  244 + //printk("single.\n");
  245 + if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
  246 + goto unordered;
  247 + rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
  248 + break;
  249 +
  250 + case typeDouble:
  251 + //printk("double.\n");
  252 + if (float64_is_nan(fpa11->fpreg[Fm].fDouble))
  253 + goto unordered;
  254 + rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble);
  255 + break;
  256 +
  257 + case typeExtended:
  258 + //printk("extended.\n");
  259 + if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended))
  260 + goto unordered;
  261 + rFm = fpa11->fpreg[Fm].fExtended;
  262 + break;
  263 +
  264 + default: return 0;
  265 + }
  266 + }
  267 +
  268 + if (n_flag)
  269 + {
  270 + rFm.high ^= 0x8000;
  271 + }
  272 +
  273 + return PerformComparisonOperation(rFn,rFm);
  274 +
  275 + unordered:
  276 + /* ?? The FPA data sheet is pretty vague about this, in particular
  277 + about whether the non-E comparisons can ever raise exceptions.
  278 + This implementation is based on a combination of what it says in
  279 + the data sheet, observation of how the Acorn emulator actually
  280 + behaves (and how programs expect it to) and guesswork. */
  281 + flags |= CC_OVERFLOW;
  282 + flags &= ~(CC_ZERO | CC_NEGATIVE);
  283 +
  284 + if (BIT_AC & readFPSR()) flags |= CC_CARRY;
  285 +
  286 + if (e_flag) float_raise(float_flag_invalid);
  287 +
  288 + writeConditionCodes(flags);
  289 + return 1;
  290 +}
... ...
target-arm/nwfpe/fpopcode.c 0 → 100644
  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 +#include "fpsr.h"
  26 +//#include "fpmodule.h"
  27 +//#include "fpmodule.inl"
  28 +
  29 +const floatx80 floatx80Constant[] = {
  30 + { 0x0000, 0x0000000000000000ULL}, /* extended 0.0 */
  31 + { 0x3fff, 0x8000000000000000ULL}, /* extended 1.0 */
  32 + { 0x4000, 0x8000000000000000ULL}, /* extended 2.0 */
  33 + { 0x4000, 0xc000000000000000ULL}, /* extended 3.0 */
  34 + { 0x4001, 0x8000000000000000ULL}, /* extended 4.0 */
  35 + { 0x4001, 0xa000000000000000ULL}, /* extended 5.0 */
  36 + { 0x3ffe, 0x8000000000000000ULL}, /* extended 0.5 */
  37 + { 0x4002, 0xa000000000000000ULL} /* extended 10.0 */
  38 +};
  39 +
  40 +const float64 float64Constant[] = {
  41 + 0x0000000000000000ULL, /* double 0.0 */
  42 + 0x3ff0000000000000ULL, /* double 1.0 */
  43 + 0x4000000000000000ULL, /* double 2.0 */
  44 + 0x4008000000000000ULL, /* double 3.0 */
  45 + 0x4010000000000000ULL, /* double 4.0 */
  46 + 0x4014000000000000ULL, /* double 5.0 */
  47 + 0x3fe0000000000000ULL, /* double 0.5 */
  48 + 0x4024000000000000ULL /* double 10.0 */
  49 +};
  50 +
  51 +const float32 float32Constant[] = {
  52 + 0x00000000, /* single 0.0 */
  53 + 0x3f800000, /* single 1.0 */
  54 + 0x40000000, /* single 2.0 */
  55 + 0x40400000, /* single 3.0 */
  56 + 0x40800000, /* single 4.0 */
  57 + 0x40a00000, /* single 5.0 */
  58 + 0x3f000000, /* single 0.5 */
  59 + 0x41200000 /* single 10.0 */
  60 +};
  61 +
  62 +unsigned int getTransferLength(const unsigned int opcode)
  63 +{
  64 + unsigned int nRc;
  65 +
  66 + switch (opcode & MASK_TRANSFER_LENGTH)
  67 + {
  68 + case 0x00000000: nRc = 1; break; /* single precision */
  69 + case 0x00008000: nRc = 2; break; /* double precision */
  70 + case 0x00400000: nRc = 3; break; /* extended precision */
  71 + default: nRc = 0;
  72 + }
  73 +
  74 + return(nRc);
  75 +}
  76 +
  77 +unsigned int getRegisterCount(const unsigned int opcode)
  78 +{
  79 + unsigned int nRc;
  80 +
  81 + switch (opcode & MASK_REGISTER_COUNT)
  82 + {
  83 + case 0x00000000: nRc = 4; break;
  84 + case 0x00008000: nRc = 1; break;
  85 + case 0x00400000: nRc = 2; break;
  86 + case 0x00408000: nRc = 3; break;
  87 + default: nRc = 0;
  88 + }
  89 +
  90 + return(nRc);
  91 +}
  92 +
  93 +unsigned int getRoundingPrecision(const unsigned int opcode)
  94 +{
  95 + unsigned int nRc;
  96 +
  97 + switch (opcode & MASK_ROUNDING_PRECISION)
  98 + {
  99 + case 0x00000000: nRc = 1; break;
  100 + case 0x00000080: nRc = 2; break;
  101 + case 0x00080000: nRc = 3; break;
  102 + default: nRc = 0;
  103 + }
  104 +
  105 + return(nRc);
  106 +}
  107 +
  108 +unsigned int getDestinationSize(const unsigned int opcode)
  109 +{
  110 + unsigned int nRc;
  111 +
  112 + switch (opcode & MASK_DESTINATION_SIZE)
  113 + {
  114 + case 0x00000000: nRc = typeSingle; break;
  115 + case 0x00000080: nRc = typeDouble; break;
  116 + case 0x00080000: nRc = typeExtended; break;
  117 + default: nRc = typeNone;
  118 + }
  119 +
  120 + return(nRc);
  121 +}
  122 +
  123 +/* condition code lookup table
  124 + index into the table is test code: EQ, NE, ... LT, GT, AL, NV
  125 + bit position in short is condition code: NZCV */
  126 +static const unsigned short aCC[16] = {
  127 + 0xF0F0, // EQ == Z set
  128 + 0x0F0F, // NE
  129 + 0xCCCC, // CS == C set
  130 + 0x3333, // CC
  131 + 0xFF00, // MI == N set
  132 + 0x00FF, // PL
  133 + 0xAAAA, // VS == V set
  134 + 0x5555, // VC
  135 + 0x0C0C, // HI == C set && Z clear
  136 + 0xF3F3, // LS == C clear || Z set
  137 + 0xAA55, // GE == (N==V)
  138 + 0x55AA, // LT == (N!=V)
  139 + 0x0A05, // GT == (!Z && (N==V))
  140 + 0xF5FA, // LE == (Z || (N!=V))
  141 + 0xFFFF, // AL always
  142 + 0 // NV
  143 +};
  144 +
  145 +unsigned int checkCondition(const unsigned int opcode, const unsigned int ccodes)
  146 +{
  147 + return (aCC[opcode>>28] >> (ccodes>>28)) & 1;
  148 +}
... ...
target-arm/nwfpe/fpopcode.h 0 → 100644
  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 +#ifndef __FPOPCODE_H__
  23 +#define __FPOPCODE_H__
  24 +
  25 +/*
  26 +ARM Floating Point Instruction Classes
  27 +| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  28 +|c o n d|1 1 0 P|U|u|W|L| Rn |v| Fd |0|0|0|1| o f f s e t | CPDT
  29 +|c o n d|1 1 0 P|U|w|W|L| Rn |x| Fd |0|0|0|1| o f f s e t | CPDT
  30 +| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  31 +|c o n d|1 1 1 0|a|b|c|d|e| Fn |j| Fd |0|0|0|1|f|g|h|0|i| Fm | CPDO
  32 +|c o n d|1 1 1 0|a|b|c|L|e| Fn | Rd |0|0|0|1|f|g|h|1|i| Fm | CPRT
  33 +|c o n d|1 1 1 0|a|b|c|1|e| Fn |1|1|1|1|0|0|0|1|f|g|h|1|i| Fm | comparisons
  34 +| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  35 +
  36 +CPDT data transfer instructions
  37 + LDF, STF, LFM, SFM
  38 +
  39 +CPDO dyadic arithmetic instructions
  40 + ADF, MUF, SUF, RSF, DVF, RDF,
  41 + POW, RPW, RMF, FML, FDV, FRD, POL
  42 +
  43 +CPDO monadic arithmetic instructions
  44 + MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP,
  45 + SIN, COS, TAN, ASN, ACS, ATN, URD, NRM
  46 +
  47 +CPRT joint arithmetic/data transfer instructions
  48 + FIX (arithmetic followed by load/store)
  49 + FLT (load/store followed by arithmetic)
  50 + CMF, CNF CMFE, CNFE (comparisons)
  51 + WFS, RFS (write/read floating point status register)
  52 + WFC, RFC (write/read floating point control register)
  53 +
  54 +cond condition codes
  55 +P pre/post index bit: 0 = postindex, 1 = preindex
  56 +U up/down bit: 0 = stack grows down, 1 = stack grows up
  57 +W write back bit: 1 = update base register (Rn)
  58 +L load/store bit: 0 = store, 1 = load
  59 +Rn base register
  60 +Rd destination/source register
  61 +Fd floating point destination register
  62 +Fn floating point source register
  63 +Fm floating point source register or floating point constant
  64 +
  65 +uv transfer length (TABLE 1)
  66 +wx register count (TABLE 2)
  67 +abcd arithmetic opcode (TABLES 3 & 4)
  68 +ef destination size (rounding precision) (TABLE 5)
  69 +gh rounding mode (TABLE 6)
  70 +j dyadic/monadic bit: 0 = dyadic, 1 = monadic
  71 +i constant bit: 1 = constant (TABLE 6)
  72 +*/
  73 +
  74 +/*
  75 +TABLE 1
  76 ++-------------------------+---+---+---------+---------+
  77 +| Precision | u | v | FPSR.EP | length |
  78 ++-------------------------+---+---+---------+---------+
  79 +| Single | 0 ü 0 | x | 1 words |
  80 +| Double | 1 ü 1 | x | 2 words |
  81 +| Extended | 1 ü 1 | x | 3 words |
  82 +| Packed decimal | 1 ü 1 | 0 | 3 words |
  83 +| Expanded packed decimal | 1 ü 1 | 1 | 4 words |
  84 ++-------------------------+---+---+---------+---------+
  85 +Note: x = don't care
  86 +*/
  87 +
  88 +/*
  89 +TABLE 2
  90 ++---+---+---------------------------------+
  91 +| w | x | Number of registers to transfer |
  92 ++---+---+---------------------------------+
  93 +| 0 ü 1 | 1 |
  94 +| 1 ü 0 | 2 |
  95 +| 1 ü 1 | 3 |
  96 +| 0 ü 0 | 4 |
  97 ++---+---+---------------------------------+
  98 +*/
  99 +
  100 +/*
  101 +TABLE 3: Dyadic Floating Point Opcodes
  102 ++---+---+---+---+----------+-----------------------+-----------------------+
  103 +| a | b | c | d | Mnemonic | Description | Operation |
  104 ++---+---+---+---+----------+-----------------------+-----------------------+
  105 +| 0 | 0 | 0 | 0 | ADF | Add | Fd := Fn + Fm |
  106 +| 0 | 0 | 0 | 1 | MUF | Multiply | Fd := Fn * Fm |
  107 +| 0 | 0 | 1 | 0 | SUF | Subtract | Fd := Fn - Fm |
  108 +| 0 | 0 | 1 | 1 | RSF | Reverse subtract | Fd := Fm - Fn |
  109 +| 0 | 1 | 0 | 0 | DVF | Divide | Fd := Fn / Fm |
  110 +| 0 | 1 | 0 | 1 | RDF | Reverse divide | Fd := Fm / Fn |
  111 +| 0 | 1 | 1 | 0 | POW | Power | Fd := Fn ^ Fm |
  112 +| 0 | 1 | 1 | 1 | RPW | Reverse power | Fd := Fm ^ Fn |
  113 +| 1 | 0 | 0 | 0 | RMF | Remainder | Fd := IEEE rem(Fn/Fm) |
  114 +| 1 | 0 | 0 | 1 | FML | Fast Multiply | Fd := Fn * Fm |
  115 +| 1 | 0 | 1 | 0 | FDV | Fast Divide | Fd := Fn / Fm |
  116 +| 1 | 0 | 1 | 1 | FRD | Fast reverse divide | Fd := Fm / Fn |
  117 +| 1 | 1 | 0 | 0 | POL | Polar angle (ArcTan2) | Fd := arctan2(Fn,Fm) |
  118 +| 1 | 1 | 0 | 1 | | undefined instruction | trap |
  119 +| 1 | 1 | 1 | 0 | | undefined instruction | trap |
  120 +| 1 | 1 | 1 | 1 | | undefined instruction | trap |
  121 ++---+---+---+---+----------+-----------------------+-----------------------+
  122 +Note: POW, RPW, POL are deprecated, and are available for backwards
  123 + compatibility only.
  124 +*/
  125 +
  126 +/*
  127 +TABLE 4: Monadic Floating Point Opcodes
  128 ++---+---+---+---+----------+-----------------------+-----------------------+
  129 +| a | b | c | d | Mnemonic | Description | Operation |
  130 ++---+---+---+---+----------+-----------------------+-----------------------+
  131 +| 0 | 0 | 0 | 0 | MVF | Move | Fd := Fm |
  132 +| 0 | 0 | 0 | 1 | MNF | Move negated | Fd := - Fm |
  133 +| 0 | 0 | 1 | 0 | ABS | Absolute value | Fd := abs(Fm) |
  134 +| 0 | 0 | 1 | 1 | RND | Round to integer | Fd := int(Fm) |
  135 +| 0 | 1 | 0 | 0 | SQT | Square root | Fd := sqrt(Fm) |
  136 +| 0 | 1 | 0 | 1 | LOG | Log base 10 | Fd := log10(Fm) |
  137 +| 0 | 1 | 1 | 0 | LGN | Log base e | Fd := ln(Fm) |
  138 +| 0 | 1 | 1 | 1 | EXP | Exponent | Fd := e ^ Fm |
  139 +| 1 | 0 | 0 | 0 | SIN | Sine | Fd := sin(Fm) |
  140 +| 1 | 0 | 0 | 1 | COS | Cosine | Fd := cos(Fm) |
  141 +| 1 | 0 | 1 | 0 | TAN | Tangent | Fd := tan(Fm) |
  142 +| 1 | 0 | 1 | 1 | ASN | Arc Sine | Fd := arcsin(Fm) |
  143 +| 1 | 1 | 0 | 0 | ACS | Arc Cosine | Fd := arccos(Fm) |
  144 +| 1 | 1 | 0 | 1 | ATN | Arc Tangent | Fd := arctan(Fm) |
  145 +| 1 | 1 | 1 | 0 | URD | Unnormalized round | Fd := int(Fm) |
  146 +| 1 | 1 | 1 | 1 | NRM | Normalize | Fd := norm(Fm) |
  147 ++---+---+---+---+----------+-----------------------+-----------------------+
  148 +Note: LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN are deprecated, and are
  149 + available for backwards compatibility only.
  150 +*/
  151 +
  152 +/*
  153 +TABLE 5
  154 ++-------------------------+---+---+
  155 +| Rounding Precision | e | f |
  156 ++-------------------------+---+---+
  157 +| IEEE Single precision | 0 ü 0 |
  158 +| IEEE Double precision | 0 ü 1 |
  159 +| IEEE Extended precision | 1 ü 0 |
  160 +| undefined (trap) | 1 ü 1 |
  161 ++-------------------------+---+---+
  162 +*/
  163 +
  164 +/*
  165 +TABLE 5
  166 ++---------------------------------+---+---+
  167 +| Rounding Mode | g | h |
  168 ++---------------------------------+---+---+
  169 +| Round to nearest (default) | 0 ü 0 |
  170 +| Round toward plus infinity | 0 ü 1 |
  171 +| Round toward negative infinity | 1 ü 0 |
  172 +| Round toward zero | 1 ü 1 |
  173 ++---------------------------------+---+---+
  174 +*/
  175 +
  176 +/*
  177 +===
  178 +=== Definitions for load and store instructions
  179 +===
  180 +*/
  181 +
  182 +/* bit masks */
  183 +#define BIT_PREINDEX 0x01000000
  184 +#define BIT_UP 0x00800000
  185 +#define BIT_WRITE_BACK 0x00200000
  186 +#define BIT_LOAD 0x00100000
  187 +
  188 +/* masks for load/store */
  189 +#define MASK_CPDT 0x0c000000 /* data processing opcode */
  190 +#define MASK_OFFSET 0x000000ff
  191 +#define MASK_TRANSFER_LENGTH 0x00408000
  192 +#define MASK_REGISTER_COUNT MASK_TRANSFER_LENGTH
  193 +#define MASK_COPROCESSOR 0x00000f00
  194 +
  195 +/* Tests for transfer length */
  196 +#define TRANSFER_SINGLE 0x00000000
  197 +#define TRANSFER_DOUBLE 0x00008000
  198 +#define TRANSFER_EXTENDED 0x00400000
  199 +#define TRANSFER_PACKED MASK_TRANSFER_LENGTH
  200 +
  201 +/* Get the coprocessor number from the opcode. */
  202 +#define getCoprocessorNumber(opcode) ((opcode & MASK_COPROCESSOR) >> 8)
  203 +
  204 +/* Get the offset from the opcode. */
  205 +#define getOffset(opcode) (opcode & MASK_OFFSET)
  206 +
  207 +/* Tests for specific data transfer load/store opcodes. */
  208 +#define TEST_OPCODE(opcode,mask) (((opcode) & (mask)) == (mask))
  209 +
  210 +#define LOAD_OP(opcode) TEST_OPCODE((opcode),MASK_CPDT | BIT_LOAD)
  211 +#define STORE_OP(opcode) ((opcode & (MASK_CPDT | BIT_LOAD)) == MASK_CPDT)
  212 +
  213 +#define LDF_OP(opcode) (LOAD_OP(opcode) && (getCoprocessorNumber(opcode) == 1))
  214 +#define LFM_OP(opcode) (LOAD_OP(opcode) && (getCoprocessorNumber(opcode) == 2))
  215 +#define STF_OP(opcode) (STORE_OP(opcode) && (getCoprocessorNumber(opcode) == 1))
  216 +#define SFM_OP(opcode) (STORE_OP(opcode) && (getCoprocessorNumber(opcode) == 2))
  217 +
  218 +#define PREINDEXED(opcode) ((opcode & BIT_PREINDEX) != 0)
  219 +#define POSTINDEXED(opcode) ((opcode & BIT_PREINDEX) == 0)
  220 +#define BIT_UP_SET(opcode) ((opcode & BIT_UP) != 0)
  221 +#define BIT_UP_CLEAR(opcode) ((opcode & BIT_DOWN) == 0)
  222 +#define WRITE_BACK(opcode) ((opcode & BIT_WRITE_BACK) != 0)
  223 +#define LOAD(opcode) ((opcode & BIT_LOAD) != 0)
  224 +#define STORE(opcode) ((opcode & BIT_LOAD) == 0)
  225 +
  226 +/*
  227 +===
  228 +=== Definitions for arithmetic instructions
  229 +===
  230 +*/
  231 +/* bit masks */
  232 +#define BIT_MONADIC 0x00008000
  233 +#define BIT_CONSTANT 0x00000008
  234 +
  235 +#define CONSTANT_FM(opcode) ((opcode & BIT_CONSTANT) != 0)
  236 +#define MONADIC_INSTRUCTION(opcode) ((opcode & BIT_MONADIC) != 0)
  237 +
  238 +/* instruction identification masks */
  239 +#define MASK_CPDO 0x0e000000 /* arithmetic opcode */
  240 +#define MASK_ARITHMETIC_OPCODE 0x00f08000
  241 +#define MASK_DESTINATION_SIZE 0x00080080
  242 +
  243 +/* dyadic arithmetic opcodes. */
  244 +#define ADF_CODE 0x00000000
  245 +#define MUF_CODE 0x00100000
  246 +#define SUF_CODE 0x00200000
  247 +#define RSF_CODE 0x00300000
  248 +#define DVF_CODE 0x00400000
  249 +#define RDF_CODE 0x00500000
  250 +#define POW_CODE 0x00600000
  251 +#define RPW_CODE 0x00700000
  252 +#define RMF_CODE 0x00800000
  253 +#define FML_CODE 0x00900000
  254 +#define FDV_CODE 0x00a00000
  255 +#define FRD_CODE 0x00b00000
  256 +#define POL_CODE 0x00c00000
  257 +/* 0x00d00000 is an invalid dyadic arithmetic opcode */
  258 +/* 0x00e00000 is an invalid dyadic arithmetic opcode */
  259 +/* 0x00f00000 is an invalid dyadic arithmetic opcode */
  260 +
  261 +/* monadic arithmetic opcodes. */
  262 +#define MVF_CODE 0x00008000
  263 +#define MNF_CODE 0x00108000
  264 +#define ABS_CODE 0x00208000
  265 +#define RND_CODE 0x00308000
  266 +#define SQT_CODE 0x00408000
  267 +#define LOG_CODE 0x00508000
  268 +#define LGN_CODE 0x00608000
  269 +#define EXP_CODE 0x00708000
  270 +#define SIN_CODE 0x00808000
  271 +#define COS_CODE 0x00908000
  272 +#define TAN_CODE 0x00a08000
  273 +#define ASN_CODE 0x00b08000
  274 +#define ACS_CODE 0x00c08000
  275 +#define ATN_CODE 0x00d08000
  276 +#define URD_CODE 0x00e08000
  277 +#define NRM_CODE 0x00f08000
  278 +
  279 +/*
  280 +===
  281 +=== Definitions for register transfer and comparison instructions
  282 +===
  283 +*/
  284 +
  285 +#define MASK_CPRT 0x0e000010 /* register transfer opcode */
  286 +#define MASK_CPRT_CODE 0x00f00000
  287 +#define FLT_CODE 0x00000000
  288 +#define FIX_CODE 0x00100000
  289 +#define WFS_CODE 0x00200000
  290 +#define RFS_CODE 0x00300000
  291 +#define WFC_CODE 0x00400000
  292 +#define RFC_CODE 0x00500000
  293 +#define CMF_CODE 0x00900000
  294 +#define CNF_CODE 0x00b00000
  295 +#define CMFE_CODE 0x00d00000
  296 +#define CNFE_CODE 0x00f00000
  297 +
  298 +/*
  299 +===
  300 +=== Common definitions
  301 +===
  302 +*/
  303 +
  304 +/* register masks */
  305 +#define MASK_Rd 0x0000f000
  306 +#define MASK_Rn 0x000f0000
  307 +#define MASK_Fd 0x00007000
  308 +#define MASK_Fm 0x00000007
  309 +#define MASK_Fn 0x00070000
  310 +
  311 +/* condition code masks */
  312 +#define CC_MASK 0xf0000000
  313 +#define CC_NEGATIVE 0x80000000
  314 +#define CC_ZERO 0x40000000
  315 +#define CC_CARRY 0x20000000
  316 +#define CC_OVERFLOW 0x10000000
  317 +#define CC_EQ 0x00000000
  318 +#define CC_NE 0x10000000
  319 +#define CC_CS 0x20000000
  320 +#define CC_HS CC_CS
  321 +#define CC_CC 0x30000000
  322 +#define CC_LO CC_CC
  323 +#define CC_MI 0x40000000
  324 +#define CC_PL 0x50000000
  325 +#define CC_VS 0x60000000
  326 +#define CC_VC 0x70000000
  327 +#define CC_HI 0x80000000
  328 +#define CC_LS 0x90000000
  329 +#define CC_GE 0xa0000000
  330 +#define CC_LT 0xb0000000
  331 +#define CC_GT 0xc0000000
  332 +#define CC_LE 0xd0000000
  333 +#define CC_AL 0xe0000000
  334 +#define CC_NV 0xf0000000
  335 +
  336 +/* rounding masks/values */
  337 +#define MASK_ROUNDING_MODE 0x00000060
  338 +#define ROUND_TO_NEAREST 0x00000000
  339 +#define ROUND_TO_PLUS_INFINITY 0x00000020
  340 +#define ROUND_TO_MINUS_INFINITY 0x00000040
  341 +#define ROUND_TO_ZERO 0x00000060
  342 +
  343 +#define MASK_ROUNDING_PRECISION 0x00080080
  344 +#define ROUND_SINGLE 0x00000000
  345 +#define ROUND_DOUBLE 0x00000080
  346 +#define ROUND_EXTENDED 0x00080000
  347 +
  348 +/* Get the condition code from the opcode. */
  349 +#define getCondition(opcode) (opcode >> 28)
  350 +
  351 +/* Get the source register from the opcode. */
  352 +#define getRn(opcode) ((opcode & MASK_Rn) >> 16)
  353 +
  354 +/* Get the destination floating point register from the opcode. */
  355 +#define getFd(opcode) ((opcode & MASK_Fd) >> 12)
  356 +
  357 +/* Get the first source floating point register from the opcode. */
  358 +#define getFn(opcode) ((opcode & MASK_Fn) >> 16)
  359 +
  360 +/* Get the second source floating point register from the opcode. */
  361 +#define getFm(opcode) (opcode & MASK_Fm)
  362 +
  363 +/* Get the destination register from the opcode. */
  364 +#define getRd(opcode) ((opcode & MASK_Rd) >> 12)
  365 +
  366 +/* Get the rounding mode from the opcode. */
  367 +#define getRoundingMode(opcode) ((opcode & MASK_ROUNDING_MODE) >> 5)
  368 +
  369 +static inline const floatx80 getExtendedConstant(const unsigned int nIndex)
  370 +{
  371 + extern const floatx80 floatx80Constant[];
  372 + return floatx80Constant[nIndex];
  373 +}
  374 +
  375 +static inline const float64 getDoubleConstant(const unsigned int nIndex)
  376 +{
  377 + extern const float64 float64Constant[];
  378 + return float64Constant[nIndex];
  379 +}
  380 +
  381 +static inline const float32 getSingleConstant(const unsigned int nIndex)
  382 +{
  383 + extern const float32 float32Constant[];
  384 + return float32Constant[nIndex];
  385 +}
  386 +
  387 +extern unsigned int getRegisterCount(const unsigned int opcode);
  388 +extern unsigned int getDestinationSize(const unsigned int opcode);
  389 +
  390 +#endif
... ...
target-arm/nwfpe/fpsr.h 0 → 100644
  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 +#ifndef __FPSR_H__
  23 +#define __FPSR_H__
  24 +
  25 +/*
  26 +The FPSR is a 32 bit register consisting of 4 parts, each exactly
  27 +one byte.
  28 +
  29 + SYSTEM ID
  30 + EXCEPTION TRAP ENABLE BYTE
  31 + SYSTEM CONTROL BYTE
  32 + CUMULATIVE EXCEPTION FLAGS BYTE
  33 +
  34 +The FPCR is a 32 bit register consisting of bit flags.
  35 +*/
  36 +
  37 +/* SYSTEM ID
  38 +------------
  39 +Note: the system id byte is read only */
  40 +
  41 +typedef unsigned int FPSR; /* type for floating point status register */
  42 +typedef unsigned int FPCR; /* type for floating point control register */
  43 +
  44 +#define MASK_SYSID 0xff000000
  45 +#define BIT_HARDWARE 0x80000000
  46 +#define FP_EMULATOR 0x01000000 /* System ID for emulator */
  47 +#define FP_ACCELERATOR 0x81000000 /* System ID for FPA11 */
  48 +
  49 +/* EXCEPTION TRAP ENABLE BYTE
  50 +----------------------------- */
  51 +
  52 +#define MASK_TRAP_ENABLE 0x00ff0000
  53 +#define MASK_TRAP_ENABLE_STRICT 0x001f0000
  54 +#define BIT_IXE 0x00100000 /* inexact exception enable */
  55 +#define BIT_UFE 0x00080000 /* underflow exception enable */
  56 +#define BIT_OFE 0x00040000 /* overflow exception enable */
  57 +#define BIT_DZE 0x00020000 /* divide by zero exception enable */
  58 +#define BIT_IOE 0x00010000 /* invalid operation exception enable */
  59 +
  60 +/* SYSTEM CONTROL BYTE
  61 +---------------------- */
  62 +
  63 +#define MASK_SYSTEM_CONTROL 0x0000ff00
  64 +#define MASK_TRAP_STRICT 0x00001f00
  65 +
  66 +#define BIT_AC 0x00001000 /* use alternative C-flag definition
  67 + for compares */
  68 +#define BIT_EP 0x00000800 /* use expanded packed decimal format */
  69 +#define BIT_SO 0x00000400 /* select synchronous operation of FPA */
  70 +#define BIT_NE 0x00000200 /* NaN exception bit */
  71 +#define BIT_ND 0x00000100 /* no denormalized numbers bit */
  72 +
  73 +/* CUMULATIVE EXCEPTION FLAGS BYTE
  74 +---------------------------------- */
  75 +
  76 +#define MASK_EXCEPTION_FLAGS 0x000000ff
  77 +#define MASK_EXCEPTION_FLAGS_STRICT 0x0000001f
  78 +
  79 +#define BIT_IXC 0x00000010 /* inexact exception flag */
  80 +#define BIT_UFC 0x00000008 /* underflow exception flag */
  81 +#define BIT_OFC 0x00000004 /* overfloat exception flag */
  82 +#define BIT_DZC 0x00000002 /* divide by zero exception flag */
  83 +#define BIT_IOC 0x00000001 /* invalid operation exception flag */
  84 +
  85 +/* Floating Point Control Register
  86 +----------------------------------*/
  87 +
  88 +#define BIT_RU 0x80000000 /* rounded up bit */
  89 +#define BIT_IE 0x10000000 /* inexact bit */
  90 +#define BIT_MO 0x08000000 /* mantissa overflow bit */
  91 +#define BIT_EO 0x04000000 /* exponent overflow bit */
  92 +#define BIT_SB 0x00000800 /* store bounce */
  93 +#define BIT_AB 0x00000400 /* arithmetic bounce */
  94 +#define BIT_RE 0x00000200 /* rounding exception */
  95 +#define BIT_DA 0x00000100 /* disable FPA */
  96 +
  97 +#define MASK_OP 0x00f08010 /* AU operation code */
  98 +#define MASK_PR 0x00080080 /* AU precision */
  99 +#define MASK_S1 0x00070000 /* AU source register 1 */
  100 +#define MASK_S2 0x00000007 /* AU source register 2 */
  101 +#define MASK_DS 0x00007000 /* AU destination register */
  102 +#define MASK_RM 0x00000060 /* AU rounding mode */
  103 +#define MASK_ALU 0x9cfff2ff /* only ALU can write these bits */
  104 +#define MASK_RESET 0x00000d00 /* bits set on reset, all others cleared */
  105 +#define MASK_WFC MASK_RESET
  106 +#define MASK_RFC ~MASK_RESET
  107 +
  108 +#endif
... ...
target-arm/nwfpe/milieu.h 0 → 100644
  1 +
  2 +/*
  3 +===============================================================================
  4 +
  5 +This C header file is part of the SoftFloat IEC/IEEE Floating-point
  6 +Arithmetic Package, Release 2.
  7 +
  8 +Written by John R. Hauser. This work was made possible in part by the
  9 +International Computer Science Institute, located at Suite 600, 1947 Center
  10 +Street, Berkeley, California 94704. Funding was partially provided by the
  11 +National Science Foundation under grant MIP-9311980. The original version
  12 +of this code was written as part of a project to build a fixed-point vector
  13 +processor in collaboration with the University of California at Berkeley,
  14 +overseen by Profs. Nelson Morgan and John Wawrzynek. More information
  15 +is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
  16 +arithmetic/softfloat.html'.
  17 +
  18 +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
  19 +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
  20 +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
  21 +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
  22 +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
  23 +
  24 +Derivative works are acceptable, even for commercial purposes, so long as
  25 +(1) they include prominent notice that the work is derivative, and (2) they
  26 +include prominent notice akin to these three paragraphs for those parts of
  27 +this code that are retained.
  28 +
  29 +===============================================================================
  30 +*/
  31 +
  32 +/*
  33 +-------------------------------------------------------------------------------
  34 +Include common integer types and flags.
  35 +-------------------------------------------------------------------------------
  36 +*/
  37 +#include "ARM-gcc.h"
  38 +
  39 +/*
  40 +-------------------------------------------------------------------------------
  41 +Symbolic Boolean literals.
  42 +-------------------------------------------------------------------------------
  43 +*/
  44 +enum {
  45 + FALSE = 0,
  46 + TRUE = 1
  47 +};
  48 +
... ...
target-arm/nwfpe/single_cpdo.c 0 → 100644
  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 +
  26 +float32 float32_exp(float32 Fm);
  27 +float32 float32_ln(float32 Fm);
  28 +float32 float32_sin(float32 rFm);
  29 +float32 float32_cos(float32 rFm);
  30 +float32 float32_arcsin(float32 rFm);
  31 +float32 float32_arctan(float32 rFm);
  32 +float32 float32_log(float32 rFm);
  33 +float32 float32_tan(float32 rFm);
  34 +float32 float32_arccos(float32 rFm);
  35 +float32 float32_pow(float32 rFn,float32 rFm);
  36 +float32 float32_pol(float32 rFn,float32 rFm);
  37 +
  38 +unsigned int SingleCPDO(const unsigned int opcode)
  39 +{
  40 + FPA11 *fpa11 = GET_FPA11();
  41 + float32 rFm, rFn;
  42 + unsigned int Fd, Fm, Fn, nRc = 1;
  43 +
  44 + Fm = getFm(opcode);
  45 + if (CONSTANT_FM(opcode))
  46 + {
  47 + rFm = getSingleConstant(Fm);
  48 + }
  49 + else
  50 + {
  51 + switch (fpa11->fType[Fm])
  52 + {
  53 + case typeSingle:
  54 + rFm = fpa11->fpreg[Fm].fSingle;
  55 + break;
  56 +
  57 + default: return 0;
  58 + }
  59 + }
  60 +
  61 + if (!MONADIC_INSTRUCTION(opcode))
  62 + {
  63 + Fn = getFn(opcode);
  64 + switch (fpa11->fType[Fn])
  65 + {
  66 + case typeSingle:
  67 + rFn = fpa11->fpreg[Fn].fSingle;
  68 + break;
  69 +
  70 + default: return 0;
  71 + }
  72 + }
  73 +
  74 + Fd = getFd(opcode);
  75 + switch (opcode & MASK_ARITHMETIC_OPCODE)
  76 + {
  77 + /* dyadic opcodes */
  78 + case ADF_CODE:
  79 + fpa11->fpreg[Fd].fSingle = float32_add(rFn,rFm);
  80 + break;
  81 +
  82 + case MUF_CODE:
  83 + case FML_CODE:
  84 + fpa11->fpreg[Fd].fSingle = float32_mul(rFn,rFm);
  85 + break;
  86 +
  87 + case SUF_CODE:
  88 + fpa11->fpreg[Fd].fSingle = float32_sub(rFn,rFm);
  89 + break;
  90 +
  91 + case RSF_CODE:
  92 + fpa11->fpreg[Fd].fSingle = float32_sub(rFm,rFn);
  93 + break;
  94 +
  95 + case DVF_CODE:
  96 + case FDV_CODE:
  97 + fpa11->fpreg[Fd].fSingle = float32_div(rFn,rFm);
  98 + break;
  99 +
  100 + case RDF_CODE:
  101 + case FRD_CODE:
  102 + fpa11->fpreg[Fd].fSingle = float32_div(rFm,rFn);
  103 + break;
  104 +
  105 +#if 0
  106 + case POW_CODE:
  107 + fpa11->fpreg[Fd].fSingle = float32_pow(rFn,rFm);
  108 + break;
  109 +
  110 + case RPW_CODE:
  111 + fpa11->fpreg[Fd].fSingle = float32_pow(rFm,rFn);
  112 + break;
  113 +#endif
  114 +
  115 + case RMF_CODE:
  116 + fpa11->fpreg[Fd].fSingle = float32_rem(rFn,rFm);
  117 + break;
  118 +
  119 +#if 0
  120 + case POL_CODE:
  121 + fpa11->fpreg[Fd].fSingle = float32_pol(rFn,rFm);
  122 + break;
  123 +#endif
  124 +
  125 + /* monadic opcodes */
  126 + case MVF_CODE:
  127 + fpa11->fpreg[Fd].fSingle = rFm;
  128 + break;
  129 +
  130 + case MNF_CODE:
  131 + rFm ^= 0x80000000;
  132 + fpa11->fpreg[Fd].fSingle = rFm;
  133 + break;
  134 +
  135 + case ABS_CODE:
  136 + rFm &= 0x7fffffff;
  137 + fpa11->fpreg[Fd].fSingle = rFm;
  138 + break;
  139 +
  140 + case RND_CODE:
  141 + case URD_CODE:
  142 + fpa11->fpreg[Fd].fSingle = float32_round_to_int(rFm);
  143 + break;
  144 +
  145 + case SQT_CODE:
  146 + fpa11->fpreg[Fd].fSingle = float32_sqrt(rFm);
  147 + break;
  148 +
  149 +#if 0
  150 + case LOG_CODE:
  151 + fpa11->fpreg[Fd].fSingle = float32_log(rFm);
  152 + break;
  153 +
  154 + case LGN_CODE:
  155 + fpa11->fpreg[Fd].fSingle = float32_ln(rFm);
  156 + break;
  157 +
  158 + case EXP_CODE:
  159 + fpa11->fpreg[Fd].fSingle = float32_exp(rFm);
  160 + break;
  161 +
  162 + case SIN_CODE:
  163 + fpa11->fpreg[Fd].fSingle = float32_sin(rFm);
  164 + break;
  165 +
  166 + case COS_CODE:
  167 + fpa11->fpreg[Fd].fSingle = float32_cos(rFm);
  168 + break;
  169 +
  170 + case TAN_CODE:
  171 + fpa11->fpreg[Fd].fSingle = float32_tan(rFm);
  172 + break;
  173 +
  174 + case ASN_CODE:
  175 + fpa11->fpreg[Fd].fSingle = float32_arcsin(rFm);
  176 + break;
  177 +
  178 + case ACS_CODE:
  179 + fpa11->fpreg[Fd].fSingle = float32_arccos(rFm);
  180 + break;
  181 +
  182 + case ATN_CODE:
  183 + fpa11->fpreg[Fd].fSingle = float32_arctan(rFm);
  184 + break;
  185 +#endif
  186 +
  187 + case NRM_CODE:
  188 + break;
  189 +
  190 + default:
  191 + {
  192 + nRc = 0;
  193 + }
  194 + }
  195 +
  196 + if (0 != nRc) fpa11->fType[Fd] = typeSingle;
  197 + return nRc;
  198 +}
  199 +
  200 +#if 0
  201 +float32 float32_exp(float32 Fm)
  202 +{
  203 +//series
  204 +}
  205 +
  206 +float32 float32_ln(float32 Fm)
  207 +{
  208 +//series
  209 +}
  210 +
  211 +float32 float32_sin(float32 rFm)
  212 +{
  213 +//series
  214 +}
  215 +
  216 +float32 float32_cos(float32 rFm)
  217 +{
  218 +//series
  219 +}
  220 +
  221 +float32 float32_arcsin(float32 rFm)
  222 +{
  223 +//series
  224 +}
  225 +
  226 +float32 float32_arctan(float32 rFm)
  227 +{
  228 + //series
  229 +}
  230 +
  231 +float32 float32_arccos(float32 rFm)
  232 +{
  233 + //return float32_sub(halfPi,float32_arcsin(rFm));
  234 +}
  235 +
  236 +float32 float32_log(float32 rFm)
  237 +{
  238 + return float32_div(float32_ln(rFm),getSingleConstant(7));
  239 +}
  240 +
  241 +float32 float32_tan(float32 rFm)
  242 +{
  243 + return float32_div(float32_sin(rFm),float32_cos(rFm));
  244 +}
  245 +
  246 +float32 float32_pow(float32 rFn,float32 rFm)
  247 +{
  248 + return float32_exp(float32_mul(rFm,float32_ln(rFn)));
  249 +}
  250 +
  251 +float32 float32_pol(float32 rFn,float32 rFm)
  252 +{
  253 + return float32_arctan(float32_div(rFn,rFm));
  254 +}
  255 +#endif
... ...
target-arm/nwfpe/softfloat-macros 0 → 100644
  1 +
  2 +/*
  3 +===============================================================================
  4 +
  5 +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
  6 +Arithmetic Package, Release 2.
  7 +
  8 +Written by John R. Hauser. This work was made possible in part by the
  9 +International Computer Science Institute, located at Suite 600, 1947 Center
  10 +Street, Berkeley, California 94704. Funding was partially provided by the
  11 +National Science Foundation under grant MIP-9311980. The original version
  12 +of this code was written as part of a project to build a fixed-point vector
  13 +processor in collaboration with the University of California at Berkeley,
  14 +overseen by Profs. Nelson Morgan and John Wawrzynek. More information
  15 +is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
  16 +arithmetic/softfloat.html'.
  17 +
  18 +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
  19 +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
  20 +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
  21 +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
  22 +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
  23 +
  24 +Derivative works are acceptable, even for commercial purposes, so long as
  25 +(1) they include prominent notice that the work is derivative, and (2) they
  26 +include prominent notice akin to these three paragraphs for those parts of
  27 +this code that are retained.
  28 +
  29 +===============================================================================
  30 +*/
  31 +
  32 +/*
  33 +-------------------------------------------------------------------------------
  34 +Shifts `a' right by the number of bits given in `count'. If any nonzero
  35 +bits are shifted off, they are ``jammed'' into the least significant bit of
  36 +the result by setting the least significant bit to 1. The value of `count'
  37 +can be arbitrarily large; in particular, if `count' is greater than 32, the
  38 +result will be either 0 or 1, depending on whether `a' is zero or nonzero.
  39 +The result is stored in the location pointed to by `zPtr'.
  40 +-------------------------------------------------------------------------------
  41 +*/
  42 +INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
  43 +{
  44 + bits32 z;
  45 + if ( count == 0 ) {
  46 + z = a;
  47 + }
  48 + else if ( count < 32 ) {
  49 + z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 );
  50 + }
  51 + else {
  52 + z = ( a != 0 );
  53 + }
  54 + *zPtr = z;
  55 +}
  56 +
  57 +/*
  58 +-------------------------------------------------------------------------------
  59 +Shifts `a' right by the number of bits given in `count'. If any nonzero
  60 +bits are shifted off, they are ``jammed'' into the least significant bit of
  61 +the result by setting the least significant bit to 1. The value of `count'
  62 +can be arbitrarily large; in particular, if `count' is greater than 64, the
  63 +result will be either 0 or 1, depending on whether `a' is zero or nonzero.
  64 +The result is stored in the location pointed to by `zPtr'.
  65 +-------------------------------------------------------------------------------
  66 +*/
  67 +INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr )
  68 +{
  69 + bits64 z;
  70 +
  71 +// __asm__("@shift64RightJamming -- start");
  72 + if ( count == 0 ) {
  73 + z = a;
  74 + }
  75 + else if ( count < 64 ) {
  76 + z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 );
  77 + }
  78 + else {
  79 + z = ( a != 0 );
  80 + }
  81 +// __asm__("@shift64RightJamming -- end");
  82 + *zPtr = z;
  83 +}
  84 +
  85 +/*
  86 +-------------------------------------------------------------------------------
  87 +Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64
  88 +_plus_ the number of bits given in `count'. The shifted result is at most
  89 +64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The
  90 +bits shifted off form a second 64-bit result as follows: The _last_ bit
  91 +shifted off is the most-significant bit of the extra result, and the other
  92 +63 bits of the extra result are all zero if and only if _all_but_the_last_
  93 +bits shifted off were all zero. This extra result is stored in the location
  94 +pointed to by `z1Ptr'. The value of `count' can be arbitrarily large.
  95 + (This routine makes more sense if `a0' and `a1' are considered to form a
  96 +fixed-point value with binary point between `a0' and `a1'. This fixed-point
  97 +value is shifted right by the number of bits given in `count', and the
  98 +integer part of the result is returned at the location pointed to by
  99 +`z0Ptr'. The fractional part of the result may be slightly corrupted as
  100 +described above, and is returned at the location pointed to by `z1Ptr'.)
  101 +-------------------------------------------------------------------------------
  102 +*/
  103 +INLINE void
  104 + shift64ExtraRightJamming(
  105 + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
  106 +{
  107 + bits64 z0, z1;
  108 + int8 negCount = ( - count ) & 63;
  109 +
  110 + if ( count == 0 ) {
  111 + z1 = a1;
  112 + z0 = a0;
  113 + }
  114 + else if ( count < 64 ) {
  115 + z1 = ( a0<<negCount ) | ( a1 != 0 );
  116 + z0 = a0>>count;
  117 + }
  118 + else {
  119 + if ( count == 64 ) {
  120 + z1 = a0 | ( a1 != 0 );
  121 + }
  122 + else {
  123 + z1 = ( ( a0 | a1 ) != 0 );
  124 + }
  125 + z0 = 0;
  126 + }
  127 + *z1Ptr = z1;
  128 + *z0Ptr = z0;
  129 +
  130 +}
  131 +
  132 +/*
  133 +-------------------------------------------------------------------------------
  134 +Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
  135 +number of bits given in `count'. Any bits shifted off are lost. The value
  136 +of `count' can be arbitrarily large; in particular, if `count' is greater
  137 +than 128, the result will be 0. The result is broken into two 64-bit pieces
  138 +which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  139 +-------------------------------------------------------------------------------
  140 +*/
  141 +INLINE void
  142 + shift128Right(
  143 + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
  144 +{
  145 + bits64 z0, z1;
  146 + int8 negCount = ( - count ) & 63;
  147 +
  148 + if ( count == 0 ) {
  149 + z1 = a1;
  150 + z0 = a0;
  151 + }
  152 + else if ( count < 64 ) {
  153 + z1 = ( a0<<negCount ) | ( a1>>count );
  154 + z0 = a0>>count;
  155 + }
  156 + else {
  157 + z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0;
  158 + z0 = 0;
  159 + }
  160 + *z1Ptr = z1;
  161 + *z0Ptr = z0;
  162 +
  163 +}
  164 +
  165 +/*
  166 +-------------------------------------------------------------------------------
  167 +Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
  168 +number of bits given in `count'. If any nonzero bits are shifted off, they
  169 +are ``jammed'' into the least significant bit of the result by setting the
  170 +least significant bit to 1. The value of `count' can be arbitrarily large;
  171 +in particular, if `count' is greater than 128, the result will be either 0
  172 +or 1, depending on whether the concatenation of `a0' and `a1' is zero or
  173 +nonzero. The result is broken into two 64-bit pieces which are stored at
  174 +the locations pointed to by `z0Ptr' and `z1Ptr'.
  175 +-------------------------------------------------------------------------------
  176 +*/
  177 +INLINE void
  178 + shift128RightJamming(
  179 + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
  180 +{
  181 + bits64 z0, z1;
  182 + int8 negCount = ( - count ) & 63;
  183 +
  184 + if ( count == 0 ) {
  185 + z1 = a1;
  186 + z0 = a0;
  187 + }
  188 + else if ( count < 64 ) {
  189 + z1 = ( a0<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 );
  190 + z0 = a0>>count;
  191 + }
  192 + else {
  193 + if ( count == 64 ) {
  194 + z1 = a0 | ( a1 != 0 );
  195 + }
  196 + else if ( count < 128 ) {
  197 + z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 );
  198 + }
  199 + else {
  200 + z1 = ( ( a0 | a1 ) != 0 );
  201 + }
  202 + z0 = 0;
  203 + }
  204 + *z1Ptr = z1;
  205 + *z0Ptr = z0;
  206 +
  207 +}
  208 +
  209 +/*
  210 +-------------------------------------------------------------------------------
  211 +Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
  212 +by 64 _plus_ the number of bits given in `count'. The shifted result is
  213 +at most 128 nonzero bits; these are broken into two 64-bit pieces which are
  214 +stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
  215 +off form a third 64-bit result as follows: The _last_ bit shifted off is
  216 +the most-significant bit of the extra result, and the other 63 bits of the
  217 +extra result are all zero if and only if _all_but_the_last_ bits shifted off
  218 +were all zero. This extra result is stored in the location pointed to by
  219 +`z2Ptr'. The value of `count' can be arbitrarily large.
  220 + (This routine makes more sense if `a0', `a1', and `a2' are considered
  221 +to form a fixed-point value with binary point between `a1' and `a2'. This
  222 +fixed-point value is shifted right by the number of bits given in `count',
  223 +and the integer part of the result is returned at the locations pointed to
  224 +by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
  225 +corrupted as described above, and is returned at the location pointed to by
  226 +`z2Ptr'.)
  227 +-------------------------------------------------------------------------------
  228 +*/
  229 +INLINE void
  230 + shift128ExtraRightJamming(
  231 + bits64 a0,
  232 + bits64 a1,
  233 + bits64 a2,
  234 + int16 count,
  235 + bits64 *z0Ptr,
  236 + bits64 *z1Ptr,
  237 + bits64 *z2Ptr
  238 + )
  239 +{
  240 + bits64 z0, z1, z2;
  241 + int8 negCount = ( - count ) & 63;
  242 +
  243 + if ( count == 0 ) {
  244 + z2 = a2;
  245 + z1 = a1;
  246 + z0 = a0;
  247 + }
  248 + else {
  249 + if ( count < 64 ) {
  250 + z2 = a1<<negCount;
  251 + z1 = ( a0<<negCount ) | ( a1>>count );
  252 + z0 = a0>>count;
  253 + }
  254 + else {
  255 + if ( count == 64 ) {
  256 + z2 = a1;
  257 + z1 = a0;
  258 + }
  259 + else {
  260 + a2 |= a1;
  261 + if ( count < 128 ) {
  262 + z2 = a0<<negCount;
  263 + z1 = a0>>( count & 63 );
  264 + }
  265 + else {
  266 + z2 = ( count == 128 ) ? a0 : ( a0 != 0 );
  267 + z1 = 0;
  268 + }
  269 + }
  270 + z0 = 0;
  271 + }
  272 + z2 |= ( a2 != 0 );
  273 + }
  274 + *z2Ptr = z2;
  275 + *z1Ptr = z1;
  276 + *z0Ptr = z0;
  277 +
  278 +}
  279 +
  280 +/*
  281 +-------------------------------------------------------------------------------
  282 +Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
  283 +number of bits given in `count'. Any bits shifted off are lost. The value
  284 +of `count' must be less than 64. The result is broken into two 64-bit
  285 +pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  286 +-------------------------------------------------------------------------------
  287 +*/
  288 +INLINE void
  289 + shortShift128Left(
  290 + bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
  291 +{
  292 +
  293 + *z1Ptr = a1<<count;
  294 + *z0Ptr =
  295 + ( count == 0 ) ? a0 : ( a0<<count ) | ( a1>>( ( - count ) & 63 ) );
  296 +
  297 +}
  298 +
  299 +/*
  300 +-------------------------------------------------------------------------------
  301 +Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left
  302 +by the number of bits given in `count'. Any bits shifted off are lost.
  303 +The value of `count' must be less than 64. The result is broken into three
  304 +64-bit pieces which are stored at the locations pointed to by `z0Ptr',
  305 +`z1Ptr', and `z2Ptr'.
  306 +-------------------------------------------------------------------------------
  307 +*/
  308 +INLINE void
  309 + shortShift192Left(
  310 + bits64 a0,
  311 + bits64 a1,
  312 + bits64 a2,
  313 + int16 count,
  314 + bits64 *z0Ptr,
  315 + bits64 *z1Ptr,
  316 + bits64 *z2Ptr
  317 + )
  318 +{
  319 + bits64 z0, z1, z2;
  320 + int8 negCount;
  321 +
  322 + z2 = a2<<count;
  323 + z1 = a1<<count;
  324 + z0 = a0<<count;
  325 + if ( 0 < count ) {
  326 + negCount = ( ( - count ) & 63 );
  327 + z1 |= a2>>negCount;
  328 + z0 |= a1>>negCount;
  329 + }
  330 + *z2Ptr = z2;
  331 + *z1Ptr = z1;
  332 + *z0Ptr = z0;
  333 +
  334 +}
  335 +
  336 +/*
  337 +-------------------------------------------------------------------------------
  338 +Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
  339 +value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so
  340 +any carry out is lost. The result is broken into two 64-bit pieces which
  341 +are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
  342 +-------------------------------------------------------------------------------
  343 +*/
  344 +INLINE void
  345 + add128(
  346 + bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
  347 +{
  348 + bits64 z1;
  349 +
  350 + z1 = a1 + b1;
  351 + *z1Ptr = z1;
  352 + *z0Ptr = a0 + b0 + ( z1 < a1 );
  353 +
  354 +}
  355 +
  356 +/*
  357 +-------------------------------------------------------------------------------
  358 +Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the
  359 +192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
  360 +modulo 2^192, so any carry out is lost. The result is broken into three
  361 +64-bit pieces which are stored at the locations pointed to by `z0Ptr',
  362 +`z1Ptr', and `z2Ptr'.
  363 +-------------------------------------------------------------------------------
  364 +*/
  365 +INLINE void
  366 + add192(
  367 + bits64 a0,
  368 + bits64 a1,
  369 + bits64 a2,
  370 + bits64 b0,
  371 + bits64 b1,
  372 + bits64 b2,
  373 + bits64 *z0Ptr,
  374 + bits64 *z1Ptr,
  375 + bits64 *z2Ptr
  376 + )
  377 +{
  378 + bits64 z0, z1, z2;
  379 + int8 carry0, carry1;
  380 +
  381 + z2 = a2 + b2;
  382 + carry1 = ( z2 < a2 );
  383 + z1 = a1 + b1;
  384 + carry0 = ( z1 < a1 );
  385 + z0 = a0 + b0;
  386 + z1 += carry1;
  387 + z0 += ( z1 < carry1 );
  388 + z0 += carry0;
  389 + *z2Ptr = z2;
  390 + *z1Ptr = z1;
  391 + *z0Ptr = z0;
  392 +
  393 +}
  394 +
  395 +/*
  396 +-------------------------------------------------------------------------------
  397 +Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the
  398 +128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
  399 +2^128, so any borrow out (carry out) is lost. The result is broken into two
  400 +64-bit pieces which are stored at the locations pointed to by `z0Ptr' and
  401 +`z1Ptr'.
  402 +-------------------------------------------------------------------------------
  403 +*/
  404 +INLINE void
  405 + sub128(
  406 + bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
  407 +{
  408 +
  409 + *z1Ptr = a1 - b1;
  410 + *z0Ptr = a0 - b0 - ( a1 < b1 );
  411 +
  412 +}
  413 +
  414 +/*
  415 +-------------------------------------------------------------------------------
  416 +Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2'
  417 +from the 192-bit value formed by concatenating `a0', `a1', and `a2'.
  418 +Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The
  419 +result is broken into three 64-bit pieces which are stored at the locations
  420 +pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.
  421 +-------------------------------------------------------------------------------
  422 +*/
  423 +INLINE void
  424 + sub192(
  425 + bits64 a0,
  426 + bits64 a1,
  427 + bits64 a2,
  428 + bits64 b0,
  429 + bits64 b1,
  430 + bits64 b2,
  431 + bits64 *z0Ptr,
  432 + bits64 *z1Ptr,
  433 + bits64 *z2Ptr
  434 + )
  435 +{
  436 + bits64 z0, z1, z2;
  437 + int8 borrow0, borrow1;
  438 +
  439 + z2 = a2 - b2;
  440 + borrow1 = ( a2 < b2 );
  441 + z1 = a1 - b1;
  442 + borrow0 = ( a1 < b1 );
  443 + z0 = a0 - b0;
  444 + z0 -= ( z1 < borrow1 );
  445 + z1 -= borrow1;
  446 + z0 -= borrow0;
  447 + *z2Ptr = z2;
  448 + *z1Ptr = z1;
  449 + *z0Ptr = z0;
  450 +
  451 +}
  452 +
  453 +/*
  454 +-------------------------------------------------------------------------------
  455 +Multiplies `a' by `b' to obtain a 128-bit product. The product is broken
  456 +into two 64-bit pieces which are stored at the locations pointed to by
  457 +`z0Ptr' and `z1Ptr'.
  458 +-------------------------------------------------------------------------------
  459 +*/
  460 +INLINE void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr )
  461 +{
  462 + bits32 aHigh, aLow, bHigh, bLow;
  463 + bits64 z0, zMiddleA, zMiddleB, z1;
  464 +
  465 + aLow = a;
  466 + aHigh = a>>32;
  467 + bLow = b;
  468 + bHigh = b>>32;
  469 + z1 = ( (bits64) aLow ) * bLow;
  470 + zMiddleA = ( (bits64) aLow ) * bHigh;
  471 + zMiddleB = ( (bits64) aHigh ) * bLow;
  472 + z0 = ( (bits64) aHigh ) * bHigh;
  473 + zMiddleA += zMiddleB;
  474 + z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 );
  475 + zMiddleA <<= 32;
  476 + z1 += zMiddleA;
  477 + z0 += ( z1 < zMiddleA );
  478 + *z1Ptr = z1;
  479 + *z0Ptr = z0;
  480 +
  481 +}
  482 +
  483 +/*
  484 +-------------------------------------------------------------------------------
  485 +Multiplies the 128-bit value formed by concatenating `a0' and `a1' by `b' to
  486 +obtain a 192-bit product. The product is broken into three 64-bit pieces
  487 +which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
  488 +`z2Ptr'.
  489 +-------------------------------------------------------------------------------
  490 +*/
  491 +INLINE void
  492 + mul128By64To192(
  493 + bits64 a0,
  494 + bits64 a1,
  495 + bits64 b,
  496 + bits64 *z0Ptr,
  497 + bits64 *z1Ptr,
  498 + bits64 *z2Ptr
  499 + )
  500 +{
  501 + bits64 z0, z1, z2, more1;
  502 +
  503 + mul64To128( a1, b, &z1, &z2 );
  504 + mul64To128( a0, b, &z0, &more1 );
  505 + add128( z0, more1, 0, z1, &z0, &z1 );
  506 + *z2Ptr = z2;
  507 + *z1Ptr = z1;
  508 + *z0Ptr = z0;
  509 +
  510 +}
  511 +
  512 +/*
  513 +-------------------------------------------------------------------------------
  514 +Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the
  515 +128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit
  516 +product. The product is broken into four 64-bit pieces which are stored at
  517 +the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
  518 +-------------------------------------------------------------------------------
  519 +*/
  520 +INLINE void
  521 + mul128To256(
  522 + bits64 a0,
  523 + bits64 a1,
  524 + bits64 b0,
  525 + bits64 b1,
  526 + bits64 *z0Ptr,
  527 + bits64 *z1Ptr,
  528 + bits64 *z2Ptr,
  529 + bits64 *z3Ptr
  530 + )
  531 +{
  532 + bits64 z0, z1, z2, z3;
  533 + bits64 more1, more2;
  534 +
  535 + mul64To128( a1, b1, &z2, &z3 );
  536 + mul64To128( a1, b0, &z1, &more2 );
  537 + add128( z1, more2, 0, z2, &z1, &z2 );
  538 + mul64To128( a0, b0, &z0, &more1 );
  539 + add128( z0, more1, 0, z1, &z0, &z1 );
  540 + mul64To128( a0, b1, &more1, &more2 );
  541 + add128( more1, more2, 0, z2, &more1, &z2 );
  542 + add128( z0, z1, 0, more1, &z0, &z1 );
  543 + *z3Ptr = z3;
  544 + *z2Ptr = z2;
  545 + *z1Ptr = z1;
  546 + *z0Ptr = z0;
  547 +
  548 +}
  549 +
  550 +/*
  551 +-------------------------------------------------------------------------------
  552 +Returns an approximation to the 64-bit integer quotient obtained by dividing
  553 +`b' into the 128-bit value formed by concatenating `a0' and `a1'. The
  554 +divisor `b' must be at least 2^63. If q is the exact quotient truncated
  555 +toward zero, the approximation returned lies between q and q + 2 inclusive.
  556 +If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
  557 +unsigned integer is returned.
  558 +-------------------------------------------------------------------------------
  559 +*/
  560 +static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b )
  561 +{
  562 + bits64 b0, b1;
  563 + bits64 rem0, rem1, term0, term1;
  564 + bits64 z;
  565 + if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF );
  566 + b0 = b>>32;
  567 + z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32;
  568 + mul64To128( b, z, &term0, &term1 );
  569 + sub128( a0, a1, term0, term1, &rem0, &rem1 );
  570 + while ( ( (sbits64) rem0 ) < 0 ) {
  571 + z -= LIT64( 0x100000000 );
  572 + b1 = b<<32;
  573 + add128( rem0, rem1, b0, b1, &rem0, &rem1 );
  574 + }
  575 + rem0 = ( rem0<<32 ) | ( rem1>>32 );
  576 + z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0;
  577 + return z;
  578 +
  579 +}
  580 +
  581 +/*
  582 +-------------------------------------------------------------------------------
  583 +Returns an approximation to the square root of the 32-bit significand given
  584 +by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
  585 +`aExp' (the least significant bit) is 1, the integer returned approximates
  586 +2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
  587 +is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
  588 +case, the approximation returned lies strictly within +/-2 of the exact
  589 +value.
  590 +-------------------------------------------------------------------------------
  591 +*/
  592 +static bits32 estimateSqrt32( int16 aExp, bits32 a )
  593 +{
  594 + static const bits16 sqrtOddAdjustments[] = {
  595 + 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
  596 + 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
  597 + };
  598 + static const bits16 sqrtEvenAdjustments[] = {
  599 + 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
  600 + 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
  601 + };
  602 + int8 index;
  603 + bits32 z;
  604 +
  605 + index = ( a>>27 ) & 15;
  606 + if ( aExp & 1 ) {
  607 + z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ];
  608 + z = ( ( a / z )<<14 ) + ( z<<15 );
  609 + a >>= 1;
  610 + }
  611 + else {
  612 + z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ];
  613 + z = a / z + z;
  614 + z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
  615 + if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );
  616 + }
  617 + return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 );
  618 +
  619 +}
  620 +
  621 +/*
  622 +-------------------------------------------------------------------------------
  623 +Returns the number of leading 0 bits before the most-significant 1 bit
  624 +of `a'. If `a' is zero, 32 is returned.
  625 +-------------------------------------------------------------------------------
  626 +*/
  627 +static int8 countLeadingZeros32( bits32 a )
  628 +{
  629 + static const int8 countLeadingZerosHigh[] = {
  630 + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
  631 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
  632 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  633 + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  634 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  635 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  636 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  637 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  638 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  639 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  640 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  641 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  642 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  643 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  644 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  645 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  646 + };
  647 + int8 shiftCount;
  648 +
  649 + shiftCount = 0;
  650 + if ( a < 0x10000 ) {
  651 + shiftCount += 16;
  652 + a <<= 16;
  653 + }
  654 + if ( a < 0x1000000 ) {
  655 + shiftCount += 8;
  656 + a <<= 8;
  657 + }
  658 + shiftCount += countLeadingZerosHigh[ a>>24 ];
  659 + return shiftCount;
  660 +
  661 +}
  662 +
  663 +/*
  664 +-------------------------------------------------------------------------------
  665 +Returns the number of leading 0 bits before the most-significant 1 bit
  666 +of `a'. If `a' is zero, 64 is returned.
  667 +-------------------------------------------------------------------------------
  668 +*/
  669 +static int8 countLeadingZeros64( bits64 a )
  670 +{
  671 + int8 shiftCount;
  672 +
  673 + shiftCount = 0;
  674 + if ( a < ( (bits64) 1 )<<32 ) {
  675 + shiftCount += 32;
  676 + }
  677 + else {
  678 + a >>= 32;
  679 + }
  680 + shiftCount += countLeadingZeros32( a );
  681 + return shiftCount;
  682 +
  683 +}
  684 +
  685 +/*
  686 +-------------------------------------------------------------------------------
  687 +Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
  688 +is equal to the 128-bit value formed by concatenating `b0' and `b1'.
  689 +Otherwise, returns 0.
  690 +-------------------------------------------------------------------------------
  691 +*/
  692 +INLINE flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
  693 +{
  694 +
  695 + return ( a0 == b0 ) && ( a1 == b1 );
  696 +
  697 +}
  698 +
  699 +/*
  700 +-------------------------------------------------------------------------------
  701 +Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
  702 +than or equal to the 128-bit value formed by concatenating `b0' and `b1'.
  703 +Otherwise, returns 0.
  704 +-------------------------------------------------------------------------------
  705 +*/
  706 +INLINE flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
  707 +{
  708 +
  709 + return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
  710 +
  711 +}
  712 +
  713 +/*
  714 +-------------------------------------------------------------------------------
  715 +Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
  716 +than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise,
  717 +returns 0.
  718 +-------------------------------------------------------------------------------
  719 +*/
  720 +INLINE flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
  721 +{
  722 +
  723 + return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
  724 +
  725 +}
  726 +
  727 +/*
  728 +-------------------------------------------------------------------------------
  729 +Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is
  730 +not equal to the 128-bit value formed by concatenating `b0' and `b1'.
  731 +Otherwise, returns 0.
  732 +-------------------------------------------------------------------------------
  733 +*/
  734 +INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
  735 +{
  736 +
  737 + return ( a0 != b0 ) || ( a1 != b1 );
  738 +
  739 +}
  740 +
... ...
target-arm/nwfpe/softfloat-specialize 0 → 100644
  1 +
  2 +/*
  3 +===============================================================================
  4 +
  5 +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
  6 +Arithmetic Package, Release 2.
  7 +
  8 +Written by John R. Hauser. This work was made possible in part by the
  9 +International Computer Science Institute, located at Suite 600, 1947 Center
  10 +Street, Berkeley, California 94704. Funding was partially provided by the
  11 +National Science Foundation under grant MIP-9311980. The original version
  12 +of this code was written as part of a project to build a fixed-point vector
  13 +processor in collaboration with the University of California at Berkeley,
  14 +overseen by Profs. Nelson Morgan and John Wawrzynek. More information
  15 +is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
  16 +arithmetic/softfloat.html'.
  17 +
  18 +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
  19 +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
  20 +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
  21 +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
  22 +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
  23 +
  24 +Derivative works are acceptable, even for commercial purposes, so long as
  25 +(1) they include prominent notice that the work is derivative, and (2) they
  26 +include prominent notice akin to these three paragraphs for those parts of
  27 +this code that are retained.
  28 +
  29 +===============================================================================
  30 +*/
  31 +
  32 +/*
  33 +-------------------------------------------------------------------------------
  34 +Underflow tininess-detection mode, statically initialized to default value.
  35 +(The declaration in `softfloat.h' must match the `int8' type here.)
  36 +-------------------------------------------------------------------------------
  37 +*/
  38 +int8 float_detect_tininess = float_tininess_after_rounding;
  39 +
  40 +/*
  41 +-------------------------------------------------------------------------------
  42 +Raises the exceptions specified by `flags'. Floating-point traps can be
  43 +defined here if desired. It is currently not possible for such a trap to
  44 +substitute a result value. If traps are not implemented, this routine
  45 +should be simply `float_exception_flags |= flags;'.
  46 +
  47 +ScottB: November 4, 1998
  48 +Moved this function out of softfloat-specialize into fpmodule.c.
  49 +This effectively isolates all the changes required for integrating with the
  50 +Linux kernel into fpmodule.c. Porting to NetBSD should only require modifying
  51 +fpmodule.c to integrate with the NetBSD kernel (I hope!).
  52 +-------------------------------------------------------------------------------
  53 +*/
  54 +void float_raise( int8 flags )
  55 +{
  56 + float_exception_flags |= flags;
  57 +}
  58 +
  59 +/*
  60 +-------------------------------------------------------------------------------
  61 +Internal canonical NaN format.
  62 +-------------------------------------------------------------------------------
  63 +*/
  64 +typedef struct {
  65 + flag sign;
  66 + bits64 high, low;
  67 +} commonNaNT;
  68 +
  69 +/*
  70 +-------------------------------------------------------------------------------
  71 +The pattern for a default generated single-precision NaN.
  72 +-------------------------------------------------------------------------------
  73 +*/
  74 +#define float32_default_nan 0xFFFFFFFF
  75 +
  76 +/*
  77 +-------------------------------------------------------------------------------
  78 +Returns 1 if the single-precision floating-point value `a' is a NaN;
  79 +otherwise returns 0.
  80 +-------------------------------------------------------------------------------
  81 +*/
  82 +flag float32_is_nan( float32 a )
  83 +{
  84 +
  85 + return ( 0xFF000000 < (bits32) ( a<<1 ) );
  86 +
  87 +}
  88 +
  89 +/*
  90 +-------------------------------------------------------------------------------
  91 +Returns 1 if the single-precision floating-point value `a' is a signaling
  92 +NaN; otherwise returns 0.
  93 +-------------------------------------------------------------------------------
  94 +*/
  95 +flag float32_is_signaling_nan( float32 a )
  96 +{
  97 +
  98 + return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
  99 +
  100 +}
  101 +
  102 +/*
  103 +-------------------------------------------------------------------------------
  104 +Returns the result of converting the single-precision floating-point NaN
  105 +`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  106 +exception is raised.
  107 +-------------------------------------------------------------------------------
  108 +*/
  109 +static commonNaNT float32ToCommonNaN( float32 a )
  110 +{
  111 + commonNaNT z;
  112 +
  113 + if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
  114 + z.sign = a>>31;
  115 + z.low = 0;
  116 + z.high = ( (bits64) a )<<41;
  117 + return z;
  118 +
  119 +}
  120 +
  121 +/*
  122 +-------------------------------------------------------------------------------
  123 +Returns the result of converting the canonical NaN `a' to the single-
  124 +precision floating-point format.
  125 +-------------------------------------------------------------------------------
  126 +*/
  127 +static float32 commonNaNToFloat32( commonNaNT a )
  128 +{
  129 +
  130 + return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
  131 +
  132 +}
  133 +
  134 +/*
  135 +-------------------------------------------------------------------------------
  136 +Takes two single-precision floating-point values `a' and `b', one of which
  137 +is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  138 +signaling NaN, the invalid exception is raised.
  139 +-------------------------------------------------------------------------------
  140 +*/
  141 +static float32 propagateFloat32NaN( float32 a, float32 b )
  142 +{
  143 + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
  144 +
  145 + aIsNaN = float32_is_nan( a );
  146 + aIsSignalingNaN = float32_is_signaling_nan( a );
  147 + bIsNaN = float32_is_nan( b );
  148 + bIsSignalingNaN = float32_is_signaling_nan( b );
  149 + a |= 0x00400000;
  150 + b |= 0x00400000;
  151 + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
  152 + if ( aIsNaN ) {
  153 + return ( aIsSignalingNaN & bIsNaN ) ? b : a;
  154 + }
  155 + else {
  156 + return b;
  157 + }
  158 +
  159 +}
  160 +
  161 +/*
  162 +-------------------------------------------------------------------------------
  163 +The pattern for a default generated double-precision NaN.
  164 +-------------------------------------------------------------------------------
  165 +*/
  166 +#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
  167 +
  168 +/*
  169 +-------------------------------------------------------------------------------
  170 +Returns 1 if the double-precision floating-point value `a' is a NaN;
  171 +otherwise returns 0.
  172 +-------------------------------------------------------------------------------
  173 +*/
  174 +flag float64_is_nan( float64 a )
  175 +{
  176 +
  177 + return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
  178 +
  179 +}
  180 +
  181 +/*
  182 +-------------------------------------------------------------------------------
  183 +Returns 1 if the double-precision floating-point value `a' is a signaling
  184 +NaN; otherwise returns 0.
  185 +-------------------------------------------------------------------------------
  186 +*/
  187 +flag float64_is_signaling_nan( float64 a )
  188 +{
  189 +
  190 + return
  191 + ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
  192 + && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
  193 +
  194 +}
  195 +
  196 +/*
  197 +-------------------------------------------------------------------------------
  198 +Returns the result of converting the double-precision floating-point NaN
  199 +`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
  200 +exception is raised.
  201 +-------------------------------------------------------------------------------
  202 +*/
  203 +static commonNaNT float64ToCommonNaN( float64 a )
  204 +{
  205 + commonNaNT z;
  206 +
  207 + if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
  208 + z.sign = a>>63;
  209 + z.low = 0;
  210 + z.high = a<<12;
  211 + return z;
  212 +
  213 +}
  214 +
  215 +/*
  216 +-------------------------------------------------------------------------------
  217 +Returns the result of converting the canonical NaN `a' to the double-
  218 +precision floating-point format.
  219 +-------------------------------------------------------------------------------
  220 +*/
  221 +static float64 commonNaNToFloat64( commonNaNT a )
  222 +{
  223 +
  224 + return
  225 + ( ( (bits64) a.sign )<<63 )
  226 + | LIT64( 0x7FF8000000000000 )
  227 + | ( a.high>>12 );
  228 +
  229 +}
  230 +
  231 +/*
  232 +-------------------------------------------------------------------------------
  233 +Takes two double-precision floating-point values `a' and `b', one of which
  234 +is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
  235 +signaling NaN, the invalid exception is raised.
  236 +-------------------------------------------------------------------------------
  237 +*/
  238 +static float64 propagateFloat64NaN( float64 a, float64 b )
  239 +{
  240 + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
  241 +
  242 + aIsNaN = float64_is_nan( a );
  243 + aIsSignalingNaN = float64_is_signaling_nan( a );
  244 + bIsNaN = float64_is_nan( b );
  245 + bIsSignalingNaN = float64_is_signaling_nan( b );
  246 + a |= LIT64( 0x0008000000000000 );
  247 + b |= LIT64( 0x0008000000000000 );
  248 + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
  249 + if ( aIsNaN ) {
  250 + return ( aIsSignalingNaN & bIsNaN ) ? b : a;
  251 + }
  252 + else {
  253 + return b;
  254 + }
  255 +
  256 +}
  257 +
  258 +#ifdef FLOATX80
  259 +
  260 +/*
  261 +-------------------------------------------------------------------------------
  262 +The pattern for a default generated extended double-precision NaN. The
  263 +`high' and `low' values hold the most- and least-significant bits,
  264 +respectively.
  265 +-------------------------------------------------------------------------------
  266 +*/
  267 +#define floatx80_default_nan_high 0xFFFF
  268 +#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
  269 +
  270 +/*
  271 +-------------------------------------------------------------------------------
  272 +Returns 1 if the extended double-precision floating-point value `a' is a
  273 +NaN; otherwise returns 0.
  274 +-------------------------------------------------------------------------------
  275 +*/
  276 +flag floatx80_is_nan( floatx80 a )
  277 +{
  278 +
  279 + return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
  280 +
  281 +}
  282 +
  283 +/*
  284 +-------------------------------------------------------------------------------
  285 +Returns 1 if the extended double-precision floating-point value `a' is a
  286 +signaling NaN; otherwise returns 0.
  287 +-------------------------------------------------------------------------------
  288 +*/
  289 +flag floatx80_is_signaling_nan( floatx80 a )
  290 +{
  291 + //register int lr;
  292 + bits64 aLow;
  293 +
  294 + //__asm__("mov %0, lr" : : "g" (lr));
  295 + //fp_printk("floatx80_is_signalling_nan() called from 0x%08x\n",lr);
  296 + aLow = a.low & ~ LIT64( 0x4000000000000000 );
  297 + return
  298 + ( ( a.high & 0x7FFF ) == 0x7FFF )
  299 + && (bits64) ( aLow<<1 )
  300 + && ( a.low == aLow );
  301 +
  302 +}
  303 +
  304 +/*
  305 +-------------------------------------------------------------------------------
  306 +Returns the result of converting the extended double-precision floating-
  307 +point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
  308 +invalid exception is raised.
  309 +-------------------------------------------------------------------------------
  310 +*/
  311 +static commonNaNT floatx80ToCommonNaN( floatx80 a )
  312 +{
  313 + commonNaNT z;
  314 +
  315 + if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
  316 + z.sign = a.high>>15;
  317 + z.low = 0;
  318 + z.high = a.low<<1;
  319 + return z;
  320 +
  321 +}
  322 +
  323 +/*
  324 +-------------------------------------------------------------------------------
  325 +Returns the result of converting the canonical NaN `a' to the extended
  326 +double-precision floating-point format.
  327 +-------------------------------------------------------------------------------
  328 +*/
  329 +static floatx80 commonNaNToFloatx80( commonNaNT a )
  330 +{
  331 + floatx80 z;
  332 +
  333 + z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
  334 + z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
  335 + return z;
  336 +
  337 +}
  338 +
  339 +/*
  340 +-------------------------------------------------------------------------------
  341 +Takes two extended double-precision floating-point values `a' and `b', one
  342 +of which is a NaN, and returns the appropriate NaN result. If either `a' or
  343 +`b' is a signaling NaN, the invalid exception is raised.
  344 +-------------------------------------------------------------------------------
  345 +*/
  346 +static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
  347 +{
  348 + flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
  349 +
  350 + aIsNaN = floatx80_is_nan( a );
  351 + aIsSignalingNaN = floatx80_is_signaling_nan( a );
  352 + bIsNaN = floatx80_is_nan( b );
  353 + bIsSignalingNaN = floatx80_is_signaling_nan( b );
  354 + a.low |= LIT64( 0xC000000000000000 );
  355 + b.low |= LIT64( 0xC000000000000000 );
  356 + if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
  357 + if ( aIsNaN ) {
  358 + return ( aIsSignalingNaN & bIsNaN ) ? b : a;
  359 + }
  360 + else {
  361 + return b;
  362 + }
  363 +
  364 +}
  365 +
  366 +#endif
... ...