~ahs3/+junk/cq-qemu

« back to all changes in this revision

Viewing changes to linux-user/arm/nwfpe/fpa11.c

  • Committer: Al Stone
  • Date: 2012-02-09 01:17:20 UTC
  • Revision ID: albert.stone@canonical.com-20120209011720-tztl7ik3qayz80p4
first commit to bzr for qemu

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    NetWinder Floating Point Emulator
 
3
    (c) Rebel.COM, 1998,1999
 
4
 
 
5
    Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
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, see <http://www.gnu.org/licenses/>.
 
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
 
 
32
FPA11* qemufpa = NULL;
 
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",
 
147
          opcode, qregs[ARM_REG_PC]);
 
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);
 
193
    nRc = -get_float_exception_flags(&fpa11->fp_status);
 
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