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