Statistics
| Branch: | Revision:

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

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

233 5fafdf24 ths
     case 0xe:
234 00406dff bellard
       if (opcode & 0x10)
235 00406dff bellard
         return EmulateCPDO(opcode);
236 00406dff bellard
       else
237 00406dff bellard
         return EmulateCPRT(opcode);
238 00406dff bellard
     break;
239 3b46e624 ths

240 00406dff bellard
     default: return 0;
241 00406dff bellard
  }
242 00406dff bellard
}
243 00406dff bellard
#endif