Statistics
| Branch: | Revision:

root / linux-user / arm / nwfpe / fpa11.c @ b53d44e5

History | View | Annotate | Download (5.6 kB)

1 00406dff bellard
/*
2 00406dff bellard
    NetWinder Floating Point Emulator
3 00406dff bellard
    (c) Rebel.COM, 1998,1999
4 00406dff bellard

5 00406dff bellard
    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
6 00406dff bellard

7 00406dff bellard
    This program is free software; you can redistribute it and/or modify
8 00406dff bellard
    it under the terms of the GNU General Public License as published by
9 00406dff bellard
    the Free Software Foundation; either version 2 of the License, or
10 00406dff bellard
    (at your option) any later version.
11 00406dff bellard

12 00406dff bellard
    This program is distributed in the hope that it will be useful,
13 00406dff bellard
    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 00406dff bellard
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 00406dff bellard
    GNU General Public License for more details.
16 00406dff bellard

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

228 5fafdf24 ths
     case 0xe:
229 00406dff bellard
       if (opcode & 0x10)
230 00406dff bellard
         return EmulateCPDO(opcode);
231 00406dff bellard
       else
232 00406dff bellard
         return EmulateCPRT(opcode);
233 00406dff bellard
     break;
234 3b46e624 ths

235 00406dff bellard
     default: return 0;
236 00406dff bellard
  }
237 00406dff bellard
}
238 00406dff bellard
#endif