Release 4.11 arch/arm/nwfpe/fpa11_cpdt.c
/*
NetWinder Floating Point Emulator
(c) Rebel.com, 1998-1999
(c) Philip Blundell, 1998, 2001
Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "fpa11.h"
#include "softfloat.h"
#include "fpopcode.h"
#include "fpmodule.h"
#include "fpmodule.inl"
#include <linux/uaccess.h>
static inline void loadSingle(const unsigned int Fn, const unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
fpa11->fType[Fn] = typeSingle;
get_user(fpa11->fpreg[Fn].fSingle, pMem);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 39 | 79.59% | 2 | 50.00% |
Linus Torvalds | 9 | 18.37% | 1 | 25.00% |
Russell King | 1 | 2.04% | 1 | 25.00% |
Total | 49 | 100.00% | 4 | 100.00% |
static inline void loadDouble(const unsigned int Fn, const unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
unsigned int *p;
p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;
fpa11->fType[Fn] = typeDouble;
#ifdef __ARMEB__
get_user(p[0], &pMem[0]); /* sign & exponent */
get_user(p[1], &pMem[1]);
#else
get_user(p[0], &pMem[1]);
get_user(p[1], &pMem[0]); /* sign & exponent */
#endif
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 76 | 62.30% | 2 | 40.00% |
Lennert Buytenhek | 36 | 29.51% | 1 | 20.00% |
Linus Torvalds | 9 | 7.38% | 1 | 20.00% |
Russell King | 1 | 0.82% | 1 | 20.00% |
Total | 122 | 100.00% | 5 | 100.00% |
#ifdef CONFIG_FPE_NWFPE_XP
static inline void loadExtended(const unsigned int Fn, const unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
unsigned int *p;
p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;
fpa11->fType[Fn] = typeExtended;
get_user(p[0], &pMem[0]); /* sign & exponent */
#ifdef __ARMEB__
get_user(p[1], &pMem[1]); /* ms bits */
get_user(p[2], &pMem[2]); /* ls bits */
#else
get_user(p[1], &pMem[2]); /* ls bits */
get_user(p[2], &pMem[1]); /* ms bits */
#endif
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 92 | 66.19% | 2 | 40.00% |
Lennert Buytenhek | 37 | 26.62% | 1 | 20.00% |
Linus Torvalds | 9 | 6.47% | 1 | 20.00% |
Russell King | 1 | 0.72% | 1 | 20.00% |
Total | 139 | 100.00% | 5 | 100.00% |
#endif
static inline void loadMultiple(const unsigned int Fn, const unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
register unsigned int *p;
unsigned long x;
p = (unsigned int *) &(fpa11->fpreg[Fn]);
get_user(x, &pMem[0]);
fpa11->fType[Fn] = (x >> 14) & 0x00000003;
switch (fpa11->fType[Fn]) {
case typeSingle:
case typeDouble:
{
get_user(p[0], &pMem[2]); /* Single */
get_user(p[1], &pMem[1]); /* double msw */
p[2] = 0; /* empty */
}
break;
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
{
get_user(p[1], &pMem[2]);
get_user(p[2], &pMem[1]); /* msw */
p[0] = (x & 0x80003fff);
}
break;
#endif
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 173 | 92.02% | 2 | 40.00% |
Linus Torvalds | 9 | 4.79% | 1 | 20.00% |
Ralph Siemsen | 5 | 2.66% | 1 | 20.00% |
Russell King | 1 | 0.53% | 1 | 20.00% |
Total | 188 | 100.00% | 5 | 100.00% |
static inline void storeSingle(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
union {
float32 f;
unsigned int i[1];
} val;
switch (fpa11->fType[Fn]) {
case typeDouble:
val.f = float64_to_float32(roundData, fpa11->fpreg[Fn].fDouble);
break;
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
val.f = floatx80_to_float32(roundData, fpa11->fpreg[Fn].fExtended);
break;
#endif
default:
val.f = fpa11->fpreg[Fn].fSingle;
}
put_user(val.i[0], pMem);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 88 | 67.18% | 2 | 28.57% |
Linus Torvalds | 28 | 21.37% | 2 | 28.57% |
Richard Purdie | 9 | 6.87% | 1 | 14.29% |
Ralph Siemsen | 5 | 3.82% | 1 | 14.29% |
Russell King | 1 | 0.76% | 1 | 14.29% |
Total | 131 | 100.00% | 7 | 100.00% |
static inline void storeDouble(struct roundingData *roundData, const unsigned int Fn, unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
union {
float64 f;
unsigned int i[2];
} val;
switch (fpa11->fType[Fn]) {
case typeSingle:
val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle);
break;
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
val.f = floatx80_to_float64(roundData, fpa11->fpreg[Fn].fExtended);
break;
#endif
default:
val.f = fpa11->fpreg[Fn].fDouble;
}
#ifdef __ARMEB__
put_user(val.i[0], &pMem[0]); /* msw */
put_user(val.i[1], &pMem[1]); /* lsw */
#else
put_user(val.i[1], &pMem[0]); /* msw */
put_user(val.i[0], &pMem[1]); /* lsw */
#endif
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 107 | 55.73% | 2 | 25.00% |
Lennert Buytenhek | 41 | 21.35% | 1 | 12.50% |
Linus Torvalds | 31 | 16.15% | 2 | 25.00% |
Richard Purdie | 7 | 3.65% | 1 | 12.50% |
Ralph Siemsen | 5 | 2.60% | 1 | 12.50% |
Russell King | 1 | 0.52% | 1 | 12.50% |
Total | 192 | 100.00% | 8 | 100.00% |
#ifdef CONFIG_FPE_NWFPE_XP
static inline void storeExtended(const unsigned int Fn, unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
union {
floatx80 f;
unsigned int i[3];
} val;
switch (fpa11->fType[Fn]) {
case typeSingle:
val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
break;
case typeDouble:
val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
break;
default:
val.f = fpa11->fpreg[Fn].fExtended;
}
put_user(val.i[0], &pMem[0]); /* sign & exp */
#ifdef __ARMEB__
put_user(val.i[1], &pMem[1]); /* msw */
put_user(val.i[2], &pMem[2]);
#else
put_user(val.i[1], &pMem[2]);
put_user(val.i[2], &pMem[1]); /* msw */
#endif
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 120 | 61.54% | 2 | 33.33% |
Lennert Buytenhek | 40 | 20.51% | 1 | 16.67% |
Linus Torvalds | 34 | 17.44% | 2 | 33.33% |
Russell King | 1 | 0.51% | 1 | 16.67% |
Total | 195 | 100.00% | 6 | 100.00% |
#endif
static inline void storeMultiple(const unsigned int Fn, unsigned int __user *pMem)
{
FPA11 *fpa11 = GET_FPA11();
register unsigned int nType, *p;
p = (unsigned int *) &(fpa11->fpreg[Fn]);
nType = fpa11->fType[Fn];
switch (nType) {
case typeSingle:
case typeDouble:
{
put_user(p[0], &pMem[2]); /* single */
put_user(p[1], &pMem[1]); /* double msw */
put_user(nType << 14, &pMem[0]);
}
break;
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
{
put_user(p[2], &pMem[1]); /* msw */
put_user(p[1], &pMem[2]);
put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]);
}
break;
#endif
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 166 | 91.71% | 2 | 40.00% |
Linus Torvalds | 9 | 4.97% | 1 | 20.00% |
Ralph Siemsen | 5 | 2.76% | 1 | 20.00% |
Russell King | 1 | 0.55% | 1 | 20.00% |
Total | 181 | 100.00% | 5 | 100.00% |
unsigned int PerformLDF(const unsigned int opcode)
{
unsigned int __user *pBase, *pAddress, *pFinal;
unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
pBase = (unsigned int __user *) readRegister(getRn(opcode));
if (REG_PC == getRn(opcode)) {
pBase += 2;
write_back = 0;
}
pFinal = pBase;
if (BIT_UP_SET(opcode))
pFinal += getOffset(opcode);
else
pFinal -= getOffset(opcode);
if (PREINDEXED(opcode))
pAddress = pFinal;
else
pAddress = pBase;
switch (opcode & MASK_TRANSFER_LENGTH) {
case TRANSFER_SINGLE:
loadSingle(getFd(opcode), pAddress);
break;
case TRANSFER_DOUBLE:
loadDouble(getFd(opcode), pAddress);
break;
#ifdef CONFIG_FPE_NWFPE_XP
case TRANSFER_EXTENDED:
loadExtended(getFd(opcode), pAddress);
break;
#endif
default:
nRc = 0;
}
if (write_back)
writeRegister(getRn(opcode), (unsigned long) pFinal);
return nRc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 183 | 94.33% | 2 | 50.00% |
Russell King | 6 | 3.09% | 1 | 25.00% |
Ralph Siemsen | 5 | 2.58% | 1 | 25.00% |
Total | 194 | 100.00% | 4 | 100.00% |
unsigned int PerformSTF(const unsigned int opcode)
{
unsigned int __user *pBase, *pAddress, *pFinal;
unsigned int nRc = 1, write_back = WRITE_BACK(opcode);
struct roundingData roundData;
roundData.mode = SetRoundingMode(opcode);
roundData.precision = SetRoundingPrecision(opcode);
roundData.exception = 0;
pBase = (unsigned int __user *) readRegister(getRn(opcode));
if (REG_PC == getRn(opcode)) {
pBase += 2;
write_back = 0;
}
pFinal = pBase;
if (BIT_UP_SET(opcode))
pFinal += getOffset(opcode);
else
pFinal -= getOffset(opcode);
if (PREINDEXED(opcode))
pAddress = pFinal;
else
pAddress = pBase;
switch (opcode & MASK_TRANSFER_LENGTH) {
case TRANSFER_SINGLE:
storeSingle(&roundData, getFd(opcode), pAddress);
break;
case TRANSFER_DOUBLE:
storeDouble(&roundData, getFd(opcode), pAddress);
break;
#ifdef CONFIG_FPE_NWFPE_XP
case TRANSFER_EXTENDED:
storeExtended(getFd(opcode), pAddress);
break;
#endif
default:
nRc = 0;
}
if (roundData.exception)
float_raise(roundData.exception);
if (write_back)
writeRegister(getRn(opcode), (unsigned long) pFinal);
return nRc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 187 | 77.59% | 2 | 40.00% |
Richard Purdie | 43 | 17.84% | 1 | 20.00% |
Russell King | 6 | 2.49% | 1 | 20.00% |
Ralph Siemsen | 5 | 2.07% | 1 | 20.00% |
Total | 241 | 100.00% | 5 | 100.00% |
unsigned int PerformLFM(const unsigned int opcode)
{
unsigned int __user *pBase, *pAddress, *pFinal;
unsigned int i, Fd, write_back = WRITE_BACK(opcode);
pBase = (unsigned int __user *) readRegister(getRn(opcode));
if (REG_PC == getRn(opcode)) {
pBase += 2;
write_back = 0;
}
pFinal = pBase;
if (BIT_UP_SET(opcode))
pFinal += getOffset(opcode);
else
pFinal -= getOffset(opcode);
if (PREINDEXED(opcode))
pAddress = pFinal;
else
pAddress = pBase;
Fd = getFd(opcode);
for (i = getRegisterCount(opcode); i > 0; i--) {
loadMultiple(Fd, pAddress);
pAddress += 3;
Fd++;
if (Fd == 8)
Fd = 0;
}
if (write_back)
writeRegister(getRn(opcode), (unsigned long) pFinal);
return 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 174 | 95.08% | 2 | 66.67% |
Russell King | 9 | 4.92% | 1 | 33.33% |
Total | 183 | 100.00% | 3 | 100.00% |
unsigned int PerformSFM(const unsigned int opcode)
{
unsigned int __user *pBase, *pAddress, *pFinal;
unsigned int i, Fd, write_back = WRITE_BACK(opcode);
pBase = (unsigned int __user *) readRegister(getRn(opcode));
if (REG_PC == getRn(opcode)) {
pBase += 2;
write_back = 0;
}
pFinal = pBase;
if (BIT_UP_SET(opcode))
pFinal += getOffset(opcode);
else
pFinal -= getOffset(opcode);
if (PREINDEXED(opcode))
pAddress = pFinal;
else
pAddress = pBase;
Fd = getFd(opcode);
for (i = getRegisterCount(opcode); i > 0; i--) {
storeMultiple(Fd, pAddress);
pAddress += 3;
Fd++;
if (Fd == 8)
Fd = 0;
}
if (write_back)
writeRegister(getRn(opcode), (unsigned long) pFinal);
return 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 174 | 95.08% | 2 | 66.67% |
Russell King | 9 | 4.92% | 1 | 33.33% |
Total | 183 | 100.00% | 3 | 100.00% |
unsigned int EmulateCPDT(const unsigned int opcode)
{
unsigned int nRc = 0;
if (LDF_OP(opcode)) {
nRc = PerformLDF(opcode);
} else if (LFM_OP(opcode)) {
nRc = PerformLFM(opcode);
} else if (STF_OP(opcode)) {
nRc = PerformSTF(opcode);
} else if (SFM_OP(opcode)) {
nRc = PerformSFM(opcode);
} else {
nRc = 0;
}
return nRc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 94 | 100.00% | 1 | 100.00% |
Total | 94 | 100.00% | 1 | 100.00% |
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 1686 | 79.49% | 2 | 16.67% |
Lennert Buytenhek | 154 | 7.26% | 2 | 16.67% |
Linus Torvalds | 138 | 6.51% | 2 | 16.67% |
Richard Purdie | 59 | 2.78% | 1 | 8.33% |
Russell King | 43 | 2.03% | 4 | 33.33% |
Ralph Siemsen | 41 | 1.93% | 1 | 8.33% |
Total | 2121 | 100.00% | 12 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.