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