Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
double_cpdo.c
Go to the documentation of this file.
1 /*
2  NetWinder Floating Point Emulator
3  (c) Rebel.COM, 1998,1999
4 
5  Direct questions, comments to Scott Bambrough <[email protected]>
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 
28  unsigned int i[2];
29 };
30 
42 
43 static float64 float64_rsf(struct roundingData *roundData, float64 rFn, float64 rFm)
44 {
45  return float64_sub(roundData, rFm, rFn);
46 }
47 
48 static float64 float64_rdv(struct roundingData *roundData, float64 rFn, float64 rFm)
49 {
50  return float64_div(roundData, rFm, rFn);
51 }
52 
53 static float64 (*const dyadic_double[16])(struct roundingData*, float64 rFn, float64 rFm) = {
54  [ADF_CODE >> 20] = float64_add,
55  [MUF_CODE >> 20] = float64_mul,
56  [SUF_CODE >> 20] = float64_sub,
57  [RSF_CODE >> 20] = float64_rsf,
58  [DVF_CODE >> 20] = float64_div,
59  [RDF_CODE >> 20] = float64_rdv,
60  [RMF_CODE >> 20] = float64_rem,
61 
62  /* strictly, these opcodes should not be implemented */
63  [FML_CODE >> 20] = float64_mul,
64  [FDV_CODE >> 20] = float64_div,
65  [FRD_CODE >> 20] = float64_rdv,
66 };
67 
68 static float64 float64_mvf(struct roundingData *roundData,float64 rFm)
69 {
70  return rFm;
71 }
72 
73 static float64 float64_mnf(struct roundingData *roundData,float64 rFm)
74 {
75  union float64_components u;
76 
77  u.f64 = rFm;
78 #ifdef __ARMEB__
79  u.i[0] ^= 0x80000000;
80 #else
81  u.i[1] ^= 0x80000000;
82 #endif
83 
84  return u.f64;
85 }
86 
87 static float64 float64_abs(struct roundingData *roundData,float64 rFm)
88 {
89  union float64_components u;
90 
91  u.f64 = rFm;
92 #ifdef __ARMEB__
93  u.i[0] &= 0x7fffffff;
94 #else
95  u.i[1] &= 0x7fffffff;
96 #endif
97 
98  return u.f64;
99 }
100 
101 static float64 (*const monadic_double[16])(struct roundingData *, float64 rFm) = {
102  [MVF_CODE >> 20] = float64_mvf,
103  [MNF_CODE >> 20] = float64_mnf,
104  [ABS_CODE >> 20] = float64_abs,
105  [RND_CODE >> 20] = float64_round_to_int,
106  [URD_CODE >> 20] = float64_round_to_int,
107  [SQT_CODE >> 20] = float64_sqrt,
108  [NRM_CODE >> 20] = float64_mvf,
109 };
110 
111 unsigned int DoubleCPDO(struct roundingData *roundData, const unsigned int opcode, FPREG * rFd)
112 {
113  FPA11 *fpa11 = GET_FPA11();
114  float64 rFm;
115  unsigned int Fm, opc_mask_shift;
116 
117  Fm = getFm(opcode);
118  if (CONSTANT_FM(opcode)) {
119  rFm = getDoubleConstant(Fm);
120  } else {
121  switch (fpa11->fType[Fm]) {
122  case typeSingle:
123  rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle);
124  break;
125 
126  case typeDouble:
127  rFm = fpa11->fpreg[Fm].fDouble;
128  break;
129 
130  default:
131  return 0;
132  }
133  }
134 
135  opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
136  if (!MONADIC_INSTRUCTION(opcode)) {
137  unsigned int Fn = getFn(opcode);
138  float64 rFn;
139 
140  switch (fpa11->fType[Fn]) {
141  case typeSingle:
142  rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle);
143  break;
144 
145  case typeDouble:
146  rFn = fpa11->fpreg[Fn].fDouble;
147  break;
148 
149  default:
150  return 0;
151  }
152 
153  if (dyadic_double[opc_mask_shift]) {
154  rFd->fDouble = dyadic_double[opc_mask_shift](roundData, rFn, rFm);
155  } else {
156  return 0;
157  }
158  } else {
159  if (monadic_double[opc_mask_shift]) {
160  rFd->fDouble = monadic_double[opc_mask_shift](roundData, rFm);
161  } else {
162  return 0;
163  }
164  }
165 
166  return 1;
167 }