Annotation of qemu/linux-user/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: 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: 
        !           150: static unsigned int __inline__
        !           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.