Import 2.3.16
[davej-history.git] / arch / arm / nwfpe / fpa11.c
blob3e11d5ddda8fdf884222217c325fada54cdde755
1 /*
2 NetWinder Floating Point Emulator
3 (c) Rebel.com, 1998-1999
5 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
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.
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.
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.
22 #include "config.h"
23 #include "fpa11.h"
24 #include "milieu.h"
25 #include "fpopcode.h"
27 #include "fpmodule.h"
28 #include "fpmodule.inl"
30 /* forward declarations */
31 unsigned int EmulateCPDO(const unsigned int);
32 unsigned int EmulateCPDT(const unsigned int);
33 unsigned int EmulateCPRT(const unsigned int);
35 /* Emulator registers */
36 FPA11 *fpa11;
38 /* Reset the FPA11 chip. Called to initialize and reset the emulator. */
39 void resetFPA11(void)
41 int i;
42 /* initialize the registers */
43 for (i=0;i<=7;i++)
45 fpa11->fpreg[i].fType = typeNone;
48 /* FPSR: set system id to FP_EMULATOR, clear all other bits */
49 fpa11->fpsr = FP_EMULATOR;
51 /* FPCR: set SB, AB and DA bits, clear all others */
52 #if MAINTAIN_FPCR
53 fpa11->fpcr = MASK_RESET;
54 #endif
57 void SetRoundingMode(const unsigned int opcode)
59 #if MAINTAIN_FPCR
60 fpa11->fpcr &= ~MASK_ROUNDING_MODE;
61 #endif
62 switch (opcode & MASK_ROUNDING_MODE)
64 default:
65 case ROUND_TO_NEAREST:
66 float_rounding_mode = float_round_nearest_even;
67 #if MAINTAIN_FPCR
68 fpa11->fpcr |= ROUND_TO_NEAREST;
69 #endif
70 break;
72 case ROUND_TO_PLUS_INFINITY:
73 float_rounding_mode = float_round_up;
74 #if MAINTAIN_FPCR
75 fpa11->fpcr |= ROUND_TO_PLUS_INFINITY;
76 #endif
77 break;
79 case ROUND_TO_MINUS_INFINITY:
80 float_rounding_mode = float_round_down;
81 #if MAINTAIN_FPCR
82 fpa11->fpcr |= ROUND_TO_MINUS_INFINITY;
83 #endif
84 break;
86 case ROUND_TO_ZERO:
87 float_rounding_mode = float_round_to_zero;
88 #if MAINTAIN_FPCR
89 fpa11->fpcr |= ROUND_TO_ZERO;
90 #endif
91 break;
95 void SetRoundingPrecision(const unsigned int opcode)
97 #if MAINTAIN_FPCR
98 fpa11->fpcr &= ~MASK_ROUNDING_PRECISION;
99 #endif
100 switch (opcode & MASK_ROUNDING_PRECISION)
102 case ROUND_SINGLE:
103 floatx80_rounding_precision = 32;
104 #if MAINTAIN_FPCR
105 fpa11->fpcr |= ROUND_SINGLE;
106 #endif
107 break;
109 case ROUND_DOUBLE:
110 floatx80_rounding_precision = 64;
111 #if MAINTAIN_FPCR
112 fpa11->fpcr |= ROUND_DOUBLE;
113 #endif
114 break;
116 case ROUND_EXTENDED:
117 floatx80_rounding_precision = 80;
118 #if MAINTAIN_FPCR
119 fpa11->fpcr |= ROUND_EXTENDED;
120 #endif
121 break;
123 default: floatx80_rounding_precision = 80;
127 /* Emulate the instruction in the opcode. */
128 unsigned int EmulateAll(unsigned int opcode)
130 unsigned int nRc = 0;
132 if (fpa11->initflag == 0) /* good place for __builtin_expect */
134 resetFPA11();
135 SetRoundingMode(ROUND_TO_NEAREST);
136 SetRoundingPrecision(ROUND_EXTENDED);
137 fpa11->initflag = 1;
140 if (TEST_OPCODE(opcode,MASK_CPRT))
142 /* Emulate conversion opcodes. */
143 /* Emulate register transfer opcodes. */
144 /* Emulate comparison opcodes. */
145 nRc = EmulateCPRT(opcode);
147 else if (TEST_OPCODE(opcode,MASK_CPDO))
149 /* Emulate monadic arithmetic opcodes. */
150 /* Emulate dyadic arithmetic opcodes. */
151 nRc = EmulateCPDO(opcode);
153 else if (TEST_OPCODE(opcode,MASK_CPDT))
155 /* Emulate load/store opcodes. */
156 /* Emulate load/store multiple opcodes. */
157 nRc = EmulateCPDT(opcode);
159 else
161 /* Invalid instruction detected. Return FALSE. */
162 nRc = 0;
165 return(nRc);
168 #if 0
169 unsigned int EmulateAll1(unsigned int opcode)
171 switch ((opcode >> 24) & 0xf)
173 case 0xc:
174 case 0xd:
175 if ((opcode >> 20) & 0x1)
177 switch ((opcode >> 8) & 0xf)
179 case 0x1: return PerformLDF(opcode); break;
180 case 0x2: return PerformLFM(opcode); break;
181 default: return 0;
184 else
186 switch ((opcode >> 8) & 0xf)
188 case 0x1: return PerformSTF(opcode); break;
189 case 0x2: return PerformSFM(opcode); break;
190 default: return 0;
193 break;
195 case 0xe:
196 if (opcode & 0x10)
197 return EmulateCPDO(opcode);
198 else
199 return EmulateCPRT(opcode);
200 break;
202 default: return 0;
205 #endif