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