|
|
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: CPUARMState* user_registers; ! 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: #ifdef 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: #ifdef 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: #ifdef 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: #ifdef 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: #ifdef 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: #ifdef 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: #ifdef 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: #ifdef MAINTAIN_FPCR ! 116: fpa11->fpcr |= ROUND_SINGLE; ! 117: #endif ! 118: break; ! 119: ! 120: case ROUND_DOUBLE: ! 121: rounding_precision = 64; ! 122: #ifdef MAINTAIN_FPCR ! 123: fpa11->fpcr |= ROUND_DOUBLE; ! 124: #endif ! 125: break; ! 126: ! 127: case ROUND_EXTENDED: ! 128: rounding_precision = 80; ! 129: #ifdef 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: /* ??? This is not thread safe. */ ! 141: unsigned int EmulateAll(unsigned int opcode, FPA11* qfpa, CPUARMState* qregs) ! 142: { ! 143: unsigned int nRc = 0; ! 144: // unsigned long flags; ! 145: FPA11 *fpa11; ! 146: // save_flags(flags); sti(); ! 147: ! 148: qemufpa=qfpa; ! 149: user_registers=qregs; ! 150: ! 151: #if 0 ! 152: fprintf(stderr,"emulating FP insn 0x%08x, PC=0x%08x\n", ! 153: opcode, qregs[REG_PC]); ! 154: #endif ! 155: fpa11 = GET_FPA11(); ! 156: ! 157: if (fpa11->initflag == 0) /* good place for __builtin_expect */ ! 158: { ! 159: resetFPA11(); ! 160: SetRoundingMode(ROUND_TO_NEAREST); ! 161: SetRoundingPrecision(ROUND_EXTENDED); ! 162: fpa11->initflag = 1; ! 163: } ! 164: ! 165: set_float_exception_flags(0, &fpa11->fp_status); ! 166: ! 167: if (TEST_OPCODE(opcode,MASK_CPRT)) ! 168: { ! 169: //fprintf(stderr,"emulating CPRT\n"); ! 170: /* Emulate conversion opcodes. */ ! 171: /* Emulate register transfer opcodes. */ ! 172: /* Emulate comparison opcodes. */ ! 173: nRc = EmulateCPRT(opcode); ! 174: } ! 175: else if (TEST_OPCODE(opcode,MASK_CPDO)) ! 176: { ! 177: //fprintf(stderr,"emulating CPDO\n"); ! 178: /* Emulate monadic arithmetic opcodes. */ ! 179: /* Emulate dyadic arithmetic opcodes. */ ! 180: nRc = EmulateCPDO(opcode); ! 181: } ! 182: else if (TEST_OPCODE(opcode,MASK_CPDT)) ! 183: { ! 184: //fprintf(stderr,"emulating CPDT\n"); ! 185: /* Emulate load/store opcodes. */ ! 186: /* Emulate load/store multiple opcodes. */ ! 187: nRc = EmulateCPDT(opcode); ! 188: } ! 189: else ! 190: { ! 191: /* Invalid instruction detected. Return FALSE. */ ! 192: nRc = 0; ! 193: } ! 194: ! 195: // restore_flags(flags); ! 196: if(nRc == 1 && get_float_exception_flags(&fpa11->fp_status)) ! 197: { ! 198: //printf("fef 0x%x\n",float_exception_flags); ! 199: nRc=-get_float_exception_flags(&fpa11->fp_status); ! 200: } ! 201: ! 202: //printf("returning %d\n",nRc); ! 203: return(nRc); ! 204: } ! 205: ! 206: #if 0 ! 207: unsigned int EmulateAll1(unsigned int opcode) ! 208: { ! 209: switch ((opcode >> 24) & 0xf) ! 210: { ! 211: case 0xc: ! 212: case 0xd: ! 213: if ((opcode >> 20) & 0x1) ! 214: { ! 215: switch ((opcode >> 8) & 0xf) ! 216: { ! 217: case 0x1: return PerformLDF(opcode); break; ! 218: case 0x2: return PerformLFM(opcode); break; ! 219: default: return 0; ! 220: } ! 221: } ! 222: else ! 223: { ! 224: switch ((opcode >> 8) & 0xf) ! 225: { ! 226: case 0x1: return PerformSTF(opcode); break; ! 227: case 0x2: return PerformSFM(opcode); break; ! 228: default: return 0; ! 229: } ! 230: } ! 231: break; ! 232: ! 233: case 0xe: ! 234: if (opcode & 0x10) ! 235: return EmulateCPDO(opcode); ! 236: else ! 237: return EmulateCPRT(opcode); ! 238: break; ! 239: ! 240: default: return 0; ! 241: } ! 242: } ! 243: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.