qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

fpa11_cpdt.c (9540B)


      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 <scottb@netwinder.org>
      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, see <http://www.gnu.org/licenses/>.
     20 */
     21 
     22 #include "qemu/osdep.h"
     23 #include "fpa11.h"
     24 #include "fpu/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, target_ulong addr)
     33 {
     34    FPA11 *fpa11 = GET_FPA11();
     35    fpa11->fType[Fn] = typeSingle;
     36    /* FIXME - handle failure of get_user() */
     37    get_user_u32(float32_val(fpa11->fpreg[Fn].fSingle), addr);
     38 }
     39 
     40 static inline
     41 void loadDouble(const unsigned int Fn, target_ulong addr)
     42 {
     43    FPA11 *fpa11 = GET_FPA11();
     44    unsigned int *p;
     45    p = (unsigned int*)&fpa11->fpreg[Fn].fDouble;
     46    fpa11->fType[Fn] = typeDouble;
     47 #if HOST_BIG_ENDIAN
     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
     59 void loadExtended(const unsigned int Fn, target_ulong addr)
     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
     72 void loadMultiple(const unsigned int Fn, target_ulong addr)
     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
    107 void storeSingle(const unsigned int Fn, target_ulong addr)
    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
    131 void storeDouble(const unsigned int Fn, target_ulong addr)
    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 #if HOST_BIG_ENDIAN
    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
    160 void storeExtended(const unsigned int Fn, target_ulong addr)
    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
    186 void storeMultiple(const unsigned int Fn, target_ulong addr)
    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 
    215 static unsigned int PerformLDF(const unsigned int opcode)
    216 {
    217     target_ulong pBase, pAddress, pFinal;
    218     unsigned int nRc = 1,
    219      write_back = WRITE_BACK(opcode);
    220 
    221    //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
    222 
    223    pBase = readRegister(getRn(opcode));
    224    if (ARM_REG_PC == getRn(opcode))
    225    {
    226      pBase += 8;
    227      write_back = 0;
    228    }
    229 
    230    pFinal = pBase;
    231    if (BIT_UP_SET(opcode))
    232      pFinal += getOffset(opcode) * 4;
    233    else
    234      pFinal -= getOffset(opcode) * 4;
    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 
    250 static unsigned int PerformSTF(const unsigned int opcode)
    251 {
    252    target_ulong pBase, pAddress, pFinal;
    253    unsigned int nRc = 1,
    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 
    259    pBase = readRegister(getRn(opcode));
    260    if (ARM_REG_PC == getRn(opcode))
    261    {
    262      pBase += 8;
    263      write_back = 0;
    264    }
    265 
    266    pFinal = pBase;
    267    if (BIT_UP_SET(opcode))
    268      pFinal += getOffset(opcode) * 4;
    269    else
    270      pFinal -= getOffset(opcode) * 4;
    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 
    286 static unsigned int PerformLFM(const unsigned int opcode)
    287 {
    288    unsigned int i, Fd,
    289      write_back = WRITE_BACK(opcode);
    290    target_ulong pBase, pAddress, pFinal;
    291 
    292    pBase = readRegister(getRn(opcode));
    293    if (ARM_REG_PC == getRn(opcode))
    294    {
    295      pBase += 8;
    296      write_back = 0;
    297    }
    298 
    299    pFinal = pBase;
    300    if (BIT_UP_SET(opcode))
    301      pFinal += getOffset(opcode) * 4;
    302    else
    303      pFinal -= getOffset(opcode) * 4;
    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);
    311      pAddress += 12; Fd++;
    312      if (Fd == 8) Fd = 0;
    313    }
    314 
    315    if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
    316    return 1;
    317 }
    318 
    319 static unsigned int PerformSFM(const unsigned int opcode)
    320 {
    321    unsigned int i, Fd,
    322      write_back = WRITE_BACK(opcode);
    323    target_ulong pBase, pAddress, pFinal;
    324 
    325    pBase = readRegister(getRn(opcode));
    326    if (ARM_REG_PC == getRn(opcode))
    327    {
    328      pBase += 8;
    329      write_back = 0;
    330    }
    331 
    332    pFinal = pBase;
    333    if (BIT_UP_SET(opcode))
    334      pFinal += getOffset(opcode) * 4;
    335    else
    336      pFinal -= getOffset(opcode) * 4;
    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);
    344      pAddress += 12; Fd++;
    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