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

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

unix.superglobalmegacorp.com

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