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