PageRenderTime 19ms CodeModel.GetById 12ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/arm26/nwfpe/fpa11.c

https://bitbucket.org/evzijst/gittest
C | 221 lines | 162 code | 24 blank | 35 comment | 20 complexity | 49a6530524e4e4862df248de8eae8978 MD5 | raw file
  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, write to the Free Software
 19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20*/
 21
 22#include "fpa11.h"
 23#include "fpopcode.h"
 24
 25#include "fpmodule.h"
 26#include "fpmodule.inl"
 27
 28#include <linux/compiler.h>
 29#include <asm/system.h>
 30
 31/* forward declarations */
 32unsigned int EmulateCPDO(const unsigned int);
 33unsigned int EmulateCPDT(const unsigned int);
 34unsigned int EmulateCPRT(const unsigned int);
 35
 36/* Reset the FPA11 chip.  Called to initialize and reset the emulator. */
 37void 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#if MAINTAIN_FPCR
 53  fpa11->fpcr = MASK_RESET;
 54#endif
 55}
 56
 57void SetRoundingMode(const unsigned int opcode)
 58{
 59#if MAINTAIN_FPCR
 60   FPA11 *fpa11 = GET_FPA11();
 61   fpa11->fpcr &= ~MASK_ROUNDING_MODE;
 62#endif   
 63   switch (opcode & MASK_ROUNDING_MODE)
 64   {
 65      default:
 66      case ROUND_TO_NEAREST:
 67         float_rounding_mode = float_round_nearest_even;
 68#if MAINTAIN_FPCR         
 69         fpa11->fpcr |= ROUND_TO_NEAREST;
 70#endif         
 71      break;
 72      
 73      case ROUND_TO_PLUS_INFINITY:
 74         float_rounding_mode = float_round_up;
 75#if MAINTAIN_FPCR         
 76         fpa11->fpcr |= ROUND_TO_PLUS_INFINITY;
 77#endif         
 78      break;
 79      
 80      case ROUND_TO_MINUS_INFINITY:
 81         float_rounding_mode = float_round_down;
 82#if MAINTAIN_FPCR         
 83         fpa11->fpcr |= ROUND_TO_MINUS_INFINITY;
 84#endif         
 85      break;
 86      
 87      case ROUND_TO_ZERO:
 88         float_rounding_mode = float_round_to_zero;
 89#if MAINTAIN_FPCR         
 90         fpa11->fpcr |= ROUND_TO_ZERO;
 91#endif         
 92      break;
 93  }
 94}
 95
 96void SetRoundingPrecision(const unsigned int opcode)
 97{
 98#if MAINTAIN_FPCR
 99   FPA11 *fpa11 = GET_FPA11();
100   fpa11->fpcr &= ~MASK_ROUNDING_PRECISION;
101#endif   
102   switch (opcode & MASK_ROUNDING_PRECISION)
103   {
104      case ROUND_SINGLE:
105         floatx80_rounding_precision = 32;
106#if MAINTAIN_FPCR         
107         fpa11->fpcr |= ROUND_SINGLE;
108#endif         
109      break;
110      
111      case ROUND_DOUBLE:
112         floatx80_rounding_precision = 64;
113#if MAINTAIN_FPCR         
114         fpa11->fpcr |= ROUND_DOUBLE;
115#endif         
116      break;
117      
118      case ROUND_EXTENDED:
119         floatx80_rounding_precision = 80;
120#if MAINTAIN_FPCR         
121         fpa11->fpcr |= ROUND_EXTENDED;
122#endif         
123      break;
124      
125      default: floatx80_rounding_precision = 80;
126  }
127}
128
129void FPA11_CheckInit(void)
130{
131  FPA11 *fpa11 = GET_FPA11();
132  if (unlikely(fpa11->initflag == 0))
133  {
134    resetFPA11();
135    SetRoundingMode(ROUND_TO_NEAREST);
136    SetRoundingPrecision(ROUND_EXTENDED);
137    fpa11->initflag = 1;
138  }
139}
140
141/* Emulate the instruction in the opcode. */
142unsigned int EmulateAll(unsigned int opcode)
143{
144  unsigned int nRc = 1, code;
145
146  code = opcode & 0x00000f00;
147  if (code == 0x00000100 || code == 0x00000200)
148  {
149    /* For coprocessor 1 or 2 (FPA11) */
150    code = opcode & 0x0e000000;
151    if (code == 0x0e000000)
152    {
153      if (opcode & 0x00000010)
154      {
155        /* Emulate conversion opcodes. */
156        /* Emulate register transfer opcodes. */
157        /* Emulate comparison opcodes. */
158        nRc = EmulateCPRT(opcode);
159      }
160      else
161      {
162        /* Emulate monadic arithmetic opcodes. */
163        /* Emulate dyadic arithmetic opcodes. */
164        nRc = EmulateCPDO(opcode);
165      }
166    }
167    else if (code == 0x0c000000)
168    {
169      /* Emulate load/store opcodes. */
170      /* Emulate load/store multiple opcodes. */
171      nRc = EmulateCPDT(opcode);
172    }
173    else
174    {
175      /* Invalid instruction detected.  Return FALSE. */
176      nRc = 0;
177    }
178  }
179
180  return(nRc);
181}
182
183#if 0
184unsigned int EmulateAll1(unsigned int opcode)
185{
186  switch ((opcode >> 24) & 0xf)
187  {
188     case 0xc:
189     case 0xd:
190       if ((opcode >> 20) & 0x1)
191       {
192          switch ((opcode >> 8) & 0xf)
193          {
194             case 0x1: return PerformLDF(opcode); break;
195             case 0x2: return PerformLFM(opcode); break;
196             default: return 0;
197          }
198       }
199       else
200       {
201          switch ((opcode >> 8) & 0xf)
202          {
203             case 0x1: return PerformSTF(opcode); break;
204             case 0x2: return PerformSFM(opcode); break;
205             default: return 0;
206          }
207      }
208     break;
209     
210     case 0xe: 
211       if (opcode & 0x10)
212         return EmulateCPDO(opcode);
213       else
214         return EmulateCPRT(opcode);
215     break;
216  
217     default: return 0;
218  }
219}
220#endif
221