|
|
1.1 ! root 1: /* ! 2: NetWinder Floating Point Emulator ! 3: (c) Rebel.COM, 1998,1999 ! 4: ! 5: Direct questions, comments to Scott Bambrough <[email protected]> ! 6: ! 7: This program is free software; you can redistribute it and/or modify ! 8: it under the terms of the GNU General Public License as published by ! 9: the Free Software Foundation; either version 2 of the License, or ! 10: (at your option) any later version. ! 11: ! 12: This program is distributed in the hope that it will be useful, ! 13: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 15: GNU General Public License for more details. ! 16: ! 17: You should have received a copy of the GNU General Public License ! 18: along with this program; if not, write to the Free Software ! 19: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 20: */ ! 21: ! 22: #include "fpa11.h" ! 23: #include "fpopcode.h" ! 24: ! 25: unsigned int SingleCPDO(const unsigned int opcode); ! 26: unsigned int DoubleCPDO(const unsigned int opcode); ! 27: unsigned int ExtendedCPDO(const unsigned int opcode); ! 28: ! 29: unsigned int EmulateCPDO(const unsigned int opcode) ! 30: { ! 31: FPA11 *fpa11 = GET_FPA11(); ! 32: unsigned int Fd, nType, nDest, nRc = 1; ! 33: ! 34: //printk("EmulateCPDO(0x%08x)\n",opcode); ! 35: ! 36: /* Get the destination size. If not valid let Linux perform ! 37: an invalid instruction trap. */ ! 38: nDest = getDestinationSize(opcode); ! 39: if (typeNone == nDest) return 0; ! 40: ! 41: SetRoundingMode(opcode); ! 42: ! 43: /* Compare the size of the operands in Fn and Fm. ! 44: Choose the largest size and perform operations in that size, ! 45: in order to make use of all the precision of the operands. ! 46: If Fm is a constant, we just grab a constant of a size ! 47: matching the size of the operand in Fn. */ ! 48: if (MONADIC_INSTRUCTION(opcode)) ! 49: nType = nDest; ! 50: else ! 51: nType = fpa11->fType[getFn(opcode)]; ! 52: ! 53: if (!CONSTANT_FM(opcode)) ! 54: { ! 55: register unsigned int Fm = getFm(opcode); ! 56: if (nType < fpa11->fType[Fm]) ! 57: { ! 58: nType = fpa11->fType[Fm]; ! 59: } ! 60: } ! 61: ! 62: switch (nType) ! 63: { ! 64: case typeSingle : nRc = SingleCPDO(opcode); break; ! 65: case typeDouble : nRc = DoubleCPDO(opcode); break; ! 66: case typeExtended : nRc = ExtendedCPDO(opcode); break; ! 67: default : nRc = 0; ! 68: } ! 69: ! 70: /* If the operation succeeded, check to see if the result in the ! 71: destination register is the correct size. If not force it ! 72: to be. */ ! 73: Fd = getFd(opcode); ! 74: nType = fpa11->fType[Fd]; ! 75: if ((0 != nRc) && (nDest != nType)) ! 76: { ! 77: switch (nDest) ! 78: { ! 79: case typeSingle: ! 80: { ! 81: if (typeDouble == nType) ! 82: fpa11->fpreg[Fd].fSingle = ! 83: float64_to_float32(fpa11->fpreg[Fd].fDouble, &fpa11->fp_status); ! 84: else ! 85: fpa11->fpreg[Fd].fSingle = ! 86: floatx80_to_float32(fpa11->fpreg[Fd].fExtended, &fpa11->fp_status); ! 87: } ! 88: break; ! 89: ! 90: case typeDouble: ! 91: { ! 92: if (typeSingle == nType) ! 93: fpa11->fpreg[Fd].fDouble = ! 94: float32_to_float64(fpa11->fpreg[Fd].fSingle, &fpa11->fp_status); ! 95: else ! 96: fpa11->fpreg[Fd].fDouble = ! 97: floatx80_to_float64(fpa11->fpreg[Fd].fExtended, &fpa11->fp_status); ! 98: } ! 99: break; ! 100: ! 101: case typeExtended: ! 102: { ! 103: if (typeSingle == nType) ! 104: fpa11->fpreg[Fd].fExtended = ! 105: float32_to_floatx80(fpa11->fpreg[Fd].fSingle, &fpa11->fp_status); ! 106: else ! 107: fpa11->fpreg[Fd].fExtended = ! 108: float64_to_floatx80(fpa11->fpreg[Fd].fDouble, &fpa11->fp_status); ! 109: } ! 110: break; ! 111: } ! 112: ! 113: fpa11->fType[Fd] = nDest; ! 114: } ! 115: ! 116: return nRc; ! 117: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.