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