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

unix.superglobalmegacorp.com

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