Fix texinfo syntax errors.
[qemu/mini2440/sniper_sniper_test.git] / linux-user / arm / nwfpe / fpa11_cpdt.c
blob41877dfe826c946af9d3639e74adf675de19c441
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 /* FIXME - handle failure of get_user() */
38 get_user_u32(fpa11->fpreg[Fn].fSingle, addr);
41 static inline
42 void loadDouble(const unsigned int Fn,const unsigned int *pMem)
44 target_ulong addr = (target_ulong)(long)pMem;
45 FPA11 *fpa11 = GET_FPA11();
46 unsigned int *p;
47 p = (unsigned int*)&fpa11->fpreg[Fn].fDouble;
48 fpa11->fType[Fn] = typeDouble;
49 #ifdef WORDS_BIGENDIAN
50 /* FIXME - handle failure of get_user() */
51 get_user_u32(p[0], addr); /* sign & exponent */
52 get_user_u32(p[1], addr + 4);
53 #else
54 /* FIXME - handle failure of get_user() */
55 get_user_u32(p[0], addr + 4);
56 get_user_u32(p[1], addr); /* sign & exponent */
57 #endif
60 static inline
61 void loadExtended(const unsigned int Fn,const unsigned int *pMem)
63 target_ulong addr = (target_ulong)(long)pMem;
64 FPA11 *fpa11 = GET_FPA11();
65 unsigned int *p;
66 p = (unsigned int*)&fpa11->fpreg[Fn].fExtended;
67 fpa11->fType[Fn] = typeExtended;
68 /* FIXME - handle failure of get_user() */
69 get_user_u32(p[0], addr); /* sign & exponent */
70 get_user_u32(p[1], addr + 8); /* ls bits */
71 get_user_u32(p[2], addr + 4); /* ms bits */
74 static inline
75 void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
77 target_ulong addr = (target_ulong)(long)pMem;
78 FPA11 *fpa11 = GET_FPA11();
79 register unsigned int *p;
80 unsigned long x;
82 p = (unsigned int*)&(fpa11->fpreg[Fn]);
83 /* FIXME - handle failure of get_user() */
84 get_user_u32(x, addr);
85 fpa11->fType[Fn] = (x >> 14) & 0x00000003;
87 switch (fpa11->fType[Fn])
89 case typeSingle:
90 case typeDouble:
92 /* FIXME - handle failure of get_user() */
93 get_user_u32(p[0], addr + 8); /* Single */
94 get_user_u32(p[1], addr + 4); /* double msw */
95 p[2] = 0; /* empty */
97 break;
99 case typeExtended:
101 /* FIXME - handle failure of get_user() */
102 get_user_u32(p[1], addr + 8);
103 get_user_u32(p[2], addr + 4); /* msw */
104 p[0] = (x & 0x80003fff);
106 break;
110 static inline
111 void storeSingle(const unsigned int Fn,unsigned int *pMem)
113 target_ulong addr = (target_ulong)(long)pMem;
114 FPA11 *fpa11 = GET_FPA11();
115 float32 val;
116 register unsigned int *p = (unsigned int*)&val;
118 switch (fpa11->fType[Fn])
120 case typeDouble:
121 val = float64_to_float32(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
122 break;
124 case typeExtended:
125 val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
126 break;
128 default: val = fpa11->fpreg[Fn].fSingle;
131 /* FIXME - handle put_user() failures */
132 put_user_u32(p[0], addr);
135 static inline
136 void storeDouble(const unsigned int Fn,unsigned int *pMem)
138 target_ulong addr = (target_ulong)(long)pMem;
139 FPA11 *fpa11 = GET_FPA11();
140 float64 val;
141 register unsigned int *p = (unsigned int*)&val;
143 switch (fpa11->fType[Fn])
145 case typeSingle:
146 val = float32_to_float64(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
147 break;
149 case typeExtended:
150 val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
151 break;
153 default: val = fpa11->fpreg[Fn].fDouble;
155 /* FIXME - handle put_user() failures */
156 #ifdef WORDS_BIGENDIAN
157 put_user_u32(p[0], addr); /* msw */
158 put_user_u32(p[1], addr + 4); /* lsw */
159 #else
160 put_user_u32(p[1], addr); /* msw */
161 put_user_u32(p[0], addr + 4); /* lsw */
162 #endif
165 static inline
166 void storeExtended(const unsigned int Fn,unsigned int *pMem)
168 target_ulong addr = (target_ulong)(long)pMem;
169 FPA11 *fpa11 = GET_FPA11();
170 floatx80 val;
171 register unsigned int *p = (unsigned int*)&val;
173 switch (fpa11->fType[Fn])
175 case typeSingle:
176 val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
177 break;
179 case typeDouble:
180 val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
181 break;
183 default: val = fpa11->fpreg[Fn].fExtended;
186 /* FIXME - handle put_user() failures */
187 put_user_u32(p[0], addr); /* sign & exp */
188 put_user_u32(p[1], addr + 8);
189 put_user_u32(p[2], addr + 4); /* msw */
192 static inline
193 void storeMultiple(const unsigned int Fn,unsigned int *pMem)
195 target_ulong addr = (target_ulong)(long)pMem;
196 FPA11 *fpa11 = GET_FPA11();
197 register unsigned int nType, *p;
199 p = (unsigned int*)&(fpa11->fpreg[Fn]);
200 nType = fpa11->fType[Fn];
202 switch (nType)
204 case typeSingle:
205 case typeDouble:
207 put_user_u32(p[0], addr + 8); /* single */
208 put_user_u32(p[1], addr + 4); /* double msw */
209 put_user_u32(nType << 14, addr);
211 break;
213 case typeExtended:
215 put_user_u32(p[2], addr + 4); /* msw */
216 put_user_u32(p[1], addr + 8);
217 put_user_u32((p[0] & 0x80003fff) | (nType << 14), addr);
219 break;
223 unsigned int PerformLDF(const unsigned int opcode)
225 unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
226 write_back = WRITE_BACK(opcode);
228 //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
230 pBase = (unsigned int*)readRegister(getRn(opcode));
231 if (REG_PC == getRn(opcode))
233 pBase += 2;
234 write_back = 0;
237 pFinal = pBase;
238 if (BIT_UP_SET(opcode))
239 pFinal += getOffset(opcode);
240 else
241 pFinal -= getOffset(opcode);
243 if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
245 switch (opcode & MASK_TRANSFER_LENGTH)
247 case TRANSFER_SINGLE : loadSingle(getFd(opcode),pAddress); break;
248 case TRANSFER_DOUBLE : loadDouble(getFd(opcode),pAddress); break;
249 case TRANSFER_EXTENDED: loadExtended(getFd(opcode),pAddress); break;
250 default: nRc = 0;
253 if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
254 return nRc;
257 unsigned int PerformSTF(const unsigned int opcode)
259 unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
260 write_back = WRITE_BACK(opcode);
262 //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
263 SetRoundingMode(ROUND_TO_NEAREST);
265 pBase = (unsigned int*)readRegister(getRn(opcode));
266 if (REG_PC == getRn(opcode))
268 pBase += 2;
269 write_back = 0;
272 pFinal = pBase;
273 if (BIT_UP_SET(opcode))
274 pFinal += getOffset(opcode);
275 else
276 pFinal -= getOffset(opcode);
278 if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
280 switch (opcode & MASK_TRANSFER_LENGTH)
282 case TRANSFER_SINGLE : storeSingle(getFd(opcode),pAddress); break;
283 case TRANSFER_DOUBLE : storeDouble(getFd(opcode),pAddress); break;
284 case TRANSFER_EXTENDED: storeExtended(getFd(opcode),pAddress); break;
285 default: nRc = 0;
288 if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
289 return nRc;
292 unsigned int PerformLFM(const unsigned int opcode)
294 unsigned int i, Fd, *pBase, *pAddress, *pFinal,
295 write_back = WRITE_BACK(opcode);
297 pBase = (unsigned int*)readRegister(getRn(opcode));
298 if (REG_PC == getRn(opcode))
300 pBase += 2;
301 write_back = 0;
304 pFinal = pBase;
305 if (BIT_UP_SET(opcode))
306 pFinal += getOffset(opcode);
307 else
308 pFinal -= getOffset(opcode);
310 if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
312 Fd = getFd(opcode);
313 for (i=getRegisterCount(opcode);i>0;i--)
315 loadMultiple(Fd,pAddress);
316 pAddress += 3; Fd++;
317 if (Fd == 8) Fd = 0;
320 if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
321 return 1;
324 unsigned int PerformSFM(const unsigned int opcode)
326 unsigned int i, Fd, *pBase, *pAddress, *pFinal,
327 write_back = WRITE_BACK(opcode);
329 pBase = (unsigned int*)readRegister(getRn(opcode));
330 if (REG_PC == getRn(opcode))
332 pBase += 2;
333 write_back = 0;
336 pFinal = pBase;
337 if (BIT_UP_SET(opcode))
338 pFinal += getOffset(opcode);
339 else
340 pFinal -= getOffset(opcode);
342 if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
344 Fd = getFd(opcode);
345 for (i=getRegisterCount(opcode);i>0;i--)
347 storeMultiple(Fd,pAddress);
348 pAddress += 3; Fd++;
349 if (Fd == 8) Fd = 0;
352 if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
353 return 1;
356 #if 1
357 unsigned int EmulateCPDT(const unsigned int opcode)
359 unsigned int nRc = 0;
361 //printk("EmulateCPDT(0x%08x)\n",opcode);
363 if (LDF_OP(opcode))
365 nRc = PerformLDF(opcode);
367 else if (LFM_OP(opcode))
369 nRc = PerformLFM(opcode);
371 else if (STF_OP(opcode))
373 nRc = PerformSTF(opcode);
375 else if (SFM_OP(opcode))
377 nRc = PerformSFM(opcode);
379 else
381 nRc = 0;
384 return nRc;
386 #endif