]> git.proxmox.com Git - mirror_qemu.git/blame - target-arm/nwfpe/fpa11_cpdt.c
find -type f | xargs sed -i 's/[\t ]$//g' # on most files
[mirror_qemu.git] / target-arm / nwfpe / fpa11_cpdt.c
CommitLineData
00406dff
FB
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
31static inline
32void loadSingle(const unsigned int Fn,const unsigned int *pMem)
33{
53a5960a 34 target_ulong addr = (target_ulong)(long)pMem;
00406dff
FB
35 FPA11 *fpa11 = GET_FPA11();
36 fpa11->fType[Fn] = typeSingle;
53a5960a 37 fpa11->fpreg[Fn].fSingle = tget32(addr);
00406dff
FB
38}
39
40static inline
41void loadDouble(const unsigned int Fn,const unsigned int *pMem)
42{
53a5960a 43 target_ulong addr = (target_ulong)(long)pMem;
00406dff
FB
44 FPA11 *fpa11 = GET_FPA11();
45 unsigned int *p;
46 p = (unsigned int*)&fpa11->fpreg[Fn].fDouble;
47 fpa11->fType[Fn] = typeDouble;
a8d3431a 48#ifdef WORDS_BIGENDIAN
53a5960a
PB
49 p[0] = tget32(addr); /* sign & exponent */
50 p[1] = tget32(addr + 4);
a8d3431a 51#else
53a5960a
PB
52 p[0] = tget32(addr + 4);
53 p[1] = tget32(addr); /* sign & exponent */
a8d3431a 54#endif
5fafdf24 55}
00406dff
FB
56
57static inline
58void loadExtended(const unsigned int Fn,const unsigned int *pMem)
59{
53a5960a 60 target_ulong addr = (target_ulong)(long)pMem;
00406dff
FB
61 FPA11 *fpa11 = GET_FPA11();
62 unsigned int *p;
63 p = (unsigned int*)&fpa11->fpreg[Fn].fExtended;
64 fpa11->fType[Fn] = typeExtended;
53a5960a
PB
65 p[0] = tget32(addr); /* sign & exponent */
66 p[1] = tget32(addr + 8); /* ls bits */
67 p[2] = tget32(addr + 4); /* ms bits */
5fafdf24 68}
00406dff
FB
69
70static inline
71void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
72{
53a5960a 73 target_ulong addr = (target_ulong)(long)pMem;
00406dff
FB
74 FPA11 *fpa11 = GET_FPA11();
75 register unsigned int *p;
76 unsigned long x;
77
78 p = (unsigned int*)&(fpa11->fpreg[Fn]);
53a5960a 79 x = tget32(addr);
00406dff 80 fpa11->fType[Fn] = (x >> 14) & 0x00000003;
5fafdf24 81
00406dff
FB
82 switch (fpa11->fType[Fn])
83 {
84 case typeSingle:
85 case typeDouble:
86 {
53a5960a
PB
87 p[0] = tget32(addr + 8); /* Single */
88 p[1] = tget32(addr + 4); /* double msw */
00406dff
FB
89 p[2] = 0; /* empty */
90 }
5fafdf24
TS
91 break;
92
00406dff
FB
93 case typeExtended:
94 {
53a5960a
PB
95 p[1] = tget32(addr + 8);
96 p[2] = tget32(addr + 4); /* msw */
5fafdf24 97 p[0] = (x & 0x80003fff);
00406dff
FB
98 }
99 break;
100 }
101}
102
103static inline
104void storeSingle(const unsigned int Fn,unsigned int *pMem)
105{
53a5960a 106 target_ulong addr = (target_ulong)(long)pMem;
00406dff
FB
107 FPA11 *fpa11 = GET_FPA11();
108 float32 val;
109 register unsigned int *p = (unsigned int*)&val;
5fafdf24 110
00406dff
FB
111 switch (fpa11->fType[Fn])
112 {
5fafdf24 113 case typeDouble:
20495218 114 val = float64_to_float32(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
00406dff
FB
115 break;
116
5fafdf24 117 case typeExtended:
20495218 118 val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
00406dff
FB
119 break;
120
121 default: val = fpa11->fpreg[Fn].fSingle;
122 }
5fafdf24 123
53a5960a 124 tput32(addr, p[0]);
5fafdf24 125}
00406dff
FB
126
127static inline
128void storeDouble(const unsigned int Fn,unsigned int *pMem)
129{
53a5960a 130 target_ulong addr = (target_ulong)(long)pMem;
00406dff
FB
131 FPA11 *fpa11 = GET_FPA11();
132 float64 val;
133 register unsigned int *p = (unsigned int*)&val;
134
135 switch (fpa11->fType[Fn])
136 {
5fafdf24 137 case typeSingle:
20495218 138 val = float32_to_float64(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
00406dff
FB
139 break;
140
141 case typeExtended:
20495218 142 val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
00406dff
FB
143 break;
144
145 default: val = fpa11->fpreg[Fn].fDouble;
146 }
a8d3431a 147#ifdef WORDS_BIGENDIAN
53a5960a
PB
148 tput32(addr, p[0]); /* msw */
149 tput32(addr + 4, p[1]); /* lsw */
a8d3431a 150#else
53a5960a
PB
151 tput32(addr, p[1]); /* msw */
152 tput32(addr + 4, p[0]); /* lsw */
a8d3431a 153#endif
5fafdf24 154}
00406dff
FB
155
156static inline
157void storeExtended(const unsigned int Fn,unsigned int *pMem)
158{
53a5960a 159 target_ulong addr = (target_ulong)(long)pMem;
00406dff
FB
160 FPA11 *fpa11 = GET_FPA11();
161 floatx80 val;
162 register unsigned int *p = (unsigned int*)&val;
5fafdf24 163
00406dff
FB
164 switch (fpa11->fType[Fn])
165 {
5fafdf24 166 case typeSingle:
20495218 167 val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
00406dff
FB
168 break;
169
5fafdf24 170 case typeDouble:
20495218 171 val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
00406dff
FB
172 break;
173
174 default: val = fpa11->fpreg[Fn].fExtended;
175 }
5fafdf24 176
53a5960a
PB
177 tput32(addr, p[0]); /* sign & exp */
178 tput32(addr + 8, p[1]);
179 tput32(addr + 4, p[2]); /* msw */
5fafdf24 180}
00406dff
FB
181
182static inline
183void storeMultiple(const unsigned int Fn,unsigned int *pMem)
184{
53a5960a 185 target_ulong addr = (target_ulong)(long)pMem;
00406dff
FB
186 FPA11 *fpa11 = GET_FPA11();
187 register unsigned int nType, *p;
5fafdf24 188
00406dff
FB
189 p = (unsigned int*)&(fpa11->fpreg[Fn]);
190 nType = fpa11->fType[Fn];
5fafdf24 191
00406dff
FB
192 switch (nType)
193 {
194 case typeSingle:
195 case typeDouble:
196 {
53a5960a
PB
197 tput32(addr + 8, p[0]); /* single */
198 tput32(addr + 4, p[1]); /* double msw */
199 tput32(addr, nType << 14);
00406dff 200 }
5fafdf24
TS
201 break;
202
00406dff
FB
203 case typeExtended:
204 {
53a5960a
PB
205 tput32(addr + 4, p[2]); /* msw */
206 tput32(addr + 8, p[1]);
207 tput32(addr, (p[0] & 0x80003fff) | (nType << 14));
00406dff
FB
208 }
209 break;
210 }
211}
212
213unsigned int PerformLDF(const unsigned int opcode)
214{
215 unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
216 write_back = WRITE_BACK(opcode);
217
218 //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
219
220 pBase = (unsigned int*)readRegister(getRn(opcode));
221 if (REG_PC == getRn(opcode))
222 {
223 pBase += 2;
224 write_back = 0;
225 }
226
227 pFinal = pBase;
228 if (BIT_UP_SET(opcode))
229 pFinal += getOffset(opcode);
230 else
231 pFinal -= getOffset(opcode);
232
233 if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
234
235 switch (opcode & MASK_TRANSFER_LENGTH)
236 {
237 case TRANSFER_SINGLE : loadSingle(getFd(opcode),pAddress); break;
238 case TRANSFER_DOUBLE : loadDouble(getFd(opcode),pAddress); break;
239 case TRANSFER_EXTENDED: loadExtended(getFd(opcode),pAddress); break;
240 default: nRc = 0;
241 }
5fafdf24 242
00406dff
FB
243 if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
244 return nRc;
245}
246
247unsigned int PerformSTF(const unsigned int opcode)
248{
249 unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
250 write_back = WRITE_BACK(opcode);
5fafdf24 251
00406dff
FB
252 //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
253 SetRoundingMode(ROUND_TO_NEAREST);
5fafdf24 254
00406dff
FB
255 pBase = (unsigned int*)readRegister(getRn(opcode));
256 if (REG_PC == getRn(opcode))
257 {
258 pBase += 2;
259 write_back = 0;
260 }
261
262 pFinal = pBase;
263 if (BIT_UP_SET(opcode))
264 pFinal += getOffset(opcode);
265 else
266 pFinal -= getOffset(opcode);
267
268 if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
269
270 switch (opcode & MASK_TRANSFER_LENGTH)
271 {
272 case TRANSFER_SINGLE : storeSingle(getFd(opcode),pAddress); break;
273 case TRANSFER_DOUBLE : storeDouble(getFd(opcode),pAddress); break;
274 case TRANSFER_EXTENDED: storeExtended(getFd(opcode),pAddress); break;
275 default: nRc = 0;
276 }
5fafdf24 277
00406dff
FB
278 if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
279 return nRc;
280}
281
282unsigned int PerformLFM(const unsigned int opcode)
283{
284 unsigned int i, Fd, *pBase, *pAddress, *pFinal,
285 write_back = WRITE_BACK(opcode);
286
287 pBase = (unsigned int*)readRegister(getRn(opcode));
288 if (REG_PC == getRn(opcode))
289 {
290 pBase += 2;
291 write_back = 0;
292 }
293
294 pFinal = pBase;
295 if (BIT_UP_SET(opcode))
296 pFinal += getOffset(opcode);
297 else
298 pFinal -= getOffset(opcode);
299
300 if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
301
302 Fd = getFd(opcode);
303 for (i=getRegisterCount(opcode);i>0;i--)
304 {
305 loadMultiple(Fd,pAddress);
306 pAddress += 3; Fd++;
307 if (Fd == 8) Fd = 0;
308 }
309
310 if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
311 return 1;
312}
313
314unsigned int PerformSFM(const unsigned int opcode)
315{
316 unsigned int i, Fd, *pBase, *pAddress, *pFinal,
317 write_back = WRITE_BACK(opcode);
5fafdf24 318
00406dff
FB
319 pBase = (unsigned int*)readRegister(getRn(opcode));
320 if (REG_PC == getRn(opcode))
321 {
322 pBase += 2;
323 write_back = 0;
324 }
5fafdf24 325
00406dff
FB
326 pFinal = pBase;
327 if (BIT_UP_SET(opcode))
328 pFinal += getOffset(opcode);
329 else
330 pFinal -= getOffset(opcode);
331
332 if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
333
334 Fd = getFd(opcode);
335 for (i=getRegisterCount(opcode);i>0;i--)
336 {
337 storeMultiple(Fd,pAddress);
338 pAddress += 3; Fd++;
339 if (Fd == 8) Fd = 0;
340 }
341
342 if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
343 return 1;
344}
345
346#if 1
347unsigned int EmulateCPDT(const unsigned int opcode)
348{
349 unsigned int nRc = 0;
350
351 //printk("EmulateCPDT(0x%08x)\n",opcode);
5fafdf24 352
00406dff
FB
353 if (LDF_OP(opcode))
354 {
355 nRc = PerformLDF(opcode);
356 }
357 else if (LFM_OP(opcode))
358 {
359 nRc = PerformLFM(opcode);
360 }
361 else if (STF_OP(opcode))
362 {
363 nRc = PerformSTF(opcode);
5fafdf24 364 }
00406dff
FB
365 else if (SFM_OP(opcode))
366 {
367 nRc = PerformSFM(opcode);
368 }
369 else
370 {
371 nRc = 0;
372 }
5fafdf24 373
00406dff
FB
374 return nRc;
375}
376#endif