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

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

unix.superglobalmegacorp.com

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