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

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

unix.superglobalmegacorp.com

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