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