fpa11.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.     NetWinder Floating Point Emulator
  3.     (c) Rebel.COM, 1998,1999
  4.     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.     You should have received a copy of the GNU General Public License
  14.     along with this program; if not, write to the Free Software
  15.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. #include "fpa11.h"
  18. #include "fpopcode.h"
  19. #include "fpmodule.h"
  20. #include "fpmodule.inl"
  21. #include <asm/system.h>
  22. /* forward declarations */
  23. unsigned int EmulateCPDO(const unsigned int);
  24. unsigned int EmulateCPDT(const unsigned int);
  25. unsigned int EmulateCPRT(const unsigned int);
  26. /* Reset the FPA11 chip.  Called to initialize and reset the emulator. */
  27. void resetFPA11(void)
  28. {
  29.   int i;
  30.   FPA11 *fpa11 = GET_FPA11();
  31.   
  32.   /* initialize the register type array */
  33.   for (i=0;i<=7;i++)
  34.   {
  35.     fpa11->fType[i] = typeNone;
  36.   }
  37.   
  38.   /* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */
  39.   fpa11->fpsr = FP_EMULATOR | BIT_AC;
  40.   
  41.   /* FPCR: set SB, AB and DA bits, clear all others */
  42. #if MAINTAIN_FPCR
  43.   fpa11->fpcr = MASK_RESET;
  44. #endif
  45. }
  46. void SetRoundingMode(const unsigned int opcode)
  47. {
  48. #if MAINTAIN_FPCR
  49.    FPA11 *fpa11 = GET_FPA11();
  50.    fpa11->fpcr &= ~MASK_ROUNDING_MODE;
  51. #endif   
  52.    switch (opcode & MASK_ROUNDING_MODE)
  53.    {
  54.       default:
  55.       case ROUND_TO_NEAREST:
  56.          float_rounding_mode = float_round_nearest_even;
  57. #if MAINTAIN_FPCR         
  58.          fpa11->fpcr |= ROUND_TO_NEAREST;
  59. #endif         
  60.       break;
  61.       
  62.       case ROUND_TO_PLUS_INFINITY:
  63.          float_rounding_mode = float_round_up;
  64. #if MAINTAIN_FPCR         
  65.          fpa11->fpcr |= ROUND_TO_PLUS_INFINITY;
  66. #endif         
  67.       break;
  68.       
  69.       case ROUND_TO_MINUS_INFINITY:
  70.          float_rounding_mode = float_round_down;
  71. #if MAINTAIN_FPCR         
  72.          fpa11->fpcr |= ROUND_TO_MINUS_INFINITY;
  73. #endif         
  74.       break;
  75.       
  76.       case ROUND_TO_ZERO:
  77.          float_rounding_mode = float_round_to_zero;
  78. #if MAINTAIN_FPCR         
  79.          fpa11->fpcr |= ROUND_TO_ZERO;
  80. #endif         
  81.       break;
  82.   }
  83. }
  84. void SetRoundingPrecision(const unsigned int opcode)
  85. {
  86. #if MAINTAIN_FPCR
  87.    FPA11 *fpa11 = GET_FPA11();
  88.    fpa11->fpcr &= ~MASK_ROUNDING_PRECISION;
  89. #endif   
  90.    switch (opcode & MASK_ROUNDING_PRECISION)
  91.    {
  92.       case ROUND_SINGLE:
  93.          floatx80_rounding_precision = 32;
  94. #if MAINTAIN_FPCR         
  95.          fpa11->fpcr |= ROUND_SINGLE;
  96. #endif         
  97.       break;
  98.       
  99.       case ROUND_DOUBLE:
  100.          floatx80_rounding_precision = 64;
  101. #if MAINTAIN_FPCR         
  102.          fpa11->fpcr |= ROUND_DOUBLE;
  103. #endif         
  104.       break;
  105.       
  106.       case ROUND_EXTENDED:
  107.          floatx80_rounding_precision = 80;
  108. #if MAINTAIN_FPCR         
  109.          fpa11->fpcr |= ROUND_EXTENDED;
  110. #endif         
  111.       break;
  112.       
  113.       default: floatx80_rounding_precision = 80;
  114.   }
  115. }
  116. /* Emulate the instruction in the opcode. */
  117. unsigned int EmulateAll(unsigned int opcode)
  118. {
  119.   unsigned int nRc = 0;
  120.   unsigned long flags;
  121.   FPA11 *fpa11; 
  122.   save_flags(flags); sti();
  123.   fpa11 = GET_FPA11();
  124.   if (fpa11->initflag == 0) /* good place for __builtin_expect */
  125.   {
  126.     resetFPA11();
  127.     SetRoundingMode(ROUND_TO_NEAREST);
  128.     SetRoundingPrecision(ROUND_EXTENDED);
  129.     fpa11->initflag = 1;
  130.   }
  131.   if (TEST_OPCODE(opcode,MASK_CPRT))
  132.   {
  133.     /* Emulate conversion opcodes. */
  134.     /* Emulate register transfer opcodes. */
  135.     /* Emulate comparison opcodes. */
  136.     nRc = EmulateCPRT(opcode);
  137.   }
  138.   else if (TEST_OPCODE(opcode,MASK_CPDO))
  139.   {
  140.     /* Emulate monadic arithmetic opcodes. */
  141.     /* Emulate dyadic arithmetic opcodes. */
  142.     nRc = EmulateCPDO(opcode);
  143.   }
  144.   else if (TEST_OPCODE(opcode,MASK_CPDT))
  145.   {
  146.     /* Emulate load/store opcodes. */
  147.     /* Emulate load/store multiple opcodes. */
  148.     nRc = EmulateCPDT(opcode);
  149.   }
  150.   else
  151.   {
  152.     /* Invalid instruction detected.  Return FALSE. */
  153.     nRc = 0;
  154.   }
  155.   restore_flags(flags);
  156.   return(nRc);
  157. }
  158. #if 0
  159. unsigned int EmulateAll1(unsigned int opcode)
  160. {
  161.   switch ((opcode >> 24) & 0xf)
  162.   {
  163.      case 0xc:
  164.      case 0xd:
  165.        if ((opcode >> 20) & 0x1)
  166.        {
  167.           switch ((opcode >> 8) & 0xf)
  168.           {
  169.              case 0x1: return PerformLDF(opcode); break;
  170.              case 0x2: return PerformLFM(opcode); break;
  171.              default: return 0;
  172.           }
  173.        }
  174.        else
  175.        {
  176.           switch ((opcode >> 8) & 0xf)
  177.           {
  178.              case 0x1: return PerformSTF(opcode); break;
  179.              case 0x2: return PerformSFM(opcode); break;
  180.              default: return 0;
  181.           }
  182.       }
  183.      break;
  184.      
  185.      case 0xe: 
  186.        if (opcode & 0x10)
  187.          return EmulateCPDO(opcode);
  188.        else
  189.          return EmulateCPRT(opcode);
  190.      break;
  191.   
  192.      default: return 0;
  193.   }
  194. }
  195. #endif