darwin fix
[qemu/mdroth.git] / target-arm / nwfpe / fpa11_cpdt.c
blob914a86fbc07cdbbd4bbd13d20cf001bdd5884e02
1 /*
2 NetWinder Floating Point Emulator
3 (c) Rebel.com, 1998-1999
4 (c) Philip Blundell, 1998
6 Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
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.
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.
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.
23 #include "fpa11.h"
24 #include "softfloat.h"
25 #include "fpopcode.h"
26 //#include "fpmodule.h"
27 //#include "fpmodule.inl"
29 //#include <asm/uaccess.h>
31 static inline
32 void loadSingle(const unsigned int Fn,const unsigned int *pMem)
34 target_ulong addr = (target_ulong)(long)pMem;
35 FPA11 *fpa11 = GET_FPA11();
36 fpa11->fType[Fn] = typeSingle;
37 fpa11->fpreg[Fn].fSingle = tget32(addr);
40 static inline
41 void loadDouble(const unsigned int Fn,const unsigned int *pMem)
43 target_ulong addr = (target_ulong)(long)pMem;
44 FPA11 *fpa11 = GET_FPA11();
45 unsigned int *p;
46 p = (unsigned int*)&fpa11->fpreg[Fn].fDouble;
47 fpa11->fType[Fn] = typeDouble;
48 #ifdef WORDS_BIGENDIAN
49 p[0] = tget32(addr); /* sign & exponent */
50 p[1] = tget32(addr + 4);
51 #else
52 p[0] = tget32(addr + 4);
53 p[1] = tget32(addr); /* sign & exponent */
54 #endif
57 static inline
58 void loadExtended(const unsigned int Fn,const unsigned int *pMem)
60 target_ulong addr = (target_ulong)(long)pMem;
61 FPA11 *fpa11 = GET_FPA11();
62 unsigned int *p;
63 p = (unsigned int*)&fpa11->fpreg[Fn].fExtended;
64 fpa11->fType[Fn] = typeExtended;
65 p[0] = tget32(addr); /* sign & exponent */
66 p[1] = tget32(addr + 8); /* ls bits */
67 p[2] = tget32(addr + 4); /* ms bits */
70 static inline
71 void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
73 target_ulong addr = (target_ulong)(long)pMem;
74 FPA11 *fpa11 = GET_FPA11();
75 register unsigned int *p;
76 unsigned long x;
78 p = (unsigned int*)&(fpa11->fpreg[Fn]);
79 x = tget32(addr);
80 fpa11->fType[Fn] = (x >> 14) & 0x00000003;
82 switch (fpa11->fType[Fn])
84 case typeSingle:
85 case typeDouble:
87 p[0] = tget32(addr + 8); /* Single */
88 p[1] = tget32(addr + 4); /* double msw */
89 p[2] = 0; /* empty */
91 break;
93 case typeExtended:
95 p[1] = tget32(addr + 8);
96 p[2] = tget32(addr + 4); /* msw */
97 p[0] = (x & 0x80003fff);
99 break;
103 static inline
104 void storeSingle(const unsigned int Fn,unsigned int *pMem)
106 target_ulong addr = (target_ulong)(long)pMem;
107 FPA11 *fpa11 = GET_FPA11();
108 float32 val;
109 register unsigned int *p = (unsigned int*)&val;
111 switch (fpa11->fType[Fn])
113 case typeDouble:
114 val = float64_to_float32(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
115 break;
117 case typeExtended:
118 val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
119 break;
121 default: val = fpa11->fpreg[Fn].fSingle;
124 tput32(addr, p[0]);
127 static inline
128 void storeDouble(const unsigned int Fn,unsigned int *pMem)
130 target_ulong addr = (target_ulong)(long)pMem;
131 FPA11 *fpa11 = GET_FPA11();
132 float64 val;
133 register unsigned int *p = (unsigned int*)&val;
135 switch (fpa11->fType[Fn])
137 case typeSingle:
138 val = float32_to_float64(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
139 break;
141 case typeExtended:
142 val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
143 break;
145 default: val = fpa11->fpreg[Fn].fDouble;
147 #ifdef WORDS_BIGENDIAN
148 tput32(addr, p[0]); /* msw */
149 tput32(addr + 4, p[1]); /* lsw */
150 #else
151 tput32(addr, p[1]); /* msw */
152 tput32(addr + 4, p[0]); /* lsw */
153 #endif
156 static inline
157 void storeExtended(const unsigned int Fn,unsigned int *pMem)
159 target_ulong addr = (target_ulong)(long)pMem;
160 FPA11 *fpa11 = GET_FPA11();
161 floatx80 val;
162 register unsigned int *p = (unsigned int*)&val;
164 switch (fpa11->fType[Fn])
166 case typeSingle:
167 val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
168 break;
170 case typeDouble:
171 val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
172 break;
174 default: val = fpa11->fpreg[Fn].fExtended;
177 tput32(addr, p[0]); /* sign & exp */
178 tput32(addr + 8, p[1]);
179 tput32(addr + 4, p[2]); /* msw */
182 static inline
183 void storeMultiple(const unsigned int Fn,unsigned int *pMem)
185 target_ulong addr = (target_ulong)(long)pMem;
186 FPA11 *fpa11 = GET_FPA11();
187 register unsigned int nType, *p;
189 p = (unsigned int*)&(fpa11->fpreg[Fn]);
190 nType = fpa11->fType[Fn];
192 switch (nType)
194 case typeSingle:
195 case typeDouble:
197 tput32(addr + 8, p[0]); /* single */
198 tput32(addr + 4, p[1]); /* double msw */
199 tput32(addr, nType << 14);
201 break;
203 case typeExtended:
205 tput32(addr + 4, p[2]); /* msw */
206 tput32(addr + 8, p[1]);
207 tput32(addr, (p[0] & 0x80003fff) | (nType << 14));
209 break;
213 unsigned int PerformLDF(const unsigned int opcode)
215 unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
216 write_back = WRITE_BACK(opcode);
218 //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
220 pBase = (unsigned int*)readRegister(getRn(opcode));
221 if (REG_PC == getRn(opcode))
223 pBase += 2;
224 write_back = 0;
227 pFinal = pBase;
228 if (BIT_UP_SET(opcode))
229 pFinal += getOffset(opcode);
230 else
231 pFinal -= getOffset(opcode);
233 if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
235 switch (opcode & MASK_TRANSFER_LENGTH)
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;
243 if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
244 return nRc;
247 unsigned int PerformSTF(const unsigned int opcode)
249 unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
250 write_back = WRITE_BACK(opcode);
252 //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
253 SetRoundingMode(ROUND_TO_NEAREST);
255 pBase = (unsigned int*)readRegister(getRn(opcode));
256 if (REG_PC == getRn(opcode))
258 pBase += 2;
259 write_back = 0;
262 pFinal = pBase;
263 if (BIT_UP_SET(opcode))
264 pFinal += getOffset(opcode);
265 else
266 pFinal -= getOffset(opcode);
268 if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
270 switch (opcode & MASK_TRANSFER_LENGTH)
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;
278 if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
279 return nRc;
282 unsigned int PerformLFM(const unsigned int opcode)
284 unsigned int i, Fd, *pBase, *pAddress, *pFinal,
285 write_back = WRITE_BACK(opcode);
287 pBase = (unsigned int*)readRegister(getRn(opcode));
288 if (REG_PC == getRn(opcode))
290 pBase += 2;
291 write_back = 0;
294 pFinal = pBase;
295 if (BIT_UP_SET(opcode))
296 pFinal += getOffset(opcode);
297 else
298 pFinal -= getOffset(opcode);
300 if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
302 Fd = getFd(opcode);
303 for (i=getRegisterCount(opcode);i>0;i--)
305 loadMultiple(Fd,pAddress);
306 pAddress += 3; Fd++;
307 if (Fd == 8) Fd = 0;
310 if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
311 return 1;
314 unsigned int PerformSFM(const unsigned int opcode)
316 unsigned int i, Fd, *pBase, *pAddress, *pFinal,
317 write_back = WRITE_BACK(opcode);
319 pBase = (unsigned int*)readRegister(getRn(opcode));
320 if (REG_PC == getRn(opcode))
322 pBase += 2;
323 write_back = 0;
326 pFinal = pBase;
327 if (BIT_UP_SET(opcode))
328 pFinal += getOffset(opcode);
329 else
330 pFinal -= getOffset(opcode);
332 if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
334 Fd = getFd(opcode);
335 for (i=getRegisterCount(opcode);i>0;i--)
337 storeMultiple(Fd,pAddress);
338 pAddress += 3; Fd++;
339 if (Fd == 8) Fd = 0;
342 if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
343 return 1;
346 #if 1
347 unsigned int EmulateCPDT(const unsigned int opcode)
349 unsigned int nRc = 0;
351 //printk("EmulateCPDT(0x%08x)\n",opcode);
353 if (LDF_OP(opcode))
355 nRc = PerformLDF(opcode);
357 else if (LFM_OP(opcode))
359 nRc = PerformLFM(opcode);
361 else if (STF_OP(opcode))
363 nRc = PerformSTF(opcode);
365 else if (SFM_OP(opcode))
367 nRc = PerformSFM(opcode);
369 else
371 nRc = 0;
374 return nRc;
376 #endif