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

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:       {
        !           136:          //printf("F%d is 0x%llx\n",Fn,fpa11->fpreg[Fn].fDouble);
        !           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.