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

unix.superglobalmegacorp.com

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