Annotation of qemu/linux-user/arm/nwfpe/fpa11.c, revision 1.1.1.2

1.1       root        1: /*
                      2:     NetWinder Floating Point Emulator
                      3:     (c) Rebel.COM, 1998,1999
                      4: 
                      5:     Direct questions, comments to Scott Bambrough <[email protected]>
                      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: 
                     24: #include "fpopcode.h"
                     25: 
                     26: //#include "fpmodule.h"
                     27: //#include "fpmodule.inl"
                     28: 
                     29: //#include <asm/system.h>
                     30: 
                     31: #include <stdio.h>
                     32: 
                     33: FPA11* qemufpa=0;
                     34: CPUARMState* user_registers;
                     35: 
                     36: /* Reset the FPA11 chip.  Called to initialize and reset the emulator. */
                     37: void 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: #ifdef MAINTAIN_FPCR
                     53:   fpa11->fpcr = MASK_RESET;
                     54: #endif
                     55: }
                     56: 
                     57: void SetRoundingMode(const unsigned int opcode)
                     58: {
                     59:     int rounding_mode;
                     60:    FPA11 *fpa11 = GET_FPA11();
                     61: 
                     62: #ifdef MAINTAIN_FPCR
                     63:    fpa11->fpcr &= ~MASK_ROUNDING_MODE;
                     64: #endif
                     65:    switch (opcode & MASK_ROUNDING_MODE)
                     66:    {
                     67:       default:
                     68:       case ROUND_TO_NEAREST:
                     69:          rounding_mode = float_round_nearest_even;
                     70: #ifdef MAINTAIN_FPCR
                     71:          fpa11->fpcr |= ROUND_TO_NEAREST;
                     72: #endif
                     73:       break;
                     74: 
                     75:       case ROUND_TO_PLUS_INFINITY:
                     76:          rounding_mode = float_round_up;
                     77: #ifdef MAINTAIN_FPCR
                     78:          fpa11->fpcr |= ROUND_TO_PLUS_INFINITY;
                     79: #endif
                     80:       break;
                     81: 
                     82:       case ROUND_TO_MINUS_INFINITY:
                     83:          rounding_mode = float_round_down;
                     84: #ifdef MAINTAIN_FPCR
                     85:          fpa11->fpcr |= ROUND_TO_MINUS_INFINITY;
                     86: #endif
                     87:       break;
                     88: 
                     89:       case ROUND_TO_ZERO:
                     90:          rounding_mode = float_round_to_zero;
                     91: #ifdef MAINTAIN_FPCR
                     92:          fpa11->fpcr |= ROUND_TO_ZERO;
                     93: #endif
                     94:       break;
                     95:   }
                     96:    set_float_rounding_mode(rounding_mode, &fpa11->fp_status);
                     97: }
                     98: 
                     99: void SetRoundingPrecision(const unsigned int opcode)
                    100: {
                    101:     int rounding_precision;
                    102:    FPA11 *fpa11 = GET_FPA11();
                    103: #ifdef MAINTAIN_FPCR
                    104:    fpa11->fpcr &= ~MASK_ROUNDING_PRECISION;
                    105: #endif
                    106:    switch (opcode & MASK_ROUNDING_PRECISION)
                    107:    {
                    108:       case ROUND_SINGLE:
                    109:          rounding_precision = 32;
                    110: #ifdef MAINTAIN_FPCR
                    111:          fpa11->fpcr |= ROUND_SINGLE;
                    112: #endif
                    113:       break;
                    114: 
                    115:       case ROUND_DOUBLE:
                    116:          rounding_precision = 64;
                    117: #ifdef MAINTAIN_FPCR
                    118:          fpa11->fpcr |= ROUND_DOUBLE;
                    119: #endif
                    120:       break;
                    121: 
                    122:       case ROUND_EXTENDED:
                    123:          rounding_precision = 80;
                    124: #ifdef MAINTAIN_FPCR
                    125:          fpa11->fpcr |= ROUND_EXTENDED;
                    126: #endif
                    127:       break;
                    128: 
                    129:       default: rounding_precision = 80;
                    130:   }
                    131:    set_floatx80_rounding_precision(rounding_precision, &fpa11->fp_status);
                    132: }
                    133: 
                    134: /* Emulate the instruction in the opcode. */
                    135: /* ??? This is not thread safe.  */
                    136: unsigned int EmulateAll(unsigned int opcode, FPA11* qfpa, CPUARMState* qregs)
                    137: {
                    138:   unsigned int nRc = 0;
                    139: //  unsigned long flags;
                    140:   FPA11 *fpa11;
                    141: //  save_flags(flags); sti();
                    142: 
                    143:   qemufpa=qfpa;
                    144:   user_registers=qregs;
                    145: 
                    146: #if 0
                    147:   fprintf(stderr,"emulating FP insn 0x%08x, PC=0x%08x\n",
                    148:           opcode, qregs[REG_PC]);
                    149: #endif
                    150:   fpa11 = GET_FPA11();
                    151: 
                    152:   if (fpa11->initflag == 0)            /* good place for __builtin_expect */
                    153:   {
                    154:     resetFPA11();
                    155:     SetRoundingMode(ROUND_TO_NEAREST);
                    156:     SetRoundingPrecision(ROUND_EXTENDED);
                    157:     fpa11->initflag = 1;
                    158:   }
                    159: 
                    160:   set_float_exception_flags(0, &fpa11->fp_status);
                    161: 
                    162:   if (TEST_OPCODE(opcode,MASK_CPRT))
                    163:   {
                    164:     //fprintf(stderr,"emulating CPRT\n");
                    165:     /* Emulate conversion opcodes. */
                    166:     /* Emulate register transfer opcodes. */
                    167:     /* Emulate comparison opcodes. */
                    168:     nRc = EmulateCPRT(opcode);
                    169:   }
                    170:   else if (TEST_OPCODE(opcode,MASK_CPDO))
                    171:   {
                    172:     //fprintf(stderr,"emulating CPDO\n");
                    173:     /* Emulate monadic arithmetic opcodes. */
                    174:     /* Emulate dyadic arithmetic opcodes. */
                    175:     nRc = EmulateCPDO(opcode);
                    176:   }
                    177:   else if (TEST_OPCODE(opcode,MASK_CPDT))
                    178:   {
                    179:     //fprintf(stderr,"emulating CPDT\n");
                    180:     /* Emulate load/store opcodes. */
                    181:     /* Emulate load/store multiple opcodes. */
                    182:     nRc = EmulateCPDT(opcode);
                    183:   }
                    184:   else
                    185:   {
                    186:     /* Invalid instruction detected.  Return FALSE. */
                    187:     nRc = 0;
                    188:   }
                    189: 
                    190: //  restore_flags(flags);
                    191:   if(nRc == 1 && get_float_exception_flags(&fpa11->fp_status))
                    192:   {
                    193:     //printf("fef 0x%x\n",float_exception_flags);
                    194:     nRc=-get_float_exception_flags(&fpa11->fp_status);
                    195:   }
                    196: 
                    197:   //printf("returning %d\n",nRc);
                    198:   return(nRc);
                    199: }
                    200: 
                    201: #if 0
                    202: unsigned int EmulateAll1(unsigned int opcode)
                    203: {
                    204:   switch ((opcode >> 24) & 0xf)
                    205:   {
                    206:      case 0xc:
                    207:      case 0xd:
                    208:        if ((opcode >> 20) & 0x1)
                    209:        {
                    210:           switch ((opcode >> 8) & 0xf)
                    211:           {
                    212:              case 0x1: return PerformLDF(opcode); break;
                    213:              case 0x2: return PerformLFM(opcode); break;
                    214:              default: return 0;
                    215:           }
                    216:        }
                    217:        else
                    218:        {
                    219:           switch ((opcode >> 8) & 0xf)
                    220:           {
                    221:              case 0x1: return PerformSTF(opcode); break;
                    222:              case 0x2: return PerformSFM(opcode); break;
                    223:              default: return 0;
                    224:           }
                    225:       }
                    226:      break;
                    227: 
                    228:      case 0xe:
                    229:        if (opcode & 0x10)
                    230:          return EmulateCPDO(opcode);
                    231:        else
                    232:          return EmulateCPRT(opcode);
                    233:      break;
                    234: 
                    235:      default: return 0;
                    236:   }
                    237: }
                    238: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.