Annotation of qemu/target-arm/nwfpe/fpa11_cprt.c, revision 1.1.1.3

1.1       root        1: /*
                      2:     NetWinder Floating Point Emulator
                      3:     (c) Rebel.COM, 1998,1999
                      4:     (c) Philip Blundell, 1999
                      5: 
                      6:     Direct questions, comments to Scott Bambrough <[email protected]>
                      7: 
                      8:     This program is free software; you can redistribute it and/or modify
                      9:     it under the terms of the GNU General Public License as published by
                     10:     the Free Software Foundation; either version 2 of the License, or
                     11:     (at your option) any later version.
                     12: 
                     13:     This program is distributed in the hope that it will be useful,
                     14:     but WITHOUT ANY WARRANTY; without even the implied warranty of
                     15:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     16:     GNU General Public License for more details.
                     17: 
                     18:     You should have received a copy of the GNU General Public License
                     19:     along with this program; if not, write to the Free Software
                     20:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     21: */
                     22: 
                     23: #include "fpa11.h"
                     24: #include "softfloat.h"
                     25: #include "fpopcode.h"
                     26: #include "fpa11.inl"
                     27: //#include "fpmodule.h"
                     28: //#include "fpmodule.inl"
                     29: 
                     30: void SetRoundingMode(const unsigned int opcode);
                     31: 
                     32: unsigned int PerformFLT(const unsigned int opcode);
                     33: unsigned int PerformFIX(const unsigned int opcode);
                     34: 
                     35: static unsigned int
                     36: PerformComparison(const unsigned int opcode);
                     37: 
                     38: unsigned int EmulateCPRT(const unsigned int opcode)
                     39: {
                     40:   unsigned int nRc = 1;
                     41: 
                     42:   //printk("EmulateCPRT(0x%08x)\n",opcode);
                     43: 
                     44:   if (opcode & 0x800000)
                     45:   {
                     46:      /* This is some variant of a comparison (PerformComparison will
                     47:        sort out which one).  Since most of the other CPRT
                     48:        instructions are oddball cases of some sort or other it makes
                     49:        sense to pull this out into a fast path.  */
                     50:      return PerformComparison(opcode);
                     51:   }
                     52: 
                     53:   /* Hint to GCC that we'd like a jump table rather than a load of CMPs */
                     54:   switch ((opcode & 0x700000) >> 20)
                     55:   {
                     56:     case  FLT_CODE >> 20: nRc = PerformFLT(opcode); break;
                     57:     case  FIX_CODE >> 20: nRc = PerformFIX(opcode); break;
                     58:     
                     59:     case  WFS_CODE >> 20: writeFPSR(readRegister(getRd(opcode))); break;
                     60:     case  RFS_CODE >> 20: writeRegister(getRd(opcode),readFPSR()); break;
                     61: 
                     62: #if 0    /* We currently have no use for the FPCR, so there's no point
                     63:            in emulating it. */
                     64:     case  WFC_CODE >> 20: writeFPCR(readRegister(getRd(opcode)));
                     65:     case  RFC_CODE >> 20: writeRegister(getRd(opcode),readFPCR()); break;
                     66: #endif
                     67: 
                     68:     default: nRc = 0;
                     69:   }
                     70:   
                     71:   return nRc;
                     72: }
                     73: 
                     74: unsigned int PerformFLT(const unsigned int opcode)
                     75: {
                     76:    FPA11 *fpa11 = GET_FPA11();
                     77:    
                     78:    unsigned int nRc = 1;
                     79:    SetRoundingMode(opcode);
                     80: 
                     81:    switch (opcode & MASK_ROUNDING_PRECISION)
                     82:    {
                     83:       case ROUND_SINGLE:
                     84:       {
                     85:         fpa11->fType[getFn(opcode)] = typeSingle;
                     86:         fpa11->fpreg[getFn(opcode)].fSingle =
                     87:           int32_to_float32(readRegister(getRd(opcode)), &fpa11->fp_status);
                     88:       }
                     89:       break;
                     90: 
                     91:       case ROUND_DOUBLE:
                     92:       {
                     93:         fpa11->fType[getFn(opcode)] = typeDouble;
                     94:         fpa11->fpreg[getFn(opcode)].fDouble =
                     95:             int32_to_float64(readRegister(getRd(opcode)), &fpa11->fp_status);
                     96:       }
                     97:       break;
                     98:         
                     99:       case ROUND_EXTENDED:
                    100:       {
                    101:         fpa11->fType[getFn(opcode)] = typeExtended;
                    102:         fpa11->fpreg[getFn(opcode)].fExtended =
                    103:           int32_to_floatx80(readRegister(getRd(opcode)), &fpa11->fp_status);
                    104:       }
                    105:       break;
                    106:       
                    107:       default: nRc = 0;
                    108:   }
                    109:   
                    110:   return nRc;
                    111: }
                    112: 
                    113: unsigned int PerformFIX(const unsigned int opcode)
                    114: {
                    115:    FPA11 *fpa11 = GET_FPA11();
                    116:    unsigned int nRc = 1;
                    117:    unsigned int Fn = getFm(opcode);
                    118:    
                    119:    SetRoundingMode(opcode);
                    120: 
                    121:    switch (fpa11->fType[Fn])
                    122:    {
                    123:       case typeSingle:
                    124:       {
                    125:          writeRegister(getRd(opcode),
                    126:                       float32_to_int32(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status));
                    127:       }
                    128:       break;
                    129: 
                    130:       case typeDouble:
                    131:       {
1.1.1.2   root      132:          //printf("F%d is 0x%" PRIx64 "\n",Fn,fpa11->fpreg[Fn].fDouble);
1.1       root      133:          writeRegister(getRd(opcode),
                    134:                       float64_to_int32(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status));
                    135:       }
                    136:       break;
                    137:                       
                    138:       case typeExtended:
                    139:       {
                    140:          writeRegister(getRd(opcode),
                    141:                       floatx80_to_int32(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status));
                    142:       }
                    143:       break;
                    144:       
                    145:       default: nRc = 0;
                    146:   }
                    147:   
                    148:   return nRc;
                    149: }
                    150: 
                    151:    
                    152: static unsigned int __inline__
                    153: PerformComparisonOperation(floatx80 Fn, floatx80 Fm)
                    154: {
                    155:    FPA11 *fpa11 = GET_FPA11();
                    156:    unsigned int flags = 0;
                    157: 
                    158:    /* test for less than condition */
                    159:    if (floatx80_lt(Fn,Fm, &fpa11->fp_status))
                    160:    {
                    161:       flags |= CC_NEGATIVE;
                    162:    }
                    163:   
                    164:    /* test for equal condition */
                    165:    if (floatx80_eq(Fn,Fm, &fpa11->fp_status))
                    166:    {
                    167:       flags |= CC_ZERO;
                    168:    }
                    169: 
                    170:    /* test for greater than or equal condition */
                    171:    if (floatx80_lt(Fm,Fn, &fpa11->fp_status))
                    172:    {
                    173:       flags |= CC_CARRY;
                    174:    }
                    175:    
                    176:    writeConditionCodes(flags);
                    177:    return 1;
                    178: }
                    179: 
                    180: /* This instruction sets the flags N, Z, C, V in the FPSR. */
                    181:    
                    182: static unsigned int PerformComparison(const unsigned int opcode)
                    183: {
                    184:    FPA11 *fpa11 = GET_FPA11();
                    185:    unsigned int Fn, Fm;
                    186:    floatx80 rFn, rFm;
                    187:    int e_flag = opcode & 0x400000;     /* 1 if CxFE */
                    188:    int n_flag = opcode & 0x200000;     /* 1 if CNxx */
                    189:    unsigned int flags = 0;
                    190: 
                    191:    //printk("PerformComparison(0x%08x)\n",opcode);
                    192: 
                    193:    Fn = getFn(opcode);
                    194:    Fm = getFm(opcode);
                    195: 
                    196:    /* Check for unordered condition and convert all operands to 80-bit
                    197:       format.
                    198:       ?? Might be some mileage in avoiding this conversion if possible.
                    199:       Eg, if both operands are 32-bit, detect this and do a 32-bit
                    200:       comparison (cheaper than an 80-bit one).  */
                    201:    switch (fpa11->fType[Fn])
                    202:    {
                    203:       case typeSingle: 
                    204:         //printk("single.\n");
                    205:        if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
                    206:           goto unordered;
                    207:         rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
                    208:       break;
                    209: 
                    210:       case typeDouble: 
                    211:         //printk("double.\n");
                    212:        if (float64_is_nan(fpa11->fpreg[Fn].fDouble))
                    213:           goto unordered;
                    214:         rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
                    215:       break;
                    216:       
                    217:       case typeExtended: 
                    218:         //printk("extended.\n");
                    219:        if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended))
                    220:           goto unordered;
                    221:         rFn = fpa11->fpreg[Fn].fExtended;
                    222:       break;
                    223:       
                    224:       default: return 0;
                    225:    }
                    226: 
                    227:    if (CONSTANT_FM(opcode))
                    228:    {
                    229:      //printk("Fm is a constant: #%d.\n",Fm);
                    230:      rFm = getExtendedConstant(Fm);
                    231:      if (floatx80_is_nan(rFm))
                    232:         goto unordered;
                    233:    }
                    234:    else
                    235:    {
                    236:      //printk("Fm = r%d which contains a ",Fm);
                    237:       switch (fpa11->fType[Fm])
                    238:       {
                    239:          case typeSingle: 
                    240:            //printk("single.\n");
                    241:           if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
                    242:              goto unordered;
                    243:            rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status);
                    244:          break;
                    245: 
                    246:          case typeDouble: 
                    247:            //printk("double.\n");
                    248:           if (float64_is_nan(fpa11->fpreg[Fm].fDouble))
                    249:              goto unordered;
                    250:            rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble, &fpa11->fp_status);
                    251:          break;
                    252:       
                    253:          case typeExtended: 
                    254:            //printk("extended.\n");
                    255:           if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended))
                    256:              goto unordered;
                    257:            rFm = fpa11->fpreg[Fm].fExtended;
                    258:          break;
                    259:       
                    260:          default: return 0;
                    261:       }
                    262:    }
                    263: 
                    264:    if (n_flag)
                    265:    {
                    266:       rFm.high ^= 0x8000;
                    267:    }
                    268: 
                    269:    return PerformComparisonOperation(rFn,rFm);
                    270: 
                    271:  unordered:
                    272:    /* ?? The FPA data sheet is pretty vague about this, in particular
                    273:       about whether the non-E comparisons can ever raise exceptions.
                    274:       This implementation is based on a combination of what it says in
                    275:       the data sheet, observation of how the Acorn emulator actually
                    276:       behaves (and how programs expect it to) and guesswork.  */
                    277:    flags |= CC_OVERFLOW;
                    278:    flags &= ~(CC_ZERO | CC_NEGATIVE);
                    279: 
                    280:    if (BIT_AC & readFPSR()) flags |= CC_CARRY;
                    281: 
                    282:    if (e_flag) float_raise(float_flag_invalid, &fpa11->fp_status);
                    283: 
                    284:    writeConditionCodes(flags);
                    285:    return 1;
                    286: }

unix.superglobalmegacorp.com

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