|
|
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: ! 24: #include "fpopcode.h" ! 25: ! 26: //#include "fpmodule.h" ! 27: //#include "fpmodule.inl" ! 28: ! 29: //#include <asm/system.h> ! 30: ! 31: #include <stdio.h> ! 32: ! 33: /* forward declarations */ ! 34: unsigned int EmulateCPDO(const unsigned int); ! 35: unsigned int EmulateCPDT(const unsigned int); ! 36: unsigned int EmulateCPRT(const unsigned int); ! 37: ! 38: FPA11* qemufpa=0; ! 39: unsigned int* user_registers=0; ! 40: ! 41: /* Reset the FPA11 chip. Called to initialize and reset the emulator. */ ! 42: void resetFPA11(void) ! 43: { ! 44: int i; ! 45: FPA11 *fpa11 = GET_FPA11(); ! 46: ! 47: /* initialize the register type array */ ! 48: for (i=0;i<=7;i++) ! 49: { ! 50: fpa11->fType[i] = typeNone; ! 51: } ! 52: ! 53: /* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */ ! 54: fpa11->fpsr = FP_EMULATOR | BIT_AC; ! 55: ! 56: /* FPCR: set SB, AB and DA bits, clear all others */ ! 57: #if MAINTAIN_FPCR ! 58: fpa11->fpcr = MASK_RESET; ! 59: #endif ! 60: } ! 61: ! 62: void SetRoundingMode(const unsigned int opcode) ! 63: { ! 64: int rounding_mode; ! 65: FPA11 *fpa11 = GET_FPA11(); ! 66: ! 67: #if MAINTAIN_FPCR ! 68: fpa11->fpcr &= ~MASK_ROUNDING_MODE; ! 69: #endif ! 70: switch (opcode & MASK_ROUNDING_MODE) ! 71: { ! 72: default: ! 73: case ROUND_TO_NEAREST: ! 74: rounding_mode = float_round_nearest_even; ! 75: #if MAINTAIN_FPCR ! 76: fpa11->fpcr |= ROUND_TO_NEAREST; ! 77: #endif ! 78: break; ! 79: ! 80: case ROUND_TO_PLUS_INFINITY: ! 81: rounding_mode = float_round_up; ! 82: #if MAINTAIN_FPCR ! 83: fpa11->fpcr |= ROUND_TO_PLUS_INFINITY; ! 84: #endif ! 85: break; ! 86: ! 87: case ROUND_TO_MINUS_INFINITY: ! 88: rounding_mode = float_round_down; ! 89: #if MAINTAIN_FPCR ! 90: fpa11->fpcr |= ROUND_TO_MINUS_INFINITY; ! 91: #endif ! 92: break; ! 93: ! 94: case ROUND_TO_ZERO: ! 95: rounding_mode = float_round_to_zero; ! 96: #if MAINTAIN_FPCR ! 97: fpa11->fpcr |= ROUND_TO_ZERO; ! 98: #endif ! 99: break; ! 100: } ! 101: set_float_rounding_mode(rounding_mode, &fpa11->fp_status); ! 102: } ! 103: ! 104: void SetRoundingPrecision(const unsigned int opcode) ! 105: { ! 106: int rounding_precision; ! 107: FPA11 *fpa11 = GET_FPA11(); ! 108: #if MAINTAIN_FPCR ! 109: fpa11->fpcr &= ~MASK_ROUNDING_PRECISION; ! 110: #endif ! 111: switch (opcode & MASK_ROUNDING_PRECISION) ! 112: { ! 113: case ROUND_SINGLE: ! 114: rounding_precision = 32; ! 115: #if MAINTAIN_FPCR ! 116: fpa11->fpcr |= ROUND_SINGLE; ! 117: #endif ! 118: break; ! 119: ! 120: case ROUND_DOUBLE: ! 121: rounding_precision = 64; ! 122: #if MAINTAIN_FPCR ! 123: fpa11->fpcr |= ROUND_DOUBLE; ! 124: #endif ! 125: break; ! 126: ! 127: case ROUND_EXTENDED: ! 128: rounding_precision = 80; ! 129: #if MAINTAIN_FPCR ! 130: fpa11->fpcr |= ROUND_EXTENDED; ! 131: #endif ! 132: break; ! 133: ! 134: default: rounding_precision = 80; ! 135: } ! 136: set_floatx80_rounding_precision(rounding_precision, &fpa11->fp_status); ! 137: } ! 138: ! 139: /* Emulate the instruction in the opcode. */ ! 140: unsigned int EmulateAll(unsigned int opcode, FPA11* qfpa, unsigned int* qregs) ! 141: { ! 142: unsigned int nRc = 0; ! 143: // unsigned long flags; ! 144: FPA11 *fpa11; ! 145: // save_flags(flags); sti(); ! 146: ! 147: qemufpa=qfpa; ! 148: user_registers=qregs; ! 149: ! 150: #if 0 ! 151: fprintf(stderr,"emulating FP insn 0x%08x, PC=0x%08x\n", ! 152: opcode, qregs[REG_PC]); ! 153: #endif ! 154: fpa11 = GET_FPA11(); ! 155: ! 156: if (fpa11->initflag == 0) /* good place for __builtin_expect */ ! 157: { ! 158: resetFPA11(); ! 159: SetRoundingMode(ROUND_TO_NEAREST); ! 160: SetRoundingPrecision(ROUND_EXTENDED); ! 161: fpa11->initflag = 1; ! 162: } ! 163: ! 164: if (TEST_OPCODE(opcode,MASK_CPRT)) ! 165: { ! 166: //fprintf(stderr,"emulating CPRT\n"); ! 167: /* Emulate conversion opcodes. */ ! 168: /* Emulate register transfer opcodes. */ ! 169: /* Emulate comparison opcodes. */ ! 170: nRc = EmulateCPRT(opcode); ! 171: } ! 172: else if (TEST_OPCODE(opcode,MASK_CPDO)) ! 173: { ! 174: //fprintf(stderr,"emulating CPDO\n"); ! 175: /* Emulate monadic arithmetic opcodes. */ ! 176: /* Emulate dyadic arithmetic opcodes. */ ! 177: nRc = EmulateCPDO(opcode); ! 178: } ! 179: else if (TEST_OPCODE(opcode,MASK_CPDT)) ! 180: { ! 181: //fprintf(stderr,"emulating CPDT\n"); ! 182: /* Emulate load/store opcodes. */ ! 183: /* Emulate load/store multiple opcodes. */ ! 184: nRc = EmulateCPDT(opcode); ! 185: } ! 186: else ! 187: { ! 188: /* Invalid instruction detected. Return FALSE. */ ! 189: nRc = 0; ! 190: } ! 191: ! 192: // restore_flags(flags); ! 193: ! 194: //printf("returning %d\n",nRc); ! 195: return(nRc); ! 196: } ! 197: ! 198: #if 0 ! 199: unsigned int EmulateAll1(unsigned int opcode) ! 200: { ! 201: switch ((opcode >> 24) & 0xf) ! 202: { ! 203: case 0xc: ! 204: case 0xd: ! 205: if ((opcode >> 20) & 0x1) ! 206: { ! 207: switch ((opcode >> 8) & 0xf) ! 208: { ! 209: case 0x1: return PerformLDF(opcode); break; ! 210: case 0x2: return PerformLFM(opcode); break; ! 211: default: return 0; ! 212: } ! 213: } ! 214: else ! 215: { ! 216: switch ((opcode >> 8) & 0xf) ! 217: { ! 218: case 0x1: return PerformSTF(opcode); break; ! 219: case 0x2: return PerformSFM(opcode); break; ! 220: default: return 0; ! 221: } ! 222: } ! 223: break; ! 224: ! 225: case 0xe: ! 226: if (opcode & 0x10) ! 227: return EmulateCPDO(opcode); ! 228: else ! 229: return EmulateCPRT(opcode); ! 230: break; ! 231: ! 232: default: return 0; ! 233: } ! 234: } ! 235: #endif ! 236:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.