0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "fpa11.h"
0012 #include "softfloat.h"
0013 #include "fpopcode.h"
0014 #include "fpmodule.h"
0015 #include "fpmodule.inl"
0016
0017 #include <linux/uaccess.h>
0018
0019 static inline void loadSingle(const unsigned int Fn, const unsigned int __user *pMem)
0020 {
0021 FPA11 *fpa11 = GET_FPA11();
0022 fpa11->fType[Fn] = typeSingle;
0023 get_user(fpa11->fpreg[Fn].fSingle, pMem);
0024 }
0025
0026 static inline void loadDouble(const unsigned int Fn, const unsigned int __user *pMem)
0027 {
0028 FPA11 *fpa11 = GET_FPA11();
0029 unsigned int *p;
0030 p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;
0031 fpa11->fType[Fn] = typeDouble;
0032 #ifdef __ARMEB__
0033 get_user(p[0], &pMem[0]);
0034 get_user(p[1], &pMem[1]);
0035 #else
0036 get_user(p[0], &pMem[1]);
0037 get_user(p[1], &pMem[0]);
0038 #endif
0039 }
0040
0041 #ifdef CONFIG_FPE_NWFPE_XP
0042 static inline void loadExtended(const unsigned int Fn, const unsigned int __user *pMem)
0043 {
0044 FPA11 *fpa11 = GET_FPA11();
0045 unsigned int *p;
0046 p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;
0047 fpa11->fType[Fn] = typeExtended;
0048 get_user(p[0], &pMem[0]);
0049 #ifdef __ARMEB__
0050 get_user(p[1], &pMem[1]);
0051 get_user(p[2], &pMem[2]);
0052 #else
0053 get_user(p[1], &pMem[2]);
0054 get_user(p[2], &pMem[1]);
0055 #endif
0056 }
0057 #endif
0058
0059 static inline void loadMultiple(const unsigned int Fn, const unsigned int __user *pMem)
0060 {
0061 FPA11 *fpa11 = GET_FPA11();
0062 register unsigned int *p;
0063 unsigned long x;
0064
0065 p = (unsigned int *) &(fpa11->fpreg[Fn]);
0066 get_user(x, &pMem[0]);
0067 fpa11->fType[Fn] = (x >> 14) & 0x00000003;
0068
0069 switch (fpa11->fType[Fn]) {
0070 case typeSingle:
0071 case typeDouble:
0072 {
0073 get_user(p[0], &pMem[2]);
0074 get_user(p[1], &pMem[1]);
0075 p[2] = 0;
0076 }
0077 break;
0078
0079 #ifdef CONFIG_FPE_NWFPE_XP
0080 case typeExtended:
0081 {
0082 get_user(p[1], &pMem[2]);
0083 get_user(p[2], &pMem[1]);
0084 p[0] = (x & 0x80003fff);
0085 }
0086 break;
0087 #endif
0088 }
0089 }
0090
0091 static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
0092 {
0093 FPA11 *fpa11 = GET_FPA11();
0094 union {
0095 float32 f;
0096 unsigned int i[1];
0097 } val;
0098
0099 switch (fpa11->fType[Fn]) {
0100 case typeDouble:
0101 val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble);
0102 break;
0103
0104 #ifdef CONFIG_FPE_NWFPE_XP
0105 case typeExtended:
0106 val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended);
0107 break;
0108 #endif
0109
0110 default:
0111 val.f = fpa11->fpreg[Fn].fSingle;
0112 }
0113
0114 put_user(val.i[0], pMem);
0115 }
0116
0117 static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
0118 {
0119 FPA11 *fpa11 = GET_FPA11();
0120 union {
0121 float64 f;
0122 unsigned int i[2];
0123 } val;
0124
0125 switch (fpa11->fType[Fn]) {
0126 case typeSingle:
0127 val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle);
0128 break;
0129
0130 #ifdef CONFIG_FPE_NWFPE_XP
0131 case typeExtended:
0132 val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended);
0133 break;
0134 #endif
0135
0136 default:
0137 val.f = fpa11->fpreg[Fn].fDouble;
0138 }
0139
0140 #ifdef __ARMEB__
0141 put_user(val.i[0], &pMem[0]);
0142 put_user(val.i[1], &pMem[1]);
0143 #else
0144 put_user(val.i[1], &pMem[0]);
0145 put_user(val.i[0], &pMem[1]);
0146 #endif
0147 }
0148
0149 #ifdef CONFIG_FPE_NWFPE_XP
0150 static inline void storeExtended(const unsigned int Fn, unsigned int __user *pMem)
0151 {
0152 FPA11 *fpa11 = GET_FPA11();
0153 union {
0154 floatx80 f;
0155 unsigned int i[3];
0156 } val;
0157
0158 switch (fpa11->fType[Fn]) {
0159 case typeSingle:
0160 val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
0161 break;
0162
0163 case typeDouble:
0164 val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
0165 break;
0166
0167 default:
0168 val.f = fpa11->fpreg[Fn].fExtended;
0169 }
0170
0171 put_user(val.i[0], &pMem[0]);
0172 #ifdef __ARMEB__
0173 put_user(val.i[1], &pMem[1]);
0174 put_user(val.i[2], &pMem[2]);
0175 #else
0176 put_user(val.i[1], &pMem[2]);
0177 put_user(val.i[2], &pMem[1]);
0178 #endif
0179 }
0180 #endif
0181
0182 static inline void storeMultiple(const unsigned int Fn, unsigned int __user *pMem)
0183 {
0184 FPA11 *fpa11 = GET_FPA11();
0185 register unsigned int nType, *p;
0186
0187 p = (unsigned int *) &(fpa11->fpreg[Fn]);
0188 nType = fpa11->fType[Fn];
0189
0190 switch (nType) {
0191 case typeSingle:
0192 case typeDouble:
0193 {
0194 put_user(p[0], &pMem[2]);
0195 put_user(p[1], &pMem[1]);
0196 put_user(nType << 14, &pMem[0]);
0197 }
0198 break;
0199
0200 #ifdef CONFIG_FPE_NWFPE_XP
0201 case typeExtended:
0202 {
0203 put_user(p[2], &pMem[1]);
0204 put_user(p[1], &pMem[2]);
0205 put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]);
0206 }
0207 break;
0208 #endif
0209 }
0210 }
0211
0212 unsigned int PerformLDF(const unsigned int opcode)
0213 {
0214 unsigned int __user *pBase, *pAddress, *pFinal;
0215 unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
0216
0217 pBase = (unsigned int __user *) readRegister(getRn(opcode));
0218 if (REG_PC == getRn(opcode)) {
0219 pBase += 2;
0220 write_back = 0;
0221 }
0222
0223 pFinal = pBase;
0224 if (BIT_UP_SET(opcode))
0225 pFinal += getOffset(opcode);
0226 else
0227 pFinal -= getOffset(opcode);
0228
0229 if (PREINDEXED(opcode))
0230 pAddress = pFinal;
0231 else
0232 pAddress = pBase;
0233
0234 switch (opcode & MASK_TRANSFER_LENGTH) {
0235 case TRANSFER_SINGLE:
0236 loadSingle(getFd(opcode), pAddress);
0237 break;
0238 case TRANSFER_DOUBLE:
0239 loadDouble(getFd(opcode), pAddress);
0240 break;
0241 #ifdef CONFIG_FPE_NWFPE_XP
0242 case TRANSFER_EXTENDED:
0243 loadExtended(getFd(opcode), pAddress);
0244 break;
0245 #endif
0246 default:
0247 nRc = 0;
0248 }
0249
0250 if (write_back)
0251 writeRegister(getRn(opcode), (unsigned long) pFinal);
0252 return nRc;
0253 }
0254
0255 unsigned int PerformSTF(const unsigned int opcode)
0256 {
0257 unsigned int __user *pBase, *pAddress, *pFinal;
0258 unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
0259 struct roundingData roundData;
0260
0261 roundData.mode = SetRoundingMode(opcode);
0262 roundData.precision = SetRoundingPrecision(opcode);
0263 roundData.exception = 0;
0264
0265 pBase = (unsigned int __user *) readRegister(getRn(opcode));
0266 if (REG_PC == getRn(opcode)) {
0267 pBase += 2;
0268 write_back = 0;
0269 }
0270
0271 pFinal = pBase;
0272 if (BIT_UP_SET(opcode))
0273 pFinal += getOffset(opcode);
0274 else
0275 pFinal -= getOffset(opcode);
0276
0277 if (PREINDEXED(opcode))
0278 pAddress = pFinal;
0279 else
0280 pAddress = pBase;
0281
0282 switch (opcode & MASK_TRANSFER_LENGTH) {
0283 case TRANSFER_SINGLE:
0284 storeSingle(&roundData, getFd(opcode), pAddress);
0285 break;
0286 case TRANSFER_DOUBLE:
0287 storeDouble(&roundData, getFd(opcode), pAddress);
0288 break;
0289 #ifdef CONFIG_FPE_NWFPE_XP
0290 case TRANSFER_EXTENDED:
0291 storeExtended(getFd(opcode), pAddress);
0292 break;
0293 #endif
0294 default:
0295 nRc = 0;
0296 }
0297
0298 if (roundData.exception)
0299 float_raise(roundData.exception);
0300
0301 if (write_back)
0302 writeRegister(getRn(opcode), (unsigned long) pFinal);
0303 return nRc;
0304 }
0305
0306 unsigned int PerformLFM(const unsigned int opcode)
0307 {
0308 unsigned int __user *pBase, *pAddress, *pFinal;
0309 unsigned int i, Fd, write_back = WRITE_BACK(opcode);
0310
0311 pBase = (unsigned int __user *) readRegister(getRn(opcode));
0312 if (REG_PC == getRn(opcode)) {
0313 pBase += 2;
0314 write_back = 0;
0315 }
0316
0317 pFinal = pBase;
0318 if (BIT_UP_SET(opcode))
0319 pFinal += getOffset(opcode);
0320 else
0321 pFinal -= getOffset(opcode);
0322
0323 if (PREINDEXED(opcode))
0324 pAddress = pFinal;
0325 else
0326 pAddress = pBase;
0327
0328 Fd = getFd(opcode);
0329 for (i = getRegisterCount(opcode); i > 0; i--) {
0330 loadMultiple(Fd, pAddress);
0331 pAddress += 3;
0332 Fd++;
0333 if (Fd == 8)
0334 Fd = 0;
0335 }
0336
0337 if (write_back)
0338 writeRegister(getRn(opcode), (unsigned long) pFinal);
0339 return 1;
0340 }
0341
0342 unsigned int PerformSFM(const unsigned int opcode)
0343 {
0344 unsigned int __user *pBase, *pAddress, *pFinal;
0345 unsigned int i, Fd, write_back = WRITE_BACK(opcode);
0346
0347 pBase = (unsigned int __user *) readRegister(getRn(opcode));
0348 if (REG_PC == getRn(opcode)) {
0349 pBase += 2;
0350 write_back = 0;
0351 }
0352
0353 pFinal = pBase;
0354 if (BIT_UP_SET(opcode))
0355 pFinal += getOffset(opcode);
0356 else
0357 pFinal -= getOffset(opcode);
0358
0359 if (PREINDEXED(opcode))
0360 pAddress = pFinal;
0361 else
0362 pAddress = pBase;
0363
0364 Fd = getFd(opcode);
0365 for (i = getRegisterCount(opcode); i > 0; i--) {
0366 storeMultiple(Fd, pAddress);
0367 pAddress += 3;
0368 Fd++;
0369 if (Fd == 8)
0370 Fd = 0;
0371 }
0372
0373 if (write_back)
0374 writeRegister(getRn(opcode), (unsigned long) pFinal);
0375 return 1;
0376 }
0377
0378 unsigned int EmulateCPDT(const unsigned int opcode)
0379 {
0380 unsigned int nRc = 0;
0381
0382 if (LDF_OP(opcode)) {
0383 nRc = PerformLDF(opcode);
0384 } else if (LFM_OP(opcode)) {
0385 nRc = PerformLFM(opcode);
0386 } else if (STF_OP(opcode)) {
0387 nRc = PerformSTF(opcode);
0388 } else if (SFM_OP(opcode)) {
0389 nRc = PerformSFM(opcode);
0390 } else {
0391 nRc = 0;
0392 }
0393
0394 return nRc;
0395 }