Commit 95a3352a authored by Ralph Siemsen's avatar Ralph Siemsen Committed by Russell King

[NWFPE] Performance improvements [Part 1]

This is the first of a series of patches to NWFPE, which aim to bring
the performance improvements from the netwinder.org CVS tree into the
mainline ARM kernel.

This patch is merely a reformatting of the NWFPE sources.  All files
were processed with "indent -kr -i8 -ts8 -sob -l132 -ss" and a few
manual fixups. Exception: the softfloat files have not been touched.

This patch should be applied after the 5 patches previously published
by RMK on linux-arm-kernel have been applied.
parent 92c6da54
2003-03-22 Ralph Siemsen <ralphs@netwinder.org>
* Reformat all but softfloat files to get a consistent coding style.
Used "indent -kr -i8 -ts8 -sob -l132 -ss" and a few manual fixups.
2002-01-19 Russell King <rmk@arm.linux.org.uk>
* fpa11.h - Add documentation
......
......@@ -23,8 +23,7 @@
#include "softfloat.h"
#include "fpopcode.h"
union float64_components
{
union float64_components {
float64 f64;
unsigned int i[2];
};
......@@ -38,8 +37,8 @@ float64 float64_arctan(float64 rFm);
float64 float64_log(float64 rFm);
float64 float64_tan(float64 rFm);
float64 float64_arccos(float64 rFm);
float64 float64_pow(float64 rFn,float64 rFm);
float64 float64_pol(float64 rFn,float64 rFm);
float64 float64_pow(float64 rFn, float64 rFm);
float64 float64_pol(float64 rFn, float64 rFm);
static float64 float64_rsf(float64 rFn, float64 rFm)
{
......@@ -51,8 +50,7 @@ static float64 float64_rdv(float64 rFn, float64 rFm)
return float64_div(rFm, rFn);
}
static float64 (* const dyadic_double[16])(float64 rFn, float64 rFm) =
{
static float64 (*const dyadic_double[16])(float64 rFn, float64 rFm) = {
[ADF_CODE >> 20] = float64_add,
[MUF_CODE >> 20] = float64_mul,
[SUF_CODE >> 20] = float64_sub,
......@@ -92,8 +90,7 @@ static float64 float64_abs(float64 rFm)
return u.f64;
}
static float64 (* const monadic_double[16])(float64 rFm) =
{
static float64 (*const monadic_double[16])(float64 rFm) = {
[MVF_CODE >> 20] = float64_mvf,
[MNF_CODE >> 20] = float64_mnf,
[ABS_CODE >> 20] = float64_abs,
......@@ -103,7 +100,7 @@ static float64 (* const monadic_double[16])(float64 rFm) =
[NRM_CODE >> 20] = float64_mvf,
};
unsigned int DoubleCPDO(const unsigned int opcode, FPREG *rFd)
unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd)
{
FPA11 *fpa11 = GET_FPA11();
float64 rFm;
......@@ -112,14 +109,10 @@ unsigned int DoubleCPDO(const unsigned int opcode, FPREG *rFd)
//printk("DoubleCPDO(0x%08x)\n",opcode);
Fm = getFm(opcode);
if (CONSTANT_FM(opcode))
{
if (CONSTANT_FM(opcode)) {
rFm = getDoubleConstant(Fm);
}
else
{
switch (fpa11->fType[Fm])
{
} else {
switch (fpa11->fType[Fm]) {
case typeSingle:
rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle);
break;
......@@ -128,18 +121,17 @@ unsigned int DoubleCPDO(const unsigned int opcode, FPREG *rFd)
rFm = fpa11->fpreg[Fm].fDouble;
break;
default: return 0;
default:
return 0;
}
}
opc = opcode & MASK_ARITHMETIC_OPCODE;
if (!MONADIC_INSTRUCTION(opcode))
{
if (!MONADIC_INSTRUCTION(opcode)) {
unsigned int Fn = getFn(opcode);
float64 rFn;
switch (fpa11->fType[Fn])
{
switch (fpa11->fType[Fn]) {
case typeSingle:
rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle);
break;
......@@ -148,26 +140,19 @@ unsigned int DoubleCPDO(const unsigned int opcode, FPREG *rFd)
rFn = fpa11->fpreg[Fn].fDouble;
break;
default: return 0;
default:
return 0;
}
if (dyadic_double[opc >> 20])
{
if (dyadic_double[opc >> 20]) {
rFd->fDouble = dyadic_double[opc >> 20](rFn, rFm);
}
else
{
} else {
return 0;
}
}
else
{
if (monadic_double[opc >> 20])
{
} else {
if (monadic_double[opc >> 20]) {
rFd->fDouble = monadic_double[opc >> 20](rFm);
}
else
{
} else {
return 0;
}
}
......
......@@ -32,8 +32,8 @@ floatx80 floatx80_arctan(floatx80 rFm);
floatx80 floatx80_log(floatx80 rFm);
floatx80 floatx80_tan(floatx80 rFm);
floatx80 floatx80_arccos(floatx80 rFm);
floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm);
floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm);
floatx80 floatx80_pow(floatx80 rFn, floatx80 rFm);
floatx80 floatx80_pol(floatx80 rFn, floatx80 rFm);
static floatx80 floatx80_rsf(floatx80 rFn, floatx80 rFm)
{
......@@ -45,8 +45,7 @@ static floatx80 floatx80_rdv(floatx80 rFn, floatx80 rFm)
return floatx80_div(rFm, rFn);
}
static floatx80 (* const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) =
{
static floatx80 (*const dyadic_extended[16])(floatx80 rFn, floatx80 rFm) = {
[ADF_CODE >> 20] = floatx80_add,
[MUF_CODE >> 20] = floatx80_mul,
[SUF_CODE >> 20] = floatx80_sub,
......@@ -78,8 +77,7 @@ static floatx80 floatx80_abs(floatx80 rFm)
return rFm;
}
static floatx80 (* const monadic_extended[16])(floatx80 rFm) =
{
static floatx80 (*const monadic_extended[16])(floatx80 rFm) = {
[MVF_CODE >> 20] = floatx80_mvf,
[MNF_CODE >> 20] = floatx80_mnf,
[ABS_CODE >> 20] = floatx80_abs,
......@@ -89,7 +87,7 @@ static floatx80 (* const monadic_extended[16])(floatx80 rFm) =
[NRM_CODE >> 20] = floatx80_mvf,
};
unsigned int ExtendedCPDO(const unsigned int opcode, FPREG *rFd)
unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd)
{
FPA11 *fpa11 = GET_FPA11();
floatx80 rFm;
......@@ -98,14 +96,10 @@ unsigned int ExtendedCPDO(const unsigned int opcode, FPREG *rFd)
//printk("ExtendedCPDO(0x%08x)\n",opcode);
Fm = getFm(opcode);
if (CONSTANT_FM(opcode))
{
if (CONSTANT_FM(opcode)) {
rFm = getExtendedConstant(Fm);
}
else
{
switch (fpa11->fType[Fm])
{
} else {
switch (fpa11->fType[Fm]) {
case typeSingle:
rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle);
break;
......@@ -118,18 +112,17 @@ unsigned int ExtendedCPDO(const unsigned int opcode, FPREG *rFd)
rFm = fpa11->fpreg[Fm].fExtended;
break;
default: return 0;
default:
return 0;
}
}
opc = opcode & MASK_ARITHMETIC_OPCODE;
if (!MONADIC_INSTRUCTION(opcode))
{
if (!MONADIC_INSTRUCTION(opcode)) {
unsigned int Fn = getFn(opcode);
floatx80 rFn;
switch (fpa11->fType[Fn])
{
switch (fpa11->fType[Fn]) {
case typeSingle:
rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
break;
......@@ -142,26 +135,19 @@ unsigned int ExtendedCPDO(const unsigned int opcode, FPREG *rFd)
rFn = fpa11->fpreg[Fn].fExtended;
break;
default: return 0;
default:
return 0;
}
if (dyadic_extended[opc >> 20])
{
if (dyadic_extended[opc >> 20]) {
rFd->fExtended = dyadic_extended[opc >> 20](rFn, rFm);
}
else
{
} else {
return 0;
}
}
else
{
if (monadic_extended[opc >> 20])
{
} else {
if (monadic_extended[opc >> 20]) {
rFd->fExtended = monadic_extended[opc >> 20](rFm);
}
else
{
} else {
return 0;
}
}
......
......@@ -41,8 +41,7 @@ static void resetFPA11(void)
FPA11 *fpa11 = GET_FPA11();
/* initialize the register type array */
for (i=0;i<=7;i++)
{
for (i = 0; i <= 7; i++) {
fpa11->fType[i] = typeNone;
}
......@@ -61,8 +60,7 @@ void SetRoundingMode(const unsigned int opcode)
FPA11 *fpa11 = GET_FPA11();
fpa11->fpcr &= ~MASK_ROUNDING_MODE;
#endif
switch (opcode & MASK_ROUNDING_MODE)
{
switch (opcode & MASK_ROUNDING_MODE) {
default:
case ROUND_TO_NEAREST:
float_rounding_mode = float_round_nearest_even;
......@@ -100,8 +98,7 @@ void SetRoundingPrecision(const unsigned int opcode)
FPA11 *fpa11 = GET_FPA11();
fpa11->fpcr &= ~MASK_ROUNDING_PRECISION;
#endif
switch (opcode & MASK_ROUNDING_PRECISION)
{
switch (opcode & MASK_ROUNDING_PRECISION) {
case ROUND_SINGLE:
floatx80_rounding_precision = 32;
#if MAINTAIN_FPCR
......@@ -123,7 +120,8 @@ void SetRoundingPrecision(const unsigned int opcode)
#endif
break;
default: floatx80_rounding_precision = 80;
default:
floatx80_rounding_precision = 80;
}
}
......@@ -143,65 +141,60 @@ unsigned int EmulateAll(unsigned int opcode)
unsigned int nRc = 1, code;
code = opcode & 0x00000f00;
if (code == 0x00000100 || code == 0x00000200)
{
if (code == 0x00000100 || code == 0x00000200) {
/* For coprocessor 1 or 2 (FPA11) */
code = opcode & 0x0e000000;
if (code == 0x0e000000)
{
if (opcode & 0x00000010)
{
if (code == 0x0e000000) {
if (opcode & 0x00000010) {
/* Emulate conversion opcodes. */
/* Emulate register transfer opcodes. */
/* Emulate comparison opcodes. */
nRc = EmulateCPRT(opcode);
}
else
{
} else {
/* Emulate monadic arithmetic opcodes. */
/* Emulate dyadic arithmetic opcodes. */
nRc = EmulateCPDO(opcode);
}
}
else if (code == 0x0c000000)
{
} else if (code == 0x0c000000) {
/* Emulate load/store opcodes. */
/* Emulate load/store multiple opcodes. */
nRc = EmulateCPDT(opcode);
}
else
{
} else {
/* Invalid instruction detected. Return FALSE. */
nRc = 0;
}
}
return(nRc);
return (nRc);
}
#if 0
unsigned int EmulateAll1(unsigned int opcode)
{
switch ((opcode >> 24) & 0xf)
{
switch ((opcode >> 24) & 0xf) {
case 0xc:
case 0xd:
if ((opcode >> 20) & 0x1)
{
switch ((opcode >> 8) & 0xf)
{
case 0x1: return PerformLDF(opcode); break;
case 0x2: return PerformLFM(opcode); break;
default: return 0;
}
if ((opcode >> 20) & 0x1) {
switch ((opcode >> 8) & 0xf) {
case 0x1:
return PerformLDF(opcode);
break;
case 0x2:
return PerformLFM(opcode);
break;
default:
return 0;
}
else
{
switch ((opcode >> 8) & 0xf)
{
case 0x1: return PerformSTF(opcode); break;
case 0x2: return PerformSFM(opcode); break;
default: return 0;
} else {
switch ((opcode >> 8) & 0xf) {
case 0x1:
return PerformSTF(opcode);
break;
case 0x2:
return PerformSFM(opcode);
break;
default:
return 0;
}
}
break;
......@@ -213,8 +206,8 @@ unsigned int EmulateAll1(unsigned int opcode)
return EmulateCPRT(opcode);
break;
default: return 0;
default:
return 0;
}
}
#endif
......@@ -71,8 +71,8 @@ typedef struct tagFPA11 {
/* 96 */ FPSR fpsr; /* floating point status register */
/* 100 */ FPCR fpcr; /* floating point control register */
/* 104 */ unsigned char fType[8]; /* type of floating point value held in
floating point registers. One of none
single, double or extended. */
floating point registers. One of
none, single, double or extended. */
/* 112 */ int initflag; /* this is special. The kernel guarantees
to set it to 0 when a thread is launched,
so we can use it to detect whether this
......
......@@ -25,7 +25,7 @@
extern __inline__ unsigned int readFPSR(void)
{
FPA11 *fpa11 = GET_FPA11();
return(fpa11->fpsr);
return (fpa11->fpsr);
}
extern __inline__ void writeFPSR(FPSR reg)
......@@ -40,7 +40,7 @@ extern __inline__ FPCR readFPCR(void)
{
FPA11 *fpa11 = GET_FPA11();
/* clear SB, AB and DA bits before returning FPCR */
return(fpa11->fpcr & ~MASK_RFC);
return (fpa11->fpcr & ~MASK_RFC);
}
extern __inline__ void writeFPCR(FPCR reg)
......
......@@ -22,9 +22,9 @@
#include "fpa11.h"
#include "fpopcode.h"
unsigned int SingleCPDO(const unsigned int opcode, FPREG *rfd);
unsigned int DoubleCPDO(const unsigned int opcode, FPREG *rfd);
unsigned int ExtendedCPDO(const unsigned int opcode, FPREG *rfd);
unsigned int SingleCPDO(const unsigned int opcode, FPREG * rfd);
unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rfd);
unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rfd);
unsigned int EmulateCPDO(const unsigned int opcode)
{
......@@ -37,7 +37,8 @@ unsigned int EmulateCPDO(const unsigned int opcode)
/* Get the destination size. If not valid let Linux perform
an invalid instruction trap. */
nDest = getDestinationSize(opcode);
if (typeNone == nDest) return 0;
if (typeNone == nDest)
return 0;
SetRoundingMode(opcode);
......@@ -51,40 +52,41 @@ unsigned int EmulateCPDO(const unsigned int opcode)
else
nType = fpa11->fType[getFn(opcode)];
if (!CONSTANT_FM(opcode))
{
if (!CONSTANT_FM(opcode)) {
register unsigned int Fm = getFm(opcode);
if (nType < fpa11->fType[Fm])
{
if (nType < fpa11->fType[Fm]) {
nType = fpa11->fType[Fm];
}
}
rFd = &fpa11->fpreg[getFd(opcode)];
switch (nType)
{
case typeSingle : nRc = SingleCPDO(opcode, rFd); break;
case typeDouble : nRc = DoubleCPDO(opcode, rFd); break;
case typeExtended : nRc = ExtendedCPDO(opcode, rFd); break;
default : nRc = 0;
switch (nType) {
case typeSingle:
nRc = SingleCPDO(opcode, rFd);
break;
case typeDouble:
nRc = DoubleCPDO(opcode, rFd);
break;
case typeExtended:
nRc = ExtendedCPDO(opcode, rFd);
break;
default:
nRc = 0;
}
/* The CPDO functions used to always set the destination type
to be the same as their working size. */
if (nRc != 0)
{
if (nRc != 0) {
/* If the operation succeeded, check to see if the result in the
destination register is the correct size. If not force it
to be. */
fpa11->fType[getFd(opcode)] = nDest;
if (nDest != nType)
{
switch (nDest)
{
if (nDest != nType) {
switch (nDest) {
case typeSingle:
{
if (typeDouble == nType)
......
......@@ -28,50 +28,45 @@
#include <asm/uaccess.h>
static inline
void loadSingle(const unsigned int Fn,const unsigned int *pMem)
static inline void loadSingle(const unsigned int Fn, const unsigned int *pMem)
{
FPA11 *fpa11 = GET_FPA11();
fpa11->fType[Fn] = typeSingle;
get_user(fpa11->fpreg[Fn].fSingle, pMem);
}
static inline
void loadDouble(const unsigned int Fn,const unsigned int *pMem)
static inline void loadDouble(const unsigned int Fn, const unsigned int *pMem)
{
FPA11 *fpa11 = GET_FPA11();
unsigned int *p;
p = (unsigned int*)&fpa11->fpreg[Fn].fDouble;
p = (unsigned int *) &fpa11->fpreg[Fn].fDouble;
fpa11->fType[Fn] = typeDouble;
get_user(p[0], &pMem[1]);
get_user(p[1], &pMem[0]); /* sign & exponent */
}
static inline
void loadExtended(const unsigned int Fn,const unsigned int *pMem)
static inline void loadExtended(const unsigned int Fn, const unsigned int *pMem)
{
FPA11 *fpa11 = GET_FPA11();
unsigned int *p;
p = (unsigned int*)&fpa11->fpreg[Fn].fExtended;
p = (unsigned int *) &fpa11->fpreg[Fn].fExtended;
fpa11->fType[Fn] = typeExtended;
get_user(p[0], &pMem[0]); /* sign & exponent */
get_user(p[1], &pMem[2]); /* ls bits */
get_user(p[2], &pMem[1]); /* ms bits */
}
static inline
void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
static inline void loadMultiple(const unsigned int Fn, const unsigned int *pMem)
{
FPA11 *fpa11 = GET_FPA11();
register unsigned int *p;
unsigned long x;
p = (unsigned int*)&(fpa11->fpreg[Fn]);
p = (unsigned int *) &(fpa11->fpreg[Fn]);
get_user(x, &pMem[0]);
fpa11->fType[Fn] = (x >> 14) & 0x00000003;
switch (fpa11->fType[Fn])
{
switch (fpa11->fType[Fn]) {
case typeSingle:
case typeDouble:
{
......@@ -91,18 +86,15 @@ void loadMultiple(const unsigned int Fn,const unsigned int *pMem)
}
}
static inline
void storeSingle(const unsigned int Fn,unsigned int *pMem)
static inline void storeSingle(const unsigned int Fn, unsigned int *pMem)
{
FPA11 *fpa11 = GET_FPA11();
union
{
union {
float32 f;
unsigned int i[1];
} val;
switch (fpa11->fType[Fn])
{
switch (fpa11->fType[Fn]) {
case typeDouble:
val.f = float64_to_float32(fpa11->fpreg[Fn].fDouble);
break;
......@@ -111,24 +103,22 @@ void storeSingle(const unsigned int Fn,unsigned int *pMem)
val.f = floatx80_to_float32(fpa11->fpreg[Fn].fExtended);
break;
default: val.f = fpa11->fpreg[Fn].fSingle;
default:
val.f = fpa11->fpreg[Fn].fSingle;
}
put_user(val.i[0], pMem);
}
static inline
void storeDouble(const unsigned int Fn,unsigned int *pMem)
static inline void storeDouble(const unsigned int Fn, unsigned int *pMem)
{
FPA11 *fpa11 = GET_FPA11();
union
{
union {
float64 f;
unsigned int i[2];
} val;
switch (fpa11->fType[Fn])
{
switch (fpa11->fType[Fn]) {
case typeSingle:
val.f = float32_to_float64(fpa11->fpreg[Fn].fSingle);
break;
......@@ -137,25 +127,23 @@ void storeDouble(const unsigned int Fn,unsigned int *pMem)
val.f = floatx80_to_float64(fpa11->fpreg[Fn].fExtended);
break;
default: val.f = fpa11->fpreg[Fn].fDouble;
default:
val.f = fpa11->fpreg[Fn].fDouble;
}
put_user(val.i[1], &pMem[0]); /* msw */
put_user(val.i[0], &pMem[1]); /* lsw */
}
static inline
void storeExtended(const unsigned int Fn,unsigned int *pMem)
static inline void storeExtended(const unsigned int Fn, unsigned int *pMem)
{
FPA11 *fpa11 = GET_FPA11();
union
{
union {
floatx80 f;
unsigned int i[3];
} val;
switch (fpa11->fType[Fn])
{
switch (fpa11->fType[Fn]) {
case typeSingle:
val.f = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
break;
......@@ -164,7 +152,8 @@ void storeExtended(const unsigned int Fn,unsigned int *pMem)
val.f = float64_to_floatx80(fpa11->fpreg[Fn].fDouble);
break;
default: val.f = fpa11->fpreg[Fn].fExtended;
default:
val.f = fpa11->fpreg[Fn].fExtended;
}
put_user(val.i[0], &pMem[0]); /* sign & exp */
......@@ -172,17 +161,15 @@ void storeExtended(const unsigned int Fn,unsigned int *pMem)
put_user(val.i[2], &pMem[1]); /* msw */
}
static inline
void storeMultiple(const unsigned int Fn,unsigned int *pMem)
static inline void storeMultiple(const unsigned int Fn, unsigned int *pMem)
{
FPA11 *fpa11 = GET_FPA11();
register unsigned int nType, *p;
p = (unsigned int*)&(fpa11->fpreg[Fn]);
p = (unsigned int *) &(fpa11->fpreg[Fn]);
nType = fpa11->fType[Fn];
switch (nType)
{
switch (nType) {
case typeSingle:
case typeDouble:
{
......@@ -209,9 +196,8 @@ unsigned int PerformLDF(const unsigned int opcode)
//printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
pBase = (unsigned int*)readRegister(getRn(opcode));
if (REG_PC == getRn(opcode))
{
pBase = (unsigned int *) readRegister(getRn(opcode));
if (REG_PC == getRn(opcode)) {
pBase += 2;
write_back = 0;
}
......@@ -222,17 +208,27 @@ unsigned int PerformLDF(const unsigned int opcode)
else
pFinal -= getOffset(opcode);
if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
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;
case TRANSFER_EXTENDED: loadExtended(getFd(opcode),pAddress); break;
default: nRc = 0;
switch (opcode & MASK_TRANSFER_LENGTH) {
case TRANSFER_SINGLE:
loadSingle(getFd(opcode), pAddress);
break;
case TRANSFER_DOUBLE:
loadDouble(getFd(opcode), pAddress);
break;
case TRANSFER_EXTENDED:
loadExtended(getFd(opcode), pAddress);
break;
default:
nRc = 0;
}
if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
if (write_back)
writeRegister(getRn(opcode), (unsigned int) pFinal);
return nRc;
}
......@@ -244,9 +240,8 @@ unsigned int PerformSTF(const unsigned int opcode)
//printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode));
SetRoundingMode(ROUND_TO_NEAREST);
pBase = (unsigned int*)readRegister(getRn(opcode));
if (REG_PC == getRn(opcode))
{
pBase = (unsigned int *) readRegister(getRn(opcode));
if (REG_PC == getRn(opcode)) {
pBase += 2;
write_back = 0;
}
......@@ -257,17 +252,27 @@ unsigned int PerformSTF(const unsigned int opcode)
else
pFinal -= getOffset(opcode);
if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
if (PREINDEXED(opcode))
pAddress = pFinal;
else
pAddress = pBase;
switch (opcode & MASK_TRANSFER_LENGTH)
{
case TRANSFER_SINGLE : storeSingle(getFd(opcode),pAddress); break;
case TRANSFER_DOUBLE : storeDouble(getFd(opcode),pAddress); break;
case TRANSFER_EXTENDED: storeExtended(getFd(opcode),pAddress); break;
default: nRc = 0;
switch (opcode & MASK_TRANSFER_LENGTH) {
case TRANSFER_SINGLE:
storeSingle(getFd(opcode), pAddress);
break;
case TRANSFER_DOUBLE:
storeDouble(getFd(opcode), pAddress);
break;
case TRANSFER_EXTENDED:
storeExtended(getFd(opcode), pAddress);
break;
default:
nRc = 0;
}
if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal);
if (write_back)
writeRegister(getRn(opcode), (unsigned int) pFinal);
return nRc;
}
......@@ -276,9 +281,8 @@ unsigned int PerformLFM(const unsigned int opcode)
unsigned int i, Fd, *pBase, *pAddress, *pFinal,
write_back = WRITE_BACK(opcode);
pBase = (unsigned int*)readRegister(getRn(opcode));
if (REG_PC == getRn(opcode))
{
pBase = (unsigned int *) readRegister(getRn(opcode));
if (REG_PC == getRn(opcode)) {
pBase += 2;
write_back = 0;
}
......@@ -289,17 +293,22 @@ unsigned int PerformLFM(const unsigned int opcode)
else
pFinal -= getOffset(opcode);
if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
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;
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 int)pFinal);
if (write_back)
writeRegister(getRn(opcode), (unsigned int) pFinal);
return 1;
}
......@@ -308,9 +317,8 @@ unsigned int PerformSFM(const unsigned int opcode)
unsigned int i, Fd, *pBase, *pAddress, *pFinal,
write_back = WRITE_BACK(opcode);
pBase = (unsigned int*)readRegister(getRn(opcode));
if (REG_PC == getRn(opcode))
{
pBase = (unsigned int *) readRegister(getRn(opcode));
if (REG_PC == getRn(opcode)) {
pBase += 2;
write_back = 0;
}
......@@ -321,17 +329,22 @@ unsigned int PerformSFM(const unsigned int opcode)
else
pFinal -= getOffset(opcode);
if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase;
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;
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 int)pFinal);
if (write_back)
writeRegister(getRn(opcode), (unsigned int) pFinal);
return 1;
}
......@@ -342,24 +355,15 @@ unsigned int EmulateCPDT(const unsigned int opcode)
//printk("EmulateCPDT(0x%08x)\n",opcode);
if (LDF_OP(opcode))
{
if (LDF_OP(opcode)) {
nRc = PerformLDF(opcode);
}
else if (LFM_OP(opcode))
{
} else if (LFM_OP(opcode)) {
nRc = PerformLFM(opcode);
}
else if (STF_OP(opcode))
{
} else if (STF_OP(opcode)) {
nRc = PerformSTF(opcode);
}
else if (SFM_OP(opcode))
{
} else if (SFM_OP(opcode)) {
nRc = PerformSFM(opcode);
}
else
{
} else {
nRc = 0;
}
......
......@@ -29,16 +29,15 @@
#include "fpmodule.inl"
extern flag floatx80_is_nan(floatx80);
extern flag float64_is_nan( float64);
extern flag float32_is_nan( float32);
extern flag float64_is_nan(float64);
extern flag float32_is_nan(float32);
void SetRoundingMode(const unsigned int opcode);
unsigned int PerformFLT(const unsigned int opcode);
unsigned int PerformFIX(const unsigned int opcode);
static unsigned int
PerformComparison(const unsigned int opcode);
static unsigned int PerformComparison(const unsigned int opcode);
unsigned int EmulateCPRT(const unsigned int opcode)
{
......@@ -46,8 +45,7 @@ unsigned int EmulateCPRT(const unsigned int opcode)
//printk("EmulateCPRT(0x%08x)\n",opcode);
if (opcode & 0x800000)
{
if (opcode & 0x800000) {
/* This is some variant of a comparison (PerformComparison will
sort out which one). Since most of the other CPRT
instructions are oddball cases of some sort or other it makes
......@@ -56,21 +54,32 @@ unsigned int EmulateCPRT(const unsigned int opcode)
}
/* Hint to GCC that we'd like a jump table rather than a load of CMPs */
switch ((opcode & 0x700000) >> 20)
{
case FLT_CODE >> 20: nRc = PerformFLT(opcode); break;
case FIX_CODE >> 20: nRc = PerformFIX(opcode); break;
switch ((opcode & 0x700000) >> 20) {
case FLT_CODE >> 20:
nRc = PerformFLT(opcode);
break;
case FIX_CODE >> 20:
nRc = PerformFIX(opcode);
break;
case WFS_CODE >> 20: writeFPSR(readRegister(getRd(opcode))); break;
case RFS_CODE >> 20: writeRegister(getRd(opcode),readFPSR()); break;
case WFS_CODE >> 20:
writeFPSR(readRegister(getRd(opcode)));
break;
case RFS_CODE >> 20:
writeRegister(getRd(opcode), readFPSR());
break;
#if 0 /* We currently have no use for the FPCR, so there's no point
in emulating it. */
case WFC_CODE >> 20: writeFPCR(readRegister(getRd(opcode)));
case RFC_CODE >> 20: writeRegister(getRd(opcode),readFPCR()); break;
case WFC_CODE >> 20:
writeFPCR(readRegister(getRd(opcode)));
case RFC_CODE >> 20:
writeRegister(getRd(opcode), readFPCR());
break;
#endif
default: nRc = 0;
default:
nRc = 0;
}
return nRc;
......@@ -83,33 +92,30 @@ unsigned int PerformFLT(const unsigned int opcode)
unsigned int nRc = 1;
SetRoundingMode(opcode);
switch (opcode & MASK_ROUNDING_PRECISION)
{
switch (opcode & MASK_ROUNDING_PRECISION) {
case ROUND_SINGLE:
{
fpa11->fType[getFn(opcode)] = typeSingle;
fpa11->fpreg[getFn(opcode)].fSingle =
int32_to_float32(readRegister(getRd(opcode)));
fpa11->fpreg[getFn(opcode)].fSingle = int32_to_float32(readRegister(getRd(opcode)));
}
break;
case ROUND_DOUBLE:
{
fpa11->fType[getFn(opcode)] = typeDouble;
fpa11->fpreg[getFn(opcode)].fDouble =
int32_to_float64(readRegister(getRd(opcode)));
fpa11->fpreg[getFn(opcode)].fDouble = int32_to_float64(readRegister(getRd(opcode)));
}
break;
case ROUND_EXTENDED:
{
fpa11->fType[getFn(opcode)] = typeExtended;
fpa11->fpreg[getFn(opcode)].fExtended =
int32_to_floatx80(readRegister(getRd(opcode)));
fpa11->fpreg[getFn(opcode)].fExtended = int32_to_floatx80(readRegister(getRd(opcode)));
}
break;
default: nRc = 0;
default:
nRc = 0;
}
return nRc;
......@@ -123,56 +129,48 @@ unsigned int PerformFIX(const unsigned int opcode)
SetRoundingMode(opcode);
switch (fpa11->fType[Fn])
{
switch (fpa11->fType[Fn]) {
case typeSingle:
{
writeRegister(getRd(opcode),
float32_to_int32(fpa11->fpreg[Fn].fSingle));
writeRegister(getRd(opcode), float32_to_int32(fpa11->fpreg[Fn].fSingle));
}
break;
case typeDouble:
{
writeRegister(getRd(opcode),
float64_to_int32(fpa11->fpreg[Fn].fDouble));
writeRegister(getRd(opcode), float64_to_int32(fpa11->fpreg[Fn].fDouble));
}
break;
case typeExtended:
{
writeRegister(getRd(opcode),
floatx80_to_int32(fpa11->fpreg[Fn].fExtended));
writeRegister(getRd(opcode), floatx80_to_int32(fpa11->fpreg[Fn].fExtended));
}
break;
default: nRc = 0;
default:
nRc = 0;
}
return nRc;
}
static unsigned int __inline__
PerformComparisonOperation(floatx80 Fn, floatx80 Fm)
static unsigned int __inline__ PerformComparisonOperation(floatx80 Fn, floatx80 Fm)
{
unsigned int flags = 0;
/* test for less than condition */
if (floatx80_lt(Fn,Fm))
{
if (floatx80_lt(Fn, Fm)) {
flags |= CC_NEGATIVE;
}
/* test for equal condition */
if (floatx80_eq(Fn,Fm))
{
if (floatx80_eq(Fn, Fm)) {
flags |= CC_ZERO;
}
/* test for greater than or equal condition */
if (floatx80_lt(Fm,Fn))
{
if (floatx80_lt(Fm, Fn)) {
flags |= CC_CARRY;
}
......@@ -201,8 +199,7 @@ static unsigned int PerformComparison(const unsigned int opcode)
?? Might be some mileage in avoiding this conversion if possible.
Eg, if both operands are 32-bit, detect this and do a 32-bit
comparison (cheaper than an 80-bit one). */
switch (fpa11->fType[Fn])
{
switch (fpa11->fType[Fn]) {
case typeSingle:
//printk("single.\n");
if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
......@@ -224,21 +221,18 @@ static unsigned int PerformComparison(const unsigned int opcode)
rFn = fpa11->fpreg[Fn].fExtended;
break;
default: return 0;
default:
return 0;
}
if (CONSTANT_FM(opcode))
{
if (CONSTANT_FM(opcode)) {
//printk("Fm is a constant: #%d.\n",Fm);
rFm = getExtendedConstant(Fm);
if (floatx80_is_nan(rFm))
goto unordered;
}
else
{
} else {
//printk("Fm = r%d which contains a ",Fm);
switch (fpa11->fType[Fm])
{
switch (fpa11->fType[Fm]) {
case typeSingle:
//printk("single.\n");
if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
......@@ -260,16 +254,16 @@ static unsigned int PerformComparison(const unsigned int opcode)
rFm = fpa11->fpreg[Fm].fExtended;
break;
default: return 0;
default:
return 0;
}
}
if (n_flag)
{
if (n_flag) {
rFm.high ^= 0x8000;
}
return PerformComparisonOperation(rFn,rFm);
return PerformComparisonOperation(rFn, rFm);
unordered:
/* ?? The FPA data sheet is pretty vague about this, in particular
......@@ -280,9 +274,11 @@ static unsigned int PerformComparison(const unsigned int opcode)
flags |= CC_OVERFLOW;
flags &= ~(CC_ZERO | CC_NEGATIVE);
if (BIT_AC & readFPSR()) flags |= CC_CARRY;
if (BIT_AC & readFPSR())
flags |= CC_CARRY;
if (e_flag) float_raise(float_flag_invalid);
if (e_flag)
float_raise(float_flag_invalid);
writeConditionCodes(flags);
return 1;
......
......@@ -70,17 +70,6 @@ static void (*orig_fp_init)(union fp_state *);
/* forward declarations */
extern void nwfpe_enter(void);
#ifdef MODULE
/*
* Return 0 if we can be unloaded. This can only happen if
* kern_fp_enter is still pointing at nwfpe_enter
*/
static int fpe_unload(void)
{
return (kern_fp_enter == nwfpe_enter) ? 0 : 1;
}
#endif
static int __init fpe_init(void)
{
if (sizeof(FPA11) > sizeof(union fp_state)) {
......@@ -92,15 +81,8 @@ static int __init fpe_init(void)
printk(KERN_ERR "nwfpe: bad register size\n");
return -EINVAL;
}
#ifdef MODULE
if (!mod_member_present(&__this_module, can_unload))
return -EINVAL;
__this_module.can_unload = fpe_unload;
#else
if (fpe_type[0] && strcmp(fpe_type, "nwfpe"))
return 0;
#endif
/* Display title, version and copyright information. */
printk(KERN_WARNING "NetWinder Floating Point Emulator V0.95 "
......@@ -147,7 +129,8 @@ void float_raise(signed char flags)
register unsigned int fpsr, cumulativeTraps;
#ifdef CONFIG_DEBUG_USER
printk(KERN_DEBUG "NWFPE: %s[%d] takes exception %08x at %p from %08x\n",
printk(KERN_DEBUG
"NWFPE: %s[%d] takes exception %08x at %p from %08x\n",
current->comm, current->pid, flags,
__builtin_return_address(0), GET_USERREG()[15]);
#endif
......
......@@ -22,8 +22,8 @@
extern __inline__
unsigned int readRegister(const unsigned int nReg)
{
/* Note: The CPU thinks it has dealt with the current instruction. As
a result the program counter has been advanced to the next
/* Note: The CPU thinks it has dealt with the current instruction.
As a result the program counter has been advanced to the next
instruction, and points 4 bytes beyond the actual instruction
that caused the invalid instruction trap to occur. We adjust
for this in this routine. LDF/STF instructions with Rn = PC
......@@ -31,7 +31,8 @@ unsigned int readRegister(const unsigned int nReg)
address calculations. */
unsigned int *userRegisters = GET_USERREG();
unsigned int val = userRegisters[nReg];
if (REG_PC == nReg) val -= 4;
if (REG_PC == nReg)
val -= 4;
return val;
}
......@@ -45,22 +46,22 @@ void writeRegister(const unsigned int nReg, const unsigned int val)
extern __inline__
unsigned int readCPSR(void)
{
return(readRegister(REG_CPSR));
return (readRegister(REG_CPSR));
}
extern __inline__
void writeCPSR(const unsigned int val)
{
writeRegister(REG_CPSR,val);
writeRegister(REG_CPSR, val);
}
extern __inline__
unsigned int readConditionCodes(void)
{
#ifdef __FPEM_TEST__
return(0);
return (0);
#else
return(readCPSR() & CC_MASK);
return (readCPSR() & CC_MASK);
#endif
}
......
......@@ -27,14 +27,14 @@
#include "fpmodule.inl"
const floatx80 floatx80Constant[] = {
{ 0x0000, 0x0000000000000000ULL}, /* extended 0.0 */
{ 0x3fff, 0x8000000000000000ULL}, /* extended 1.0 */
{ 0x4000, 0x8000000000000000ULL}, /* extended 2.0 */
{ 0x4000, 0xc000000000000000ULL}, /* extended 3.0 */
{ 0x4001, 0x8000000000000000ULL}, /* extended 4.0 */
{ 0x4001, 0xa000000000000000ULL}, /* extended 5.0 */
{ 0x3ffe, 0x8000000000000000ULL}, /* extended 0.5 */
{ 0x4002, 0xa000000000000000ULL} /* extended 10.0 */
{0x0000, 0x0000000000000000ULL}, /* extended 0.0 */
{0x3fff, 0x8000000000000000ULL}, /* extended 1.0 */
{0x4000, 0x8000000000000000ULL}, /* extended 2.0 */
{0x4000, 0xc000000000000000ULL}, /* extended 3.0 */
{0x4001, 0x8000000000000000ULL}, /* extended 4.0 */
{0x4001, 0xa000000000000000ULL}, /* extended 5.0 */
{0x3ffe, 0x8000000000000000ULL}, /* extended 0.5 */
{0x4002, 0xa000000000000000ULL} /* extended 10.0 */
};
const float64 float64Constant[] = {
......@@ -63,61 +63,87 @@ unsigned int getTransferLength(const unsigned int opcode)
{
unsigned int nRc;
switch (opcode & MASK_TRANSFER_LENGTH)
{
case 0x00000000: nRc = 1; break; /* single precision */
case 0x00008000: nRc = 2; break; /* double precision */
case 0x00400000: nRc = 3; break; /* extended precision */
default: nRc = 0;
switch (opcode & MASK_TRANSFER_LENGTH) {
case 0x00000000:
nRc = 1;
break; /* single precision */
case 0x00008000:
nRc = 2;
break; /* double precision */
case 0x00400000:
nRc = 3;
break; /* extended precision */
default:
nRc = 0;
}
return(nRc);
return (nRc);
}
unsigned int getRegisterCount(const unsigned int opcode)
{
unsigned int nRc;
switch (opcode & MASK_REGISTER_COUNT)
{
case 0x00000000: nRc = 4; break;
case 0x00008000: nRc = 1; break;
case 0x00400000: nRc = 2; break;
case 0x00408000: nRc = 3; break;
default: nRc = 0;
switch (opcode & MASK_REGISTER_COUNT) {
case 0x00000000:
nRc = 4;
break;
case 0x00008000:
nRc = 1;
break;
case 0x00400000:
nRc = 2;
break;
case 0x00408000:
nRc = 3;
break;
default:
nRc = 0;
}
return(nRc);
return (nRc);
}
unsigned int getRoundingPrecision(const unsigned int opcode)
{
unsigned int nRc;
switch (opcode & MASK_ROUNDING_PRECISION)
{
case 0x00000000: nRc = 1; break;
case 0x00000080: nRc = 2; break;
case 0x00080000: nRc = 3; break;
default: nRc = 0;
switch (opcode & MASK_ROUNDING_PRECISION) {
case 0x00000000:
nRc = 1;
break;
case 0x00000080:
nRc = 2;
break;
case 0x00080000:
nRc = 3;
break;
default:
nRc = 0;
}
return(nRc);
return (nRc);
}
unsigned int getDestinationSize(const unsigned int opcode)
{
unsigned int nRc;
switch (opcode & MASK_DESTINATION_SIZE)
{
case 0x00000000: nRc = typeSingle; break;
case 0x00000080: nRc = typeDouble; break;
case 0x00080000: nRc = typeExtended; break;
default: nRc = typeNone;
switch (opcode & MASK_DESTINATION_SIZE) {
case 0x00000000:
nRc = typeSingle;
break;
case 0x00000080:
nRc = typeDouble;
break;
case 0x00080000:
nRc = typeExtended;
break;
default:
nRc = typeNone;
}
return(nRc);
return (nRc);
}
/* condition code lookup table
......@@ -144,5 +170,5 @@ static const unsigned short aCC[16] = {
unsigned int checkCondition(const unsigned int opcode, const unsigned int ccodes)
{
return (aCC[opcode>>28] >> (ccodes>>28)) & 1;
return (aCC[opcode >> 28] >> (ccodes >> 28)) & 1;
}
......@@ -32,8 +32,8 @@ float32 float32_arctan(float32 rFm);
float32 float32_log(float32 rFm);
float32 float32_tan(float32 rFm);
float32 float32_arccos(float32 rFm);
float32 float32_pow(float32 rFn,float32 rFm);
float32 float32_pol(float32 rFn,float32 rFm);
float32 float32_pow(float32 rFn, float32 rFm);
float32 float32_pol(float32 rFn, float32 rFm);
static float32 float32_rsf(float32 rFn, float32 rFm)
{
......@@ -45,8 +45,7 @@ static float32 float32_rdv(float32 rFn, float32 rFm)
return float32_div(rFm, rFn);
}
static float32 (* const dyadic_single[16])(float32 rFn, float32 rFm) =
{
static float32 (*const dyadic_single[16])(float32 rFn, float32 rFm) = {
[ADF_CODE >> 20] = float32_add,
[MUF_CODE >> 20] = float32_mul,
[SUF_CODE >> 20] = float32_sub,
......@@ -54,6 +53,7 @@ static float32 (* const dyadic_single[16])(float32 rFn, float32 rFm) =
[DVF_CODE >> 20] = float32_div,
[RDF_CODE >> 20] = float32_rdv,
[RMF_CODE >> 20] = float32_rem,
[FML_CODE >> 20] = float32_mul,
[FDV_CODE >> 20] = float32_div,
[FRD_CODE >> 20] = float32_rdv,
......@@ -74,8 +74,7 @@ static float32 float32_abs(float32 rFm)
return rFm & 0x7fffffff;
}
static float32 (* const monadic_single[16])(float32 rFm) =
{
static float32 (*const monadic_single[16])(float32 rFm) = {
[MVF_CODE >> 20] = float32_mvf,
[MNF_CODE >> 20] = float32_mnf,
[ABS_CODE >> 20] = float32_abs,
......@@ -85,51 +84,36 @@ static float32 (* const monadic_single[16])(float32 rFm) =
[NRM_CODE >> 20] = float32_mvf,
};
unsigned int SingleCPDO(const unsigned int opcode, FPREG *rFd)
unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd)
{
FPA11 *fpa11 = GET_FPA11();
float32 rFm;
unsigned int Fm, opc;
Fm = getFm(opcode);
if (CONSTANT_FM(opcode))
{
if (CONSTANT_FM(opcode)) {
rFm = getSingleConstant(Fm);
}
else if (fpa11->fType[Fm] == typeSingle)
{
} else if (fpa11->fType[Fm] == typeSingle) {
rFm = fpa11->fpreg[Fm].fSingle;
}
else
{
} else {
return 0;
}
opc = opcode & MASK_ARITHMETIC_OPCODE;
if (!MONADIC_INSTRUCTION(opcode))
{
if (!MONADIC_INSTRUCTION(opcode)) {
unsigned int Fn = getFn(opcode);
float32 rFn;
if (fpa11->fType[Fn] == typeSingle &&
dyadic_single[opc >> 20])
{
if (fpa11->fType[Fn] == typeSingle && dyadic_single[opc >> 20]) {
rFn = fpa11->fpreg[Fn].fSingle;
rFd->fSingle = dyadic_single[opc >> 20](rFn, rFm);
}
else
{
} else {
return 0;
}
}
else
{
if (monadic_single[opc >> 20])
{
} else {
if (monadic_single[opc >> 20]) {
rFd->fSingle = monadic_single[opc >> 20](rFm);
}
else
{
} else {
return 0;
}
}
......
......@@ -184,9 +184,9 @@ INLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig )
{
#if 0
float32 f;
__asm__("@ packFloat32; \n\
mov %0, %1, asl #31; \n\
orr %0, %2, asl #23; \n\
__asm__("@ packFloat32 \n\
mov %0, %1, asl #31 \n\
orr %0, %2, asl #23 \n\
orr %0, %3"
: /* no outputs */
: "g" (f), "g" (zSign), "g" (zExp), "g" (zSig)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment