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