|
|
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.