18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci NetWinder Floating Point Emulator 48c2ecf20Sopenharmony_ci (c) Rebel.com, 1998-1999 58c2ecf20Sopenharmony_ci (c) Philip Blundell, 1998, 2001 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci Direct questions, comments to Scott Bambrough <scottb@netwinder.org> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci*/ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include "fpa11.h" 128c2ecf20Sopenharmony_ci#include "softfloat.h" 138c2ecf20Sopenharmony_ci#include "fpopcode.h" 148c2ecf20Sopenharmony_ci#include "fpmodule.h" 158c2ecf20Sopenharmony_ci#include "fpmodule.inl" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic inline void loadSingle(const unsigned int Fn, const unsigned int __user *pMem) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci FPA11 *fpa11 = GET_FPA11(); 228c2ecf20Sopenharmony_ci fpa11->fType[Fn] = typeSingle; 238c2ecf20Sopenharmony_ci get_user(fpa11->fpreg[Fn].fSingle, pMem); 248c2ecf20Sopenharmony_ci} 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic inline void loadDouble(const unsigned int Fn, const unsigned int __user *pMem) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci FPA11 *fpa11 = GET_FPA11(); 298c2ecf20Sopenharmony_ci unsigned int *p; 308c2ecf20Sopenharmony_ci p = (unsigned int *) &fpa11->fpreg[Fn].fDouble; 318c2ecf20Sopenharmony_ci fpa11->fType[Fn] = typeDouble; 328c2ecf20Sopenharmony_ci#ifdef __ARMEB__ 338c2ecf20Sopenharmony_ci get_user(p[0], &pMem[0]); /* sign & exponent */ 348c2ecf20Sopenharmony_ci get_user(p[1], &pMem[1]); 358c2ecf20Sopenharmony_ci#else 368c2ecf20Sopenharmony_ci get_user(p[0], &pMem[1]); 378c2ecf20Sopenharmony_ci get_user(p[1], &pMem[0]); /* sign & exponent */ 388c2ecf20Sopenharmony_ci#endif 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#ifdef CONFIG_FPE_NWFPE_XP 428c2ecf20Sopenharmony_cistatic inline void loadExtended(const unsigned int Fn, const unsigned int __user *pMem) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci FPA11 *fpa11 = GET_FPA11(); 458c2ecf20Sopenharmony_ci unsigned int *p; 468c2ecf20Sopenharmony_ci p = (unsigned int *) &fpa11->fpreg[Fn].fExtended; 478c2ecf20Sopenharmony_ci fpa11->fType[Fn] = typeExtended; 488c2ecf20Sopenharmony_ci get_user(p[0], &pMem[0]); /* sign & exponent */ 498c2ecf20Sopenharmony_ci#ifdef __ARMEB__ 508c2ecf20Sopenharmony_ci get_user(p[1], &pMem[1]); /* ms bits */ 518c2ecf20Sopenharmony_ci get_user(p[2], &pMem[2]); /* ls bits */ 528c2ecf20Sopenharmony_ci#else 538c2ecf20Sopenharmony_ci get_user(p[1], &pMem[2]); /* ls bits */ 548c2ecf20Sopenharmony_ci get_user(p[2], &pMem[1]); /* ms bits */ 558c2ecf20Sopenharmony_ci#endif 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci#endif 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic inline void loadMultiple(const unsigned int Fn, const unsigned int __user *pMem) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci FPA11 *fpa11 = GET_FPA11(); 628c2ecf20Sopenharmony_ci register unsigned int *p; 638c2ecf20Sopenharmony_ci unsigned long x; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci p = (unsigned int *) &(fpa11->fpreg[Fn]); 668c2ecf20Sopenharmony_ci get_user(x, &pMem[0]); 678c2ecf20Sopenharmony_ci fpa11->fType[Fn] = (x >> 14) & 0x00000003; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci switch (fpa11->fType[Fn]) { 708c2ecf20Sopenharmony_ci case typeSingle: 718c2ecf20Sopenharmony_ci case typeDouble: 728c2ecf20Sopenharmony_ci { 738c2ecf20Sopenharmony_ci get_user(p[0], &pMem[2]); /* Single */ 748c2ecf20Sopenharmony_ci get_user(p[1], &pMem[1]); /* double msw */ 758c2ecf20Sopenharmony_ci p[2] = 0; /* empty */ 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci break; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci#ifdef CONFIG_FPE_NWFPE_XP 808c2ecf20Sopenharmony_ci case typeExtended: 818c2ecf20Sopenharmony_ci { 828c2ecf20Sopenharmony_ci get_user(p[1], &pMem[2]); 838c2ecf20Sopenharmony_ci get_user(p[2], &pMem[1]); /* msw */ 848c2ecf20Sopenharmony_ci p[0] = (x & 0x80003fff); 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci#endif 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci FPA11 *fpa11 = GET_FPA11(); 948c2ecf20Sopenharmony_ci union { 958c2ecf20Sopenharmony_ci float32 f; 968c2ecf20Sopenharmony_ci unsigned int i[1]; 978c2ecf20Sopenharmony_ci } val; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci switch (fpa11->fType[Fn]) { 1008c2ecf20Sopenharmony_ci case typeDouble: 1018c2ecf20Sopenharmony_ci val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble); 1028c2ecf20Sopenharmony_ci break; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci#ifdef CONFIG_FPE_NWFPE_XP 1058c2ecf20Sopenharmony_ci case typeExtended: 1068c2ecf20Sopenharmony_ci val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended); 1078c2ecf20Sopenharmony_ci break; 1088c2ecf20Sopenharmony_ci#endif 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci default: 1118c2ecf20Sopenharmony_ci val.f = fpa11->fpreg[Fn].fSingle; 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci put_user(val.i[0], pMem); 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci FPA11 *fpa11 = GET_FPA11(); 1208c2ecf20Sopenharmony_ci union { 1218c2ecf20Sopenharmony_ci float64 f; 1228c2ecf20Sopenharmony_ci unsigned int i[2]; 1238c2ecf20Sopenharmony_ci } val; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci switch (fpa11->fType[Fn]) { 1268c2ecf20Sopenharmony_ci case typeSingle: 1278c2ecf20Sopenharmony_ci val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle); 1288c2ecf20Sopenharmony_ci break; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci#ifdef CONFIG_FPE_NWFPE_XP 1318c2ecf20Sopenharmony_ci case typeExtended: 1328c2ecf20Sopenharmony_ci val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended); 1338c2ecf20Sopenharmony_ci break; 1348c2ecf20Sopenharmony_ci#endif 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci default: 1378c2ecf20Sopenharmony_ci val.f = fpa11->fpreg[Fn].fDouble; 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci#ifdef __ARMEB__ 1418c2ecf20Sopenharmony_ci put_user(val.i[0], &pMem[0]); /* msw */ 1428c2ecf20Sopenharmony_ci put_user(val.i[1], &pMem[1]); /* lsw */ 1438c2ecf20Sopenharmony_ci#else 1448c2ecf20Sopenharmony_ci put_user(val.i[1], &pMem[0]); /* msw */ 1458c2ecf20Sopenharmony_ci put_user(val.i[0], &pMem[1]); /* lsw */ 1468c2ecf20Sopenharmony_ci#endif 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci#ifdef CONFIG_FPE_NWFPE_XP 1508c2ecf20Sopenharmony_cistatic inline void storeExtended(const unsigned int Fn, unsigned int __user *pMem) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci FPA11 *fpa11 = GET_FPA11(); 1538c2ecf20Sopenharmony_ci union { 1548c2ecf20Sopenharmony_ci floatx80 f; 1558c2ecf20Sopenharmony_ci unsigned int i[3]; 1568c2ecf20Sopenharmony_ci } val; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci switch (fpa11->fType[Fn]) { 1598c2ecf20Sopenharmony_ci case typeSingle: 1608c2ecf20Sopenharmony_ci val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); 1618c2ecf20Sopenharmony_ci break; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci case typeDouble: 1648c2ecf20Sopenharmony_ci val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); 1658c2ecf20Sopenharmony_ci break; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci default: 1688c2ecf20Sopenharmony_ci val.f = fpa11->fpreg[Fn].fExtended; 1698c2ecf20Sopenharmony_ci } 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci put_user(val.i[0], &pMem[0]); /* sign & exp */ 1728c2ecf20Sopenharmony_ci#ifdef __ARMEB__ 1738c2ecf20Sopenharmony_ci put_user(val.i[1], &pMem[1]); /* msw */ 1748c2ecf20Sopenharmony_ci put_user(val.i[2], &pMem[2]); 1758c2ecf20Sopenharmony_ci#else 1768c2ecf20Sopenharmony_ci put_user(val.i[1], &pMem[2]); 1778c2ecf20Sopenharmony_ci put_user(val.i[2], &pMem[1]); /* msw */ 1788c2ecf20Sopenharmony_ci#endif 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci#endif 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic inline void storeMultiple(const unsigned int Fn, unsigned int __user *pMem) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci FPA11 *fpa11 = GET_FPA11(); 1858c2ecf20Sopenharmony_ci register unsigned int nType, *p; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci p = (unsigned int *) &(fpa11->fpreg[Fn]); 1888c2ecf20Sopenharmony_ci nType = fpa11->fType[Fn]; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci switch (nType) { 1918c2ecf20Sopenharmony_ci case typeSingle: 1928c2ecf20Sopenharmony_ci case typeDouble: 1938c2ecf20Sopenharmony_ci { 1948c2ecf20Sopenharmony_ci put_user(p[0], &pMem[2]); /* single */ 1958c2ecf20Sopenharmony_ci put_user(p[1], &pMem[1]); /* double msw */ 1968c2ecf20Sopenharmony_ci put_user(nType << 14, &pMem[0]); 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci break; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci#ifdef CONFIG_FPE_NWFPE_XP 2018c2ecf20Sopenharmony_ci case typeExtended: 2028c2ecf20Sopenharmony_ci { 2038c2ecf20Sopenharmony_ci put_user(p[2], &pMem[1]); /* msw */ 2048c2ecf20Sopenharmony_ci put_user(p[1], &pMem[2]); 2058c2ecf20Sopenharmony_ci put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]); 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci break; 2088c2ecf20Sopenharmony_ci#endif 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ciunsigned int PerformLDF(const unsigned int opcode) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci unsigned int __user *pBase, *pAddress, *pFinal; 2158c2ecf20Sopenharmony_ci unsigned int nRc = 1, write_back = WRITE_BACK(opcode); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci pBase = (unsigned int __user *) readRegister(getRn(opcode)); 2188c2ecf20Sopenharmony_ci if (REG_PC == getRn(opcode)) { 2198c2ecf20Sopenharmony_ci pBase += 2; 2208c2ecf20Sopenharmony_ci write_back = 0; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci pFinal = pBase; 2248c2ecf20Sopenharmony_ci if (BIT_UP_SET(opcode)) 2258c2ecf20Sopenharmony_ci pFinal += getOffset(opcode); 2268c2ecf20Sopenharmony_ci else 2278c2ecf20Sopenharmony_ci pFinal -= getOffset(opcode); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci if (PREINDEXED(opcode)) 2308c2ecf20Sopenharmony_ci pAddress = pFinal; 2318c2ecf20Sopenharmony_ci else 2328c2ecf20Sopenharmony_ci pAddress = pBase; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci switch (opcode & MASK_TRANSFER_LENGTH) { 2358c2ecf20Sopenharmony_ci case TRANSFER_SINGLE: 2368c2ecf20Sopenharmony_ci loadSingle(getFd(opcode), pAddress); 2378c2ecf20Sopenharmony_ci break; 2388c2ecf20Sopenharmony_ci case TRANSFER_DOUBLE: 2398c2ecf20Sopenharmony_ci loadDouble(getFd(opcode), pAddress); 2408c2ecf20Sopenharmony_ci break; 2418c2ecf20Sopenharmony_ci#ifdef CONFIG_FPE_NWFPE_XP 2428c2ecf20Sopenharmony_ci case TRANSFER_EXTENDED: 2438c2ecf20Sopenharmony_ci loadExtended(getFd(opcode), pAddress); 2448c2ecf20Sopenharmony_ci break; 2458c2ecf20Sopenharmony_ci#endif 2468c2ecf20Sopenharmony_ci default: 2478c2ecf20Sopenharmony_ci nRc = 0; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci if (write_back) 2518c2ecf20Sopenharmony_ci writeRegister(getRn(opcode), (unsigned long) pFinal); 2528c2ecf20Sopenharmony_ci return nRc; 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ciunsigned int PerformSTF(const unsigned int opcode) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci unsigned int __user *pBase, *pAddress, *pFinal; 2588c2ecf20Sopenharmony_ci unsigned int nRc = 1, write_back = WRITE_BACK(opcode); 2598c2ecf20Sopenharmony_ci struct roundingData roundData; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci roundData.mode = SetRoundingMode(opcode); 2628c2ecf20Sopenharmony_ci roundData.precision = SetRoundingPrecision(opcode); 2638c2ecf20Sopenharmony_ci roundData.exception = 0; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci pBase = (unsigned int __user *) readRegister(getRn(opcode)); 2668c2ecf20Sopenharmony_ci if (REG_PC == getRn(opcode)) { 2678c2ecf20Sopenharmony_ci pBase += 2; 2688c2ecf20Sopenharmony_ci write_back = 0; 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci pFinal = pBase; 2728c2ecf20Sopenharmony_ci if (BIT_UP_SET(opcode)) 2738c2ecf20Sopenharmony_ci pFinal += getOffset(opcode); 2748c2ecf20Sopenharmony_ci else 2758c2ecf20Sopenharmony_ci pFinal -= getOffset(opcode); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci if (PREINDEXED(opcode)) 2788c2ecf20Sopenharmony_ci pAddress = pFinal; 2798c2ecf20Sopenharmony_ci else 2808c2ecf20Sopenharmony_ci pAddress = pBase; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci switch (opcode & MASK_TRANSFER_LENGTH) { 2838c2ecf20Sopenharmony_ci case TRANSFER_SINGLE: 2848c2ecf20Sopenharmony_ci storeSingle(&roundData, getFd(opcode), pAddress); 2858c2ecf20Sopenharmony_ci break; 2868c2ecf20Sopenharmony_ci case TRANSFER_DOUBLE: 2878c2ecf20Sopenharmony_ci storeDouble(&roundData, getFd(opcode), pAddress); 2888c2ecf20Sopenharmony_ci break; 2898c2ecf20Sopenharmony_ci#ifdef CONFIG_FPE_NWFPE_XP 2908c2ecf20Sopenharmony_ci case TRANSFER_EXTENDED: 2918c2ecf20Sopenharmony_ci storeExtended(getFd(opcode), pAddress); 2928c2ecf20Sopenharmony_ci break; 2938c2ecf20Sopenharmony_ci#endif 2948c2ecf20Sopenharmony_ci default: 2958c2ecf20Sopenharmony_ci nRc = 0; 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci if (roundData.exception) 2998c2ecf20Sopenharmony_ci float_raise(roundData.exception); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci if (write_back) 3028c2ecf20Sopenharmony_ci writeRegister(getRn(opcode), (unsigned long) pFinal); 3038c2ecf20Sopenharmony_ci return nRc; 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ciunsigned int PerformLFM(const unsigned int opcode) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci unsigned int __user *pBase, *pAddress, *pFinal; 3098c2ecf20Sopenharmony_ci unsigned int i, Fd, write_back = WRITE_BACK(opcode); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci pBase = (unsigned int __user *) readRegister(getRn(opcode)); 3128c2ecf20Sopenharmony_ci if (REG_PC == getRn(opcode)) { 3138c2ecf20Sopenharmony_ci pBase += 2; 3148c2ecf20Sopenharmony_ci write_back = 0; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci pFinal = pBase; 3188c2ecf20Sopenharmony_ci if (BIT_UP_SET(opcode)) 3198c2ecf20Sopenharmony_ci pFinal += getOffset(opcode); 3208c2ecf20Sopenharmony_ci else 3218c2ecf20Sopenharmony_ci pFinal -= getOffset(opcode); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci if (PREINDEXED(opcode)) 3248c2ecf20Sopenharmony_ci pAddress = pFinal; 3258c2ecf20Sopenharmony_ci else 3268c2ecf20Sopenharmony_ci pAddress = pBase; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci Fd = getFd(opcode); 3298c2ecf20Sopenharmony_ci for (i = getRegisterCount(opcode); i > 0; i--) { 3308c2ecf20Sopenharmony_ci loadMultiple(Fd, pAddress); 3318c2ecf20Sopenharmony_ci pAddress += 3; 3328c2ecf20Sopenharmony_ci Fd++; 3338c2ecf20Sopenharmony_ci if (Fd == 8) 3348c2ecf20Sopenharmony_ci Fd = 0; 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci if (write_back) 3388c2ecf20Sopenharmony_ci writeRegister(getRn(opcode), (unsigned long) pFinal); 3398c2ecf20Sopenharmony_ci return 1; 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ciunsigned int PerformSFM(const unsigned int opcode) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci unsigned int __user *pBase, *pAddress, *pFinal; 3458c2ecf20Sopenharmony_ci unsigned int i, Fd, write_back = WRITE_BACK(opcode); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci pBase = (unsigned int __user *) readRegister(getRn(opcode)); 3488c2ecf20Sopenharmony_ci if (REG_PC == getRn(opcode)) { 3498c2ecf20Sopenharmony_ci pBase += 2; 3508c2ecf20Sopenharmony_ci write_back = 0; 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci pFinal = pBase; 3548c2ecf20Sopenharmony_ci if (BIT_UP_SET(opcode)) 3558c2ecf20Sopenharmony_ci pFinal += getOffset(opcode); 3568c2ecf20Sopenharmony_ci else 3578c2ecf20Sopenharmony_ci pFinal -= getOffset(opcode); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci if (PREINDEXED(opcode)) 3608c2ecf20Sopenharmony_ci pAddress = pFinal; 3618c2ecf20Sopenharmony_ci else 3628c2ecf20Sopenharmony_ci pAddress = pBase; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci Fd = getFd(opcode); 3658c2ecf20Sopenharmony_ci for (i = getRegisterCount(opcode); i > 0; i--) { 3668c2ecf20Sopenharmony_ci storeMultiple(Fd, pAddress); 3678c2ecf20Sopenharmony_ci pAddress += 3; 3688c2ecf20Sopenharmony_ci Fd++; 3698c2ecf20Sopenharmony_ci if (Fd == 8) 3708c2ecf20Sopenharmony_ci Fd = 0; 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci if (write_back) 3748c2ecf20Sopenharmony_ci writeRegister(getRn(opcode), (unsigned long) pFinal); 3758c2ecf20Sopenharmony_ci return 1; 3768c2ecf20Sopenharmony_ci} 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ciunsigned int EmulateCPDT(const unsigned int opcode) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci unsigned int nRc = 0; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci if (LDF_OP(opcode)) { 3838c2ecf20Sopenharmony_ci nRc = PerformLDF(opcode); 3848c2ecf20Sopenharmony_ci } else if (LFM_OP(opcode)) { 3858c2ecf20Sopenharmony_ci nRc = PerformLFM(opcode); 3868c2ecf20Sopenharmony_ci } else if (STF_OP(opcode)) { 3878c2ecf20Sopenharmony_ci nRc = PerformSTF(opcode); 3888c2ecf20Sopenharmony_ci } else if (SFM_OP(opcode)) { 3898c2ecf20Sopenharmony_ci nRc = PerformSFM(opcode); 3908c2ecf20Sopenharmony_ci } else { 3918c2ecf20Sopenharmony_ci nRc = 0; 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci return nRc; 3958c2ecf20Sopenharmony_ci} 396