Annotation of qemu/linux-user/arm/nwfpe/fpa11_cpdt.c, revision 1.1.1.1

1.1       root        1: /*
                      2:     NetWinder Floating Point Emulator
                      3:     (c) Rebel.com, 1998-1999
                      4:     (c) Philip Blundell, 1998
                      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 "fpmodule.h"
                     27: //#include "fpmodule.inl"
                     28: 
                     29: //#include <asm/uaccess.h>
                     30: 
                     31: static inline
                     32: void loadSingle(const unsigned int Fn,const unsigned int *pMem)
                     33: {
                     34:    target_ulong addr = (target_ulong)(long)pMem;
                     35:    FPA11 *fpa11 = GET_FPA11();
                     36:    fpa11->fType[Fn] = typeSingle;
                     37:    /* FIXME - handle failure of get_user() */
                     38:    get_user_u32(fpa11->fpreg[Fn].fSingle, addr);
                     39: }
                     40: 
                     41: static inline
                     42: void loadDouble(const unsigned int Fn,const unsigned int *pMem)
                     43: {
                     44:    target_ulong addr = (target_ulong)(long)pMem;
                     45:    FPA11 *fpa11 = GET_FPA11();
                     46:    unsigned int *p;
                     47:    p = (unsigned int*)&fpa11->fpreg[Fn].fDouble;
                     48:    fpa11->fType[Fn] = typeDouble;
                     49: #ifdef WORDS_BIGENDIAN
                     50:    /* FIXME - handle failure of get_user() */
                     51:    get_user_u32(p[0], addr); /* sign & exponent */
                     52:    get_user_u32(p[1], addr + 4);
                     53: #else
                     54:    /* FIXME - handle failure of get_user() */
                     55:    get_user_u32(p[0], addr + 4);
                     56:    get_user_u32(p[1], addr); /* sign & exponent */
                     57: #endif
                     58: }
                     59: 
                     60: static inline
                     61: void loadExtended(const unsigned int Fn,const unsigned int *pMem)
                     62: {
                     63:    target_ulong addr = (target_ulong)(long)pMem;
                     64:    FPA11 *fpa11 = GET_FPA11();
                     65:    unsigned int *p;
                     66:    p = (unsigned int*)&fpa11->fpreg[Fn].fExtended;
                     67:    fpa11->fType[Fn] = typeExtended;
                     68:    /* FIXME - handle failure of get_user() */
                     69:    get_user_u32(p[0], addr);  /* sign & exponent */
                     70:    get_user_u32(p[1], addr + 8);  /* ls bits */
                     71:    get_user_u32(p[2], addr + 4);  /* ms bits */
                     72: }
                     73: 
                     74: static inline
                     75: void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
                     76: {
                     77:    target_ulong addr = (target_ulong)(long)pMem;
                     78:    FPA11 *fpa11 = GET_FPA11();
                     79:    register unsigned int *p;
                     80:    unsigned long x;
                     81: 
                     82:    p = (unsigned int*)&(fpa11->fpreg[Fn]);
                     83:    /* FIXME - handle failure of get_user() */
                     84:    get_user_u32(x, addr);
                     85:    fpa11->fType[Fn] = (x >> 14) & 0x00000003;
                     86: 
                     87:    switch (fpa11->fType[Fn])
                     88:    {
                     89:       case typeSingle:
                     90:       case typeDouble:
                     91:       {
                     92:          /* FIXME - handle failure of get_user() */
                     93:          get_user_u32(p[0], addr + 8);  /* Single */
                     94:          get_user_u32(p[1], addr + 4);  /* double msw */
                     95:          p[2] = 0;        /* empty */
                     96:       }
                     97:       break;
                     98: 
                     99:       case typeExtended:
                    100:       {
                    101:          /* FIXME - handle failure of get_user() */
                    102:          get_user_u32(p[1], addr + 8);
                    103:          get_user_u32(p[2], addr + 4);  /* msw */
                    104:          p[0] = (x & 0x80003fff);
                    105:       }
                    106:       break;
                    107:    }
                    108: }
                    109: 
                    110: static inline
                    111: void storeSingle(const unsigned int Fn,unsigned int *pMem)
                    112: {
                    113:    target_ulong addr = (target_ulong)(long)pMem;
                    114:    FPA11 *fpa11 = GET_FPA11();
                    115:    float32 val;
                    116:    register unsigned int *p = (unsigned int*)&val;
                    117: 
                    118:    switch (fpa11->fType[Fn])
                    119:    {
                    120:       case typeDouble:
                    121:          val = float64_to_float32(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
                    122:       break;
                    123: 
                    124:       case typeExtended:
                    125:          val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
                    126:       break;
                    127: 
                    128:       default: val = fpa11->fpreg[Fn].fSingle;
                    129:    }
                    130: 
                    131:    /* FIXME - handle put_user() failures */
                    132:    put_user_u32(p[0], addr);
                    133: }
                    134: 
                    135: static inline
                    136: void storeDouble(const unsigned int Fn,unsigned int *pMem)
                    137: {
                    138:    target_ulong addr = (target_ulong)(long)pMem;
                    139:    FPA11 *fpa11 = GET_FPA11();
                    140:    float64 val;
                    141:    register unsigned int *p = (unsigned int*)&val;
                    142: 
                    143:    switch (fpa11->fType[Fn])
                    144:    {
                    145:       case typeSingle:
                    146:          val = float32_to_float64(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
                    147:       break;
                    148: 
                    149:       case typeExtended:
                    150:          val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status);
                    151:       break;
                    152: 
                    153:       default: val = fpa11->fpreg[Fn].fDouble;
                    154:    }
                    155:    /* FIXME - handle put_user() failures */
                    156: #ifdef WORDS_BIGENDIAN
                    157:    put_user_u32(p[0], addr);   /* msw */
                    158:    put_user_u32(p[1], addr + 4);       /* lsw */
                    159: #else
                    160:    put_user_u32(p[1], addr);   /* msw */
                    161:    put_user_u32(p[0], addr + 4);       /* lsw */
                    162: #endif
                    163: }
                    164: 
                    165: static inline
                    166: void storeExtended(const unsigned int Fn,unsigned int *pMem)
                    167: {
                    168:    target_ulong addr = (target_ulong)(long)pMem;
                    169:    FPA11 *fpa11 = GET_FPA11();
                    170:    floatx80 val;
                    171:    register unsigned int *p = (unsigned int*)&val;
                    172: 
                    173:    switch (fpa11->fType[Fn])
                    174:    {
                    175:       case typeSingle:
                    176:          val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
                    177:       break;
                    178: 
                    179:       case typeDouble:
                    180:          val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
                    181:       break;
                    182: 
                    183:       default: val = fpa11->fpreg[Fn].fExtended;
                    184:    }
                    185: 
                    186:    /* FIXME - handle put_user() failures */
                    187:    put_user_u32(p[0], addr); /* sign & exp */
                    188:    put_user_u32(p[1], addr + 8);
                    189:    put_user_u32(p[2], addr + 4); /* msw */
                    190: }
                    191: 
                    192: static inline
                    193: void storeMultiple(const unsigned int Fn,unsigned int *pMem)
                    194: {
                    195:    target_ulong addr = (target_ulong)(long)pMem;
                    196:    FPA11 *fpa11 = GET_FPA11();
                    197:    register unsigned int nType, *p;
                    198: 
                    199:    p = (unsigned int*)&(fpa11->fpreg[Fn]);
                    200:    nType = fpa11->fType[Fn];
                    201: 
                    202:    switch (nType)
                    203:    {
                    204:       case typeSingle:
                    205:       case typeDouble:
                    206:       {
                    207:          put_user_u32(p[0], addr + 8); /* single */
                    208:         put_user_u32(p[1], addr + 4); /* double msw */
                    209:         put_user_u32(nType << 14, addr);
                    210:       }
                    211:       break;
                    212: 
                    213:       case typeExtended:
                    214:       {
                    215:          put_user_u32(p[2], addr + 4); /* msw */
                    216:         put_user_u32(p[1], addr + 8);
                    217:         put_user_u32((p[0] & 0x80003fff) | (nType << 14), addr);
                    218:       }
                    219:       break;
                    220:    }
                    221: }
                    222: 
                    223: unsigned int PerformLDF(const unsigned int opcode)
                    224: {
                    225:    unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
                    226:      write_back = WRITE_BACK(opcode);
                    227: 
                    228:    //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
                    229: 
                    230:    pBase = (unsigned int*)readRegister(getRn(opcode));
                    231:    if (REG_PC == getRn(opcode))
                    232:    {
                    233:      pBase += 2;
                    234:      write_back = 0;
                    235:    }
                    236: 
                    237:    pFinal = pBase;
                    238:    if (BIT_UP_SET(opcode))
                    239:      pFinal += getOffset(opcode);
                    240:    else
                    241:      pFinal -= getOffset(opcode);
                    242: 
                    243:    if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
                    244: 
                    245:    switch (opcode & MASK_TRANSFER_LENGTH)
                    246:    {
                    247:       case TRANSFER_SINGLE  : loadSingle(getFd(opcode),pAddress);   break;
                    248:       case TRANSFER_DOUBLE  : loadDouble(getFd(opcode),pAddress);   break;
                    249:       case TRANSFER_EXTENDED: loadExtended(getFd(opcode),pAddress); break;
                    250:       default: nRc = 0;
                    251:    }
                    252: 
                    253:    if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
                    254:    return nRc;
                    255: }
                    256: 
                    257: unsigned int PerformSTF(const unsigned int opcode)
                    258: {
                    259:    unsigned int *pBase, *pAddress, *pFinal, nRc = 1,
                    260:      write_back = WRITE_BACK(opcode);
                    261: 
                    262:    //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
                    263:    SetRoundingMode(ROUND_TO_NEAREST);
                    264: 
                    265:    pBase = (unsigned int*)readRegister(getRn(opcode));
                    266:    if (REG_PC == getRn(opcode))
                    267:    {
                    268:      pBase += 2;
                    269:      write_back = 0;
                    270:    }
                    271: 
                    272:    pFinal = pBase;
                    273:    if (BIT_UP_SET(opcode))
                    274:      pFinal += getOffset(opcode);
                    275:    else
                    276:      pFinal -= getOffset(opcode);
                    277: 
                    278:    if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
                    279: 
                    280:    switch (opcode & MASK_TRANSFER_LENGTH)
                    281:    {
                    282:       case TRANSFER_SINGLE  : storeSingle(getFd(opcode),pAddress);   break;
                    283:       case TRANSFER_DOUBLE  : storeDouble(getFd(opcode),pAddress);   break;
                    284:       case TRANSFER_EXTENDED: storeExtended(getFd(opcode),pAddress); break;
                    285:       default: nRc = 0;
                    286:    }
                    287: 
                    288:    if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
                    289:    return nRc;
                    290: }
                    291: 
                    292: unsigned int PerformLFM(const unsigned int opcode)
                    293: {
                    294:    unsigned int i, Fd, *pBase, *pAddress, *pFinal,
                    295:      write_back = WRITE_BACK(opcode);
                    296: 
                    297:    pBase = (unsigned int*)readRegister(getRn(opcode));
                    298:    if (REG_PC == getRn(opcode))
                    299:    {
                    300:      pBase += 2;
                    301:      write_back = 0;
                    302:    }
                    303: 
                    304:    pFinal = pBase;
                    305:    if (BIT_UP_SET(opcode))
                    306:      pFinal += getOffset(opcode);
                    307:    else
                    308:      pFinal -= getOffset(opcode);
                    309: 
                    310:    if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
                    311: 
                    312:    Fd = getFd(opcode);
                    313:    for (i=getRegisterCount(opcode);i>0;i--)
                    314:    {
                    315:      loadMultiple(Fd,pAddress);
                    316:      pAddress += 3; Fd++;
                    317:      if (Fd == 8) Fd = 0;
                    318:    }
                    319: 
                    320:    if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
                    321:    return 1;
                    322: }
                    323: 
                    324: unsigned int PerformSFM(const unsigned int opcode)
                    325: {
                    326:    unsigned int i, Fd, *pBase, *pAddress, *pFinal,
                    327:      write_back = WRITE_BACK(opcode);
                    328: 
                    329:    pBase = (unsigned int*)readRegister(getRn(opcode));
                    330:    if (REG_PC == getRn(opcode))
                    331:    {
                    332:      pBase += 2;
                    333:      write_back = 0;
                    334:    }
                    335: 
                    336:    pFinal = pBase;
                    337:    if (BIT_UP_SET(opcode))
                    338:      pFinal += getOffset(opcode);
                    339:    else
                    340:      pFinal -= getOffset(opcode);
                    341: 
                    342:    if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
                    343: 
                    344:    Fd = getFd(opcode);
                    345:    for (i=getRegisterCount(opcode);i>0;i--)
                    346:    {
                    347:      storeMultiple(Fd,pAddress);
                    348:      pAddress += 3; Fd++;
                    349:      if (Fd == 8) Fd = 0;
                    350:    }
                    351: 
                    352:    if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
                    353:    return 1;
                    354: }
                    355: 
                    356: #if 1
                    357: unsigned int EmulateCPDT(const unsigned int opcode)
                    358: {
                    359:   unsigned int nRc = 0;
                    360: 
                    361:   //printk("EmulateCPDT(0x%08x)\n",opcode);
                    362: 
                    363:   if (LDF_OP(opcode))
                    364:   {
                    365:     nRc = PerformLDF(opcode);
                    366:   }
                    367:   else if (LFM_OP(opcode))
                    368:   {
                    369:     nRc = PerformLFM(opcode);
                    370:   }
                    371:   else if (STF_OP(opcode))
                    372:   {
                    373:     nRc = PerformSTF(opcode);
                    374:   }
                    375:   else if (SFM_OP(opcode))
                    376:   {
                    377:     nRc = PerformSFM(opcode);
                    378:   }
                    379:   else
                    380:   {
                    381:     nRc = 0;
                    382:   }
                    383: 
                    384:   return nRc;
                    385: }
                    386: #endif

unix.superglobalmegacorp.com

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