|
|
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: {
1.1.1.2 ! root 34: target_ulong addr = (target_ulong)(long)pMem;
1.1 root 35: FPA11 *fpa11 = GET_FPA11();
36: fpa11->fType[Fn] = typeSingle;
1.1.1.2 ! root 37: fpa11->fpreg[Fn].fSingle = tget32(addr);
1.1 root 38: }
39:
40: static inline
41: void loadDouble(const unsigned int Fn,const unsigned int *pMem)
42: {
1.1.1.2 ! root 43: target_ulong addr = (target_ulong)(long)pMem;
1.1 root 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
1.1.1.2 ! root 49: p[0] = tget32(addr); /* sign & exponent */
! 50: p[1] = tget32(addr + 4);
1.1 root 51: #else
1.1.1.2 ! root 52: p[0] = tget32(addr + 4);
! 53: p[1] = tget32(addr); /* sign & exponent */
1.1 root 54: #endif
55: }
56:
57: static inline
58: void loadExtended(const unsigned int Fn,const unsigned int *pMem)
59: {
1.1.1.2 ! root 60: target_ulong addr = (target_ulong)(long)pMem;
1.1 root 61: FPA11 *fpa11 = GET_FPA11();
62: unsigned int *p;
63: p = (unsigned int*)&fpa11->fpreg[Fn].fExtended;
64: fpa11->fType[Fn] = typeExtended;
1.1.1.2 ! root 65: p[0] = tget32(addr); /* sign & exponent */
! 66: p[1] = tget32(addr + 8); /* ls bits */
! 67: p[2] = tget32(addr + 4); /* ms bits */
1.1 root 68: }
69:
70: static inline
71: void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
72: {
1.1.1.2 ! root 73: target_ulong addr = (target_ulong)(long)pMem;
1.1 root 74: FPA11 *fpa11 = GET_FPA11();
75: register unsigned int *p;
76: unsigned long x;
77:
78: p = (unsigned int*)&(fpa11->fpreg[Fn]);
1.1.1.2 ! root 79: x = tget32(addr);
1.1 root 80: fpa11->fType[Fn] = (x >> 14) & 0x00000003;
81:
82: switch (fpa11->fType[Fn])
83: {
84: case typeSingle:
85: case typeDouble:
86: {
1.1.1.2 ! root 87: p[0] = tget32(addr + 8); /* Single */
! 88: p[1] = tget32(addr + 4); /* double msw */
1.1 root 89: p[2] = 0; /* empty */
90: }
91: break;
92:
93: case typeExtended:
94: {
1.1.1.2 ! root 95: p[1] = tget32(addr + 8);
! 96: p[2] = tget32(addr + 4); /* msw */
1.1 root 97: p[0] = (x & 0x80003fff);
98: }
99: break;
100: }
101: }
102:
103: static inline
104: void storeSingle(const unsigned int Fn,unsigned int *pMem)
105: {
1.1.1.2 ! root 106: target_ulong addr = (target_ulong)(long)pMem;
1.1 root 107: FPA11 *fpa11 = GET_FPA11();
108: float32 val;
109: register unsigned int *p = (unsigned int*)&val;
110:
111: switch (fpa11->fType[Fn])
112: {
113: case typeDouble:
114: val = float64_to_float32(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
115: break;
116:
117: case typeExtended:
118: val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
119: break;
120:
121: default: val = fpa11->fpreg[Fn].fSingle;
122: }
123:
1.1.1.2 ! root 124: tput32(addr, p[0]);
1.1 root 125: }
126:
127: static inline
128: void storeDouble(const unsigned int Fn,unsigned int *pMem)
129: {
1.1.1.2 ! root 130: target_ulong addr = (target_ulong)(long)pMem;
1.1 root 131: FPA11 *fpa11 = GET_FPA11();
132: float64 val;
133: register unsigned int *p = (unsigned int*)&val;
134:
135: switch (fpa11->fType[Fn])
136: {
137: case typeSingle:
138: val = float32_to_float64(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
139: break;
140:
141: case typeExtended:
142: val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
143: break;
144:
145: default: val = fpa11->fpreg[Fn].fDouble;
146: }
147: #ifdef WORDS_BIGENDIAN
1.1.1.2 ! root 148: tput32(addr, p[0]); /* msw */
! 149: tput32(addr + 4, p[1]); /* lsw */
1.1 root 150: #else
1.1.1.2 ! root 151: tput32(addr, p[1]); /* msw */
! 152: tput32(addr + 4, p[0]); /* lsw */
1.1 root 153: #endif
154: }
155:
156: static inline
157: void storeExtended(const unsigned int Fn,unsigned int *pMem)
158: {
1.1.1.2 ! root 159: target_ulong addr = (target_ulong)(long)pMem;
1.1 root 160: FPA11 *fpa11 = GET_FPA11();
161: floatx80 val;
162: register unsigned int *p = (unsigned int*)&val;
163:
164: switch (fpa11->fType[Fn])
165: {
166: case typeSingle:
167: val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
168: break;
169:
170: case typeDouble:
171: val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
172: break;
173:
174: default: val = fpa11->fpreg[Fn].fExtended;
175: }
176:
1.1.1.2 ! root 177: tput32(addr, p[0]); /* sign & exp */
! 178: tput32(addr + 8, p[1]);
! 179: tput32(addr + 4, p[2]); /* msw */
1.1 root 180: }
181:
182: static inline
183: void storeMultiple(const unsigned int Fn,unsigned int *pMem)
184: {
1.1.1.2 ! root 185: target_ulong addr = (target_ulong)(long)pMem;
1.1 root 186: FPA11 *fpa11 = GET_FPA11();
187: register unsigned int nType, *p;
188:
189: p = (unsigned int*)&(fpa11->fpreg[Fn]);
190: nType = fpa11->fType[Fn];
191:
192: switch (nType)
193: {
194: case typeSingle:
195: case typeDouble:
196: {
1.1.1.2 ! root 197: tput32(addr + 8, p[0]); /* single */
! 198: tput32(addr + 4, p[1]); /* double msw */
! 199: tput32(addr, nType << 14);
1.1 root 200: }
201: break;
202:
203: case typeExtended:
204: {
1.1.1.2 ! root 205: tput32(addr + 4, p[2]); /* msw */
! 206: tput32(addr + 8, p[1]);
! 207: tput32(addr, (p[0] & 0x80003fff) | (nType << 14));
1.1 root 208: }
209: break;
210: }
211: }
212:
213: unsigned 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: }
242:
243: if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
244: return nRc;
245: }
246:
247: unsigned int PerformSTF(const unsigned int opcode)
248: {
249: unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
250: write_back = WRITE_BACK(opcode);
251:
252: //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
253: SetRoundingMode(ROUND_TO_NEAREST);
254:
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: }
277:
278: if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
279: return nRc;
280: }
281:
282: unsigned 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:
314: unsigned int PerformSFM(const unsigned int opcode)
315: {
316: unsigned int i, Fd, *pBase, *pAddress, *pFinal,
317: write_back = WRITE_BACK(opcode);
318:
319: pBase = (unsigned int*)readRegister(getRn(opcode));
320: if (REG_PC == getRn(opcode))
321: {
322: pBase += 2;
323: write_back = 0;
324: }
325:
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
347: unsigned int EmulateCPDT(const unsigned int opcode)
348: {
349: unsigned int nRc = 0;
350:
351: //printk("EmulateCPDT(0x%08x)\n",opcode);
352:
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);
364: }
365: else if (SFM_OP(opcode))
366: {
367: nRc = PerformSFM(opcode);
368: }
369: else
370: {
371: nRc = 0;
372: }
373:
374: return nRc;
375: }
376: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.