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

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
1.1.1.4   root       18:     along with this program; if not, see <http://www.gnu.org/licenses/>.
1.1       root       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: 
1.1.1.3   root       32: FPA11* qemufpa = NULL;
1.1       root       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",
1.1.1.5 ! root      147:           opcode, qregs[ARM_REG_PC]);
1.1       root      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);
1.1.1.3   root      193:     nRc = -get_float_exception_flags(&fpa11->fp_status);
1.1       root      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

unix.superglobalmegacorp.com

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