Commit 58ada350 authored by Russell King's avatar Russell King

Merge flint.arm.linux.org.uk:/usr/src/linux-bk-2.5/linux-2.5-nwfpe

into flint.arm.linux.org.uk:/usr/src/linux-bk-2.5/linux-2.5-rmk
parents 8a0aa9f7 180699eb
......@@ -628,6 +628,18 @@ config FPE_NWFPE
You may say N here if you are going to load the Acorn FPEmulator
early in the bootup.
config FPE_NWFPE_XP
bool "Support extended precision"
depends on FPE_NWFPE
help
Say Y to include 80-bit support in the kernel floating-point
emulator. Otherwise, only 32 and 64-bit support is compiled in.
Note that gcc does not generate 80-bit operations by default,
so in most cases this option only enlarges the size of the
floating point emulator without any good reason.
You almost surely want to say N here.
config FPE_FASTFPE
tristate "FastFPE math emulation (EXPERIMENTAL)"
depends on !CPU_26 && !CPU_32v3 && EXPERIMENTAL
......
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.
* Removed dead code and fixed function protypes to match definitions.
* Consolidated use of (opcode && MASK_ARITHMETIC_OPCODE) >> 20.
* Make 80-bit precision a compile-time option. (1%)
* Only initialize FPE state once in repeat-FP situations. (6%)
2002-01-19 Russell King <rmk@arm.linux.org.uk>
* fpa11.h - Add documentation
......
......@@ -2,18 +2,12 @@
# Copyright (C) 1998, 1999, 2001 Philip Blundell
#
obj-y :=
obj-m :=
obj-n :=
obj-$(CONFIG_FPE_NWFPE) += nwfpe.o
nwfpe-objs := fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o \
fpmodule.o fpopcode.o softfloat.o \
single_cpdo.o double_cpdo.o extended_cpdo.o
nwfpe-y += fpa11.o fpa11_cpdo.o fpa11_cpdt.o \
fpa11_cprt.o fpmodule.o fpopcode.o \
softfloat.o single_cpdo.o double_cpdo.o
ifeq ($(CONFIG_CPU_26),y)
nwfpe-objs += entry26.o
else
nwfpe-objs += entry.o
endif
nwfpe-$(CONFIG_FPE_NWFPE_XP) += extended_cpdo.o
nwfpe-$(CONFIG_CPU_26) += entry26.o
nwfpe-$(CONFIG_CPU_32) += entry.o
......@@ -23,6 +23,11 @@
#include "softfloat.h"
#include "fpopcode.h"
union float64_components {
float64 f64;
unsigned int i[2];
};
float64 float64_exp(float64 Fm);
float64 float64_ln(float64 Fm);
float64 float64_sin(float64 rFm);
......@@ -32,26 +37,80 @@ 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);
unsigned int DoubleCPDO(const unsigned int opcode)
static float64 float64_rsf(float64 rFn, float64 rFm)
{
FPA11 *fpa11 = GET_FPA11();
float64 rFm, rFn;
unsigned int Fd, Fm, Fn, nRc = 1;
return float64_sub(rFm, rFn);
}
static float64 float64_rdv(float64 rFn, float64 rFm)
{
return float64_div(rFm, rFn);
}
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,
[RSF_CODE >> 20] = float64_rsf,
[DVF_CODE >> 20] = float64_div,
[RDF_CODE >> 20] = float64_rdv,
[RMF_CODE >> 20] = float64_rem,
/* strictly, these opcodes should not be implemented */
[FML_CODE >> 20] = float64_mul,
[FDV_CODE >> 20] = float64_div,
[FRD_CODE >> 20] = float64_rdv,
};
static float64 float64_mvf(float64 rFm)
{
return rFm;
}
static float64 float64_mnf(float64 rFm)
{
union float64_components u;
u.f64 = rFm;
u.i[1] ^= 0x80000000;
return u.f64;
}
//printk("DoubleCPDO(0x%08x)\n",opcode);
static float64 float64_abs(float64 rFm)
{
union float64_components u;
u.f64 = rFm;
u.i[1] &= 0x7fffffff;
return u.f64;
}
static float64 (*const monadic_double[16])(float64 rFm) = {
[MVF_CODE >> 20] = float64_mvf,
[MNF_CODE >> 20] = float64_mnf,
[ABS_CODE >> 20] = float64_abs,
[RND_CODE >> 20] = float64_round_to_int,
[URD_CODE >> 20] = float64_round_to_int,
[SQT_CODE >> 20] = float64_sqrt,
[NRM_CODE >> 20] = float64_mvf,
};
unsigned int DoubleCPDO(const unsigned int opcode, FPREG * rFd)
{
FPA11 *fpa11 = GET_FPA11();
float64 rFm;
unsigned int Fm, opc_mask_shift;
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;
......@@ -60,24 +119,17 @@ unsigned int DoubleCPDO(const unsigned int opcode)
rFm = fpa11->fpreg[Fm].fDouble;
break;
case typeExtended:
// !! patb
//printk("not implemented! why not?\n");
//!! ScottB
// should never get here, if extended involved
// then other operand should be promoted then
// ExtendedCPDO called.
break;
default: return 0;
default:
return 0;
}
}
if (!MONADIC_INSTRUCTION(opcode))
{
Fn = getFn(opcode);
switch (fpa11->fType[Fn])
{
opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
if (!MONADIC_INSTRUCTION(opcode)) {
unsigned int Fn = getFn(opcode);
float64 rFn;
switch (fpa11->fType[Fn]) {
case typeSingle:
rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle);
break;
......@@ -86,203 +138,22 @@ unsigned int DoubleCPDO(const unsigned int opcode)
rFn = fpa11->fpreg[Fn].fDouble;
break;
default: return 0;
}
}
Fd = getFd(opcode);
/* !! this switch isn't optimized; better (opcode & MASK_ARITHMETIC_OPCODE)>>24, sort of */
switch (opcode & MASK_ARITHMETIC_OPCODE)
{
/* dyadic opcodes */
case ADF_CODE:
fpa11->fpreg[Fd].fDouble = float64_add(rFn,rFm);
break;
case MUF_CODE:
case FML_CODE:
fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm);
break;
case SUF_CODE:
fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm);
break;
case RSF_CODE:
fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn);
break;
case DVF_CODE:
case FDV_CODE:
fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm);
break;
case RDF_CODE:
case FRD_CODE:
fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn);
break;
#if 0
case POW_CODE:
fpa11->fpreg[Fd].fDouble = float64_pow(rFn,rFm);
break;
case RPW_CODE:
fpa11->fpreg[Fd].fDouble = float64_pow(rFm,rFn);
break;
#endif
case RMF_CODE:
fpa11->fpreg[Fd].fDouble = float64_rem(rFn,rFm);
break;
#if 0
case POL_CODE:
fpa11->fpreg[Fd].fDouble = float64_pol(rFn,rFm);
break;
#endif
/* monadic opcodes */
case MVF_CODE:
fpa11->fpreg[Fd].fDouble = rFm;
break;
case MNF_CODE:
{
unsigned int *p = (unsigned int*)&rFm;
p[1] ^= 0x80000000;
fpa11->fpreg[Fd].fDouble = rFm;
default:
return 0;
}
break;
case ABS_CODE:
{
unsigned int *p = (unsigned int*)&rFm;
p[1] &= 0x7fffffff;
fpa11->fpreg[Fd].fDouble = rFm;
if (dyadic_double[opc_mask_shift]) {
rFd->fDouble = dyadic_double[opc_mask_shift](rFn, rFm);
} else {
return 0;
}
break;
case RND_CODE:
case URD_CODE:
fpa11->fpreg[Fd].fDouble = float64_round_to_int(rFm);
break;
case SQT_CODE:
fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm);
break;
#if 0
case LOG_CODE:
fpa11->fpreg[Fd].fDouble = float64_log(rFm);
break;
case LGN_CODE:
fpa11->fpreg[Fd].fDouble = float64_ln(rFm);
break;
case EXP_CODE:
fpa11->fpreg[Fd].fDouble = float64_exp(rFm);
break;
case SIN_CODE:
fpa11->fpreg[Fd].fDouble = float64_sin(rFm);
break;
case COS_CODE:
fpa11->fpreg[Fd].fDouble = float64_cos(rFm);
break;
case TAN_CODE:
fpa11->fpreg[Fd].fDouble = float64_tan(rFm);
break;
case ASN_CODE:
fpa11->fpreg[Fd].fDouble = float64_arcsin(rFm);
break;
case ACS_CODE:
fpa11->fpreg[Fd].fDouble = float64_arccos(rFm);
break;
case ATN_CODE:
fpa11->fpreg[Fd].fDouble = float64_arctan(rFm);
break;
#endif
case NRM_CODE:
break;
default:
{
nRc = 0;
} else {
if (monadic_double[opc_mask_shift]) {
rFd->fDouble = monadic_double[opc_mask_shift](rFm);
} else {
return 0;
}
}
if (0 != nRc) fpa11->fType[Fd] = typeDouble;
return nRc;
}
#if 0
float64 float64_exp(float64 rFm)
{
return rFm;
//series
}
float64 float64_ln(float64 rFm)
{
return rFm;
//series
}
float64 float64_sin(float64 rFm)
{
return rFm;
//series
}
float64 float64_cos(float64 rFm)
{
return rFm;
//series
}
#if 0
float64 float64_arcsin(float64 rFm)
{
//series
}
float64 float64_arctan(float64 rFm)
{
//series
}
#endif
float64 float64_log(float64 rFm)
{
return float64_div(float64_ln(rFm),getDoubleConstant(7));
}
float64 float64_tan(float64 rFm)
{
return float64_div(float64_sin(rFm),float64_cos(rFm));
}
float64 float64_arccos(float64 rFm)
{
return rFm;
//return float64_sub(halfPi,float64_arcsin(rFm));
}
float64 float64_pow(float64 rFn,float64 rFm)
{
return float64_exp(float64_mul(rFm,float64_ln(rFn)));
}
float64 float64_pol(float64 rFn,float64 rFm)
{
return float64_arctan(float64_div(rFn,rFm));
return 1;
}
#endif
......@@ -73,7 +73,7 @@ several floating point instructions. */
.globl nwfpe_enter
nwfpe_enter:
mov r4, lr @ save the failure-return addresses
mov sl, sp
mov sl, sp @ we access the registers via 'sl'
ldr r5, [sp, #60] @ get contents of PC;
emulate:
......
......@@ -66,7 +66,6 @@ several floating point instructions. */
.globl nwfpe_enter
nwfpe_enter:
mov sl, sp
ldr r5, [sp, #60] @ get contents of PC
bic r5, r5, #0xfc000003
ldr r0, [r5, #-4] @ get actual instruction into r0
......
......@@ -32,26 +32,72 @@ 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);
unsigned int ExtendedCPDO(const unsigned int opcode)
static floatx80 floatx80_rsf(floatx80 rFn, floatx80 rFm)
{
FPA11 *fpa11 = GET_FPA11();
floatx80 rFm, rFn;
unsigned int Fd, Fm, Fn, nRc = 1;
return floatx80_sub(rFm, rFn);
}
static floatx80 floatx80_rdv(floatx80 rFn, floatx80 rFm)
{
return floatx80_div(rFm, rFn);
}
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,
[RSF_CODE >> 20] = floatx80_rsf,
[DVF_CODE >> 20] = floatx80_div,
[RDF_CODE >> 20] = floatx80_rdv,
[RMF_CODE >> 20] = floatx80_rem,
/* strictly, these opcodes should not be implemented */
[FML_CODE >> 20] = floatx80_mul,
[FDV_CODE >> 20] = floatx80_div,
[FRD_CODE >> 20] = floatx80_rdv,
};
static floatx80 floatx80_mvf(floatx80 rFm)
{
return rFm;
}
static floatx80 floatx80_mnf(floatx80 rFm)
{
rFm.high ^= 0x8000;
return rFm;
}
static floatx80 floatx80_abs(floatx80 rFm)
{
rFm.high &= 0x7fff;
return rFm;
}
//printk("ExtendedCPDO(0x%08x)\n",opcode);
static floatx80 (*const monadic_extended[16])(floatx80 rFm) = {
[MVF_CODE >> 20] = floatx80_mvf,
[MNF_CODE >> 20] = floatx80_mnf,
[ABS_CODE >> 20] = floatx80_abs,
[RND_CODE >> 20] = floatx80_round_to_int,
[URD_CODE >> 20] = floatx80_round_to_int,
[SQT_CODE >> 20] = floatx80_sqrt,
[NRM_CODE >> 20] = floatx80_mvf,
};
unsigned int ExtendedCPDO(const unsigned int opcode, FPREG * rFd)
{
FPA11 *fpa11 = GET_FPA11();
floatx80 rFm;
unsigned int Fm, opc_mask_shift;
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;
......@@ -64,15 +110,17 @@ unsigned int ExtendedCPDO(const unsigned int opcode)
rFm = fpa11->fpreg[Fm].fExtended;
break;
default: return 0;
default:
return 0;
}
}
if (!MONADIC_INSTRUCTION(opcode))
{
Fn = getFn(opcode);
switch (fpa11->fType[Fn])
{
opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
if (!MONADIC_INSTRUCTION(opcode)) {
unsigned int Fn = getFn(opcode);
floatx80 rFn;
switch (fpa11->fType[Fn]) {
case typeSingle:
rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle);
break;
......@@ -85,189 +133,22 @@ unsigned int ExtendedCPDO(const unsigned int opcode)
rFn = fpa11->fpreg[Fn].fExtended;
break;
default: return 0;
}
default:
return 0;
}
Fd = getFd(opcode);
switch (opcode & MASK_ARITHMETIC_OPCODE)
{
/* dyadic opcodes */
case ADF_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_add(rFn,rFm);
break;
case MUF_CODE:
case FML_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_mul(rFn,rFm);
break;
case SUF_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_sub(rFn,rFm);
break;
case RSF_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_sub(rFm,rFn);
break;
case DVF_CODE:
case FDV_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_div(rFn,rFm);
break;
case RDF_CODE:
case FRD_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_div(rFm,rFn);
break;
#if 0
case POW_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_pow(rFn,rFm);
break;
case RPW_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_pow(rFm,rFn);
break;
#endif
case RMF_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_rem(rFn,rFm);
break;
#if 0
case POL_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_pol(rFn,rFm);
break;
#endif
/* monadic opcodes */
case MVF_CODE:
fpa11->fpreg[Fd].fExtended = rFm;
break;
case MNF_CODE:
rFm.high ^= 0x8000;
fpa11->fpreg[Fd].fExtended = rFm;
break;
case ABS_CODE:
rFm.high &= 0x7fff;
fpa11->fpreg[Fd].fExtended = rFm;
break;
case RND_CODE:
case URD_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_round_to_int(rFm);
break;
case SQT_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_sqrt(rFm);
break;
#if 0
case LOG_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_log(rFm);
break;
case LGN_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_ln(rFm);
break;
case EXP_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_exp(rFm);
break;
case SIN_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_sin(rFm);
break;
case COS_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_cos(rFm);
break;
case TAN_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_tan(rFm);
break;
case ASN_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_arcsin(rFm);
break;
case ACS_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_arccos(rFm);
break;
case ATN_CODE:
fpa11->fpreg[Fd].fExtended = floatx80_arctan(rFm);
break;
#endif
case NRM_CODE:
break;
default:
{
nRc = 0;
if (dyadic_extended[opc_mask_shift]) {
rFd->fExtended = dyadic_extended[opc_mask_shift](rFn, rFm);
} else {
return 0;
}
} else {
if (monadic_extended[opc_mask_shift]) {
rFd->fExtended = monadic_extended[opc_mask_shift](rFm);
} else {
return 0;
}
}
if (0 != nRc) fpa11->fType[Fd] = typeExtended;
return nRc;
}
#if 0
floatx80 floatx80_exp(floatx80 Fm)
{
//series
}
floatx80 floatx80_ln(floatx80 Fm)
{
//series
}
floatx80 floatx80_sin(floatx80 rFm)
{
//series
}
floatx80 floatx80_cos(floatx80 rFm)
{
//series
}
floatx80 floatx80_arcsin(floatx80 rFm)
{
//series
}
floatx80 floatx80_arctan(floatx80 rFm)
{
//series
}
floatx80 floatx80_log(floatx80 rFm)
{
return floatx80_div(floatx80_ln(rFm),getExtendedConstant(7));
}
floatx80 floatx80_tan(floatx80 rFm)
{
return floatx80_div(floatx80_sin(rFm),floatx80_cos(rFm));
}
floatx80 floatx80_arccos(floatx80 rFm)
{
//return floatx80_sub(halfPi,floatx80_arcsin(rFm));
}
floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm)
{
return floatx80_exp(floatx80_mul(rFm,floatx80_ln(rFn)));
}
floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm)
{
return floatx80_arctan(floatx80_div(rFn,rFm));
return 1;
}
#endif
/*
NetWinder Floating Point Emulator
(c) Rebel.COM, 1998,1999
(c) Philip Blundell, 2001
Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
......@@ -41,95 +42,64 @@ 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;
}
/* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */
fpa11->fpsr = FP_EMULATOR | BIT_AC;
/* FPCR: set SB, AB and DA bits, clear all others */
#if MAINTAIN_FPCR
fpa11->fpcr = MASK_RESET;
#endif
}
void SetRoundingMode(const unsigned int opcode)
{
#if MAINTAIN_FPCR
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;
#if MAINTAIN_FPCR
fpa11->fpcr |= ROUND_TO_NEAREST;
#endif
break;
case ROUND_TO_PLUS_INFINITY:
float_rounding_mode = float_round_up;
#if MAINTAIN_FPCR
fpa11->fpcr |= ROUND_TO_PLUS_INFINITY;
#endif
break;
case ROUND_TO_MINUS_INFINITY:
float_rounding_mode = float_round_down;
#if MAINTAIN_FPCR
fpa11->fpcr |= ROUND_TO_MINUS_INFINITY;
#endif
break;
case ROUND_TO_ZERO:
float_rounding_mode = float_round_to_zero;
#if MAINTAIN_FPCR
fpa11->fpcr |= ROUND_TO_ZERO;
#endif
break;
}
}
void SetRoundingPrecision(const unsigned int opcode)
{
#if MAINTAIN_FPCR
FPA11 *fpa11 = GET_FPA11();
fpa11->fpcr &= ~MASK_ROUNDING_PRECISION;
#endif
switch (opcode & MASK_ROUNDING_PRECISION)
{
#ifdef CONFIG_FPE_NWFPE_XP
switch (opcode & MASK_ROUNDING_PRECISION) {
case ROUND_SINGLE:
floatx80_rounding_precision = 32;
#if MAINTAIN_FPCR
fpa11->fpcr |= ROUND_SINGLE;
#endif
break;
case ROUND_DOUBLE:
floatx80_rounding_precision = 64;
#if MAINTAIN_FPCR
fpa11->fpcr |= ROUND_DOUBLE;
#endif
break;
case ROUND_EXTENDED:
floatx80_rounding_precision = 80;
#if MAINTAIN_FPCR
fpa11->fpcr |= ROUND_EXTENDED;
#endif
break;
default: floatx80_rounding_precision = 80;
default:
floatx80_rounding_precision = 80;
}
#endif
}
void nwfpe_init(union fp_state *fp)
void nwfpe_init_fpa(union fp_state *fp)
{
FPA11 *fpa11 = (FPA11 *)fp;
#ifdef NWFPE_DEBUG
printk("NWFPE: setting up state.\n");
#endif
memset(fpa11, 0, sizeof(FPA11));
resetFPA11();
SetRoundingMode(ROUND_TO_NEAREST);
......@@ -140,81 +110,33 @@ void nwfpe_init(union fp_state *fp)
/* Emulate the instruction in the opcode. */
unsigned int EmulateAll(unsigned int opcode)
{
unsigned int nRc = 1, code;
unsigned int code;
#ifdef NWFPE_DEBUG
printk("NWFPE: emulating opcode %08x\n", opcode);
#endif
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
{
return EmulateCPRT(opcode);
} else {
/* Emulate monadic arithmetic opcodes. */
/* Emulate dyadic arithmetic opcodes. */
nRc = EmulateCPDO(opcode);
}
return EmulateCPDO(opcode);
}
else if (code == 0x0c000000)
{
} else if (code == 0x0c000000) {
/* Emulate load/store opcodes. */
/* Emulate load/store multiple opcodes. */
nRc = EmulateCPDT(opcode);
}
else
{
/* Invalid instruction detected. Return FALSE. */
nRc = 0;
}
}
return(nRc);
}
#if 0
unsigned int EmulateAll1(unsigned int opcode)
{
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;
}
return EmulateCPDT(opcode);
}
else
{
switch ((opcode >> 8) & 0xf)
{
case 0x1: return PerformSTF(opcode); break;
case 0x2: return PerformSFM(opcode); break;
default: return 0;
}
}
break;
case 0xe:
if (opcode & 0x10)
return EmulateCPDO(opcode);
else
return EmulateCPRT(opcode);
break;
default: return 0;
}
/* Invalid instruction detected. Return FALSE. */
return 0;
}
#endif
......@@ -37,6 +37,7 @@ register unsigned int *user_registers asm("sl");
/* includes */
#include "fpsr.h" /* FP control and status register definitions */
#include "milieu.h"
#include "softfloat.h"
#define typeNone 0x00
......@@ -48,9 +49,13 @@ register unsigned int *user_registers asm("sl");
* This must be no more and no less than 12 bytes.
*/
typedef union tagFPREG {
floatx80 fExtended;
float64 fDouble;
float32 fSingle;
float64 fDouble;
#ifdef CONFIG_FPE_NWFPE_XP
floatx80 fExtended;
#else
int padding[3];
#endif
} FPREG;
/*
......@@ -71,8 +76,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
......@@ -82,6 +87,6 @@ typedef struct tagFPA11 {
extern void SetRoundingMode(const unsigned int);
extern void SetRoundingPrecision(const unsigned int);
extern void nwfpe_init(union fp_state *fp);
extern void nwfpe_init_fpa(union fp_state *fp);
#endif
......@@ -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)
......
/*
NetWinder Floating Point Emulator
(c) Rebel.COM, 1998,1999
(c) Philip Blundell, 2001
Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
......@@ -22,21 +23,21 @@
#include "fpa11.h"
#include "fpopcode.h"
unsigned int SingleCPDO(const unsigned int opcode);
unsigned int DoubleCPDO(const unsigned int opcode);
unsigned int ExtendedCPDO(const unsigned int opcode);
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)
{
FPA11 *fpa11 = GET_FPA11();
unsigned int Fd, nType, nDest, nRc = 1;
//printk("EmulateCPDO(0x%08x)\n",opcode);
FPREG *rFd;
unsigned int nType, nDest, nRc;
/* 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);
......@@ -50,67 +51,80 @@ 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];
}
}
switch (nType)
{
case typeSingle : nRc = SingleCPDO(opcode); break;
case typeDouble : nRc = DoubleCPDO(opcode); break;
case typeExtended : nRc = ExtendedCPDO(opcode); break;
default : nRc = 0;
rFd = &fpa11->fpreg[getFd(opcode)];
switch (nType) {
case typeSingle:
nRc = SingleCPDO(opcode, rFd);
break;
case typeDouble:
nRc = DoubleCPDO(opcode, rFd);
break;
#ifdef CONFIG_FPE_NWFPE_XP
case typeExtended:
nRc = ExtendedCPDO(opcode, rFd);
break;
#endif
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 the operation succeeded, check to see if the result in the
destination register is the correct size. If not force it
to be. */
Fd = getFd(opcode);
nType = fpa11->fType[Fd];
if ((0 != nRc) && (nDest != nType))
{
switch (nDest)
{
fpa11->fType[getFd(opcode)] = nDest;
#ifdef CONFIG_FPE_NWFPE_XP
if (nDest != nType) {
switch (nDest) {
case typeSingle:
{
if (typeDouble == nType)
fpa11->fpreg[Fd].fSingle =
float64_to_float32(fpa11->fpreg[Fd].fDouble);
rFd->fSingle = float64_to_float32(rFd->fDouble);
else
fpa11->fpreg[Fd].fSingle =
floatx80_to_float32(fpa11->fpreg[Fd].fExtended);
rFd->fSingle = floatx80_to_float32(rFd->fExtended);
}
break;
case typeDouble:
{
if (typeSingle == nType)
fpa11->fpreg[Fd].fDouble =
float32_to_float64(fpa11->fpreg[Fd].fSingle);
rFd->fDouble = float32_to_float64(rFd->fSingle);
else
fpa11->fpreg[Fd].fDouble =
floatx80_to_float64(fpa11->fpreg[Fd].fExtended);
rFd->fDouble = floatx80_to_float64(rFd->fExtended);
}
break;
case typeExtended:
{
if (typeSingle == nType)
fpa11->fpreg[Fd].fExtended =
float32_to_floatx80(fpa11->fpreg[Fd].fSingle);
rFd->fExtended = float32_to_floatx80(rFd->fSingle);
else
fpa11->fpreg[Fd].fExtended =
float64_to_floatx80(fpa11->fpreg[Fd].fDouble);
rFd->fExtended = float64_to_floatx80(rFd->fDouble);
}
break;
}
fpa11->fType[Fd] = nDest;
}
#else
if (nDest != nType) {
if (nDest == typeSingle)
rFd->fSingle = float64_to_float32(rFd->fDouble);
else
rFd->fDouble = float32_to_float64(rFd->fSingle);
}
#endif
}
return nRc;
......
This diff is collapsed.
This diff is collapsed.
......@@ -42,11 +42,17 @@
#include "fpa11.inl"
/* kernel symbols required for signal handling */
#ifdef CONFIG_FPE_NWFPE_XP
#define NWFPE_BITS "extended"
#else
#define NWFPE_BITS "double"
#endif
#ifdef MODULE
void fp_send_sig(unsigned long sig, struct task_struct *p, int priv);
#if LINUX_VERSION_CODE > 0x20115
MODULE_AUTHOR("Scott Bambrough <scottb@rebel.com>");
MODULE_DESCRIPTION("NWFPE floating point emulator");
MODULE_DESCRIPTION("NWFPE floating point emulator (" NWFPE_BITS " precision)");
#endif
#else
......@@ -70,17 +76,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,25 +87,18 @@ 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 "
"(c) 1998-1999 Rebel.com\n");
printk(KERN_WARNING "NetWinder Floating Point Emulator V0.97 ("
NWFPE_BITS " precision)\n");
/* Save pointer to the old FP handler and then patch ourselves in */
orig_fp_enter = kern_fp_enter;
orig_fp_init = fp_init;
kern_fp_enter = nwfpe_enter;
fp_init = nwfpe_init;
fp_init = nwfpe_init_fpa;
return 0;
}
......@@ -147,7 +135,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
}
......
......@@ -26,16 +26,18 @@
#include "fpmodule.h"
#include "fpmodule.inl"
#ifdef CONFIG_FPE_NWFPE_XP
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 */
};
#endif
const float64 float64Constant[] = {
0x0000000000000000ULL, /* double 0.0 */
......@@ -59,67 +61,6 @@ const float32 float32Constant[] = {
0x41200000 /* single 10.0 */
};
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;
}
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;
}
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;
}
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;
}
return(nRc);
}
/* condition code lookup table
index into the table is test code: EQ, NE, ... LT, GT, AL, NV
bit position in short is condition code: NZCV */
......@@ -144,5 +85,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;
}
/*
NetWinder Floating Point Emulator
(c) Rebel.COM, 1998,1999
(c) Philip Blundell, 2001
Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
......@@ -366,11 +367,13 @@ TABLE 5
/* Get the rounding mode from the opcode. */
#define getRoundingMode(opcode) ((opcode & MASK_ROUNDING_MODE) >> 5)
#ifdef CONFIG_FPE_NWFPE_XP
static inline const floatx80 getExtendedConstant(const unsigned int nIndex)
{
extern const floatx80 floatx80Constant[];
return floatx80Constant[nIndex];
}
#endif
static inline const float64 getDoubleConstant(const unsigned int nIndex)
{
......@@ -384,7 +387,91 @@ static inline const float32 getSingleConstant(const unsigned int nIndex)
return float32Constant[nIndex];
}
extern unsigned int getRegisterCount(const unsigned int opcode);
extern unsigned int getDestinationSize(const unsigned int opcode);
static inline 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;
}
return (nRc);
}
static inline 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;
}
return (nRc);
}
static inline 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;
}
return (nRc);
}
static inline 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;
}
return (nRc);
}
#endif
/*
NetWinder Floating Point Emulator
(c) Rebel.COM, 1998,1999
(c) Philip Blundell, 2001
Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
......@@ -32,224 +33,92 @@ 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);
unsigned int SingleCPDO(const unsigned int opcode)
static float32 float32_rsf(float32 rFn, float32 rFm)
{
FPA11 *fpa11 = GET_FPA11();
float32 rFm, rFn;
unsigned int Fd, Fm, Fn, nRc = 1;
Fm = getFm(opcode);
if (CONSTANT_FM(opcode))
{
rFm = getSingleConstant(Fm);
}
else
{
switch (fpa11->fType[Fm])
{
case typeSingle:
rFm = fpa11->fpreg[Fm].fSingle;
break;
default: return 0;
}
}
if (!MONADIC_INSTRUCTION(opcode))
{
Fn = getFn(opcode);
switch (fpa11->fType[Fn])
{
case typeSingle:
rFn = fpa11->fpreg[Fn].fSingle;
break;
default: return 0;
}
}
Fd = getFd(opcode);
switch (opcode & MASK_ARITHMETIC_OPCODE)
{
/* dyadic opcodes */
case ADF_CODE:
fpa11->fpreg[Fd].fSingle = float32_add(rFn,rFm);
break;
case MUF_CODE:
case FML_CODE:
fpa11->fpreg[Fd].fSingle = float32_mul(rFn,rFm);
break;
case SUF_CODE:
fpa11->fpreg[Fd].fSingle = float32_sub(rFn,rFm);
break;
case RSF_CODE:
fpa11->fpreg[Fd].fSingle = float32_sub(rFm,rFn);
break;
case DVF_CODE:
case FDV_CODE:
fpa11->fpreg[Fd].fSingle = float32_div(rFn,rFm);
break;
case RDF_CODE:
case FRD_CODE:
fpa11->fpreg[Fd].fSingle = float32_div(rFm,rFn);
break;
#if 0
case POW_CODE:
fpa11->fpreg[Fd].fSingle = float32_pow(rFn,rFm);
break;
case RPW_CODE:
fpa11->fpreg[Fd].fSingle = float32_pow(rFm,rFn);
break;
#endif
case RMF_CODE:
fpa11->fpreg[Fd].fSingle = float32_rem(rFn,rFm);
break;
#if 0
case POL_CODE:
fpa11->fpreg[Fd].fSingle = float32_pol(rFn,rFm);
break;
#endif
/* monadic opcodes */
case MVF_CODE:
fpa11->fpreg[Fd].fSingle = rFm;
break;
case MNF_CODE:
rFm ^= 0x80000000;
fpa11->fpreg[Fd].fSingle = rFm;
break;
case ABS_CODE:
rFm &= 0x7fffffff;
fpa11->fpreg[Fd].fSingle = rFm;
break;
case RND_CODE:
case URD_CODE:
fpa11->fpreg[Fd].fSingle = float32_round_to_int(rFm);
break;
case SQT_CODE:
fpa11->fpreg[Fd].fSingle = float32_sqrt(rFm);
break;
#if 0
case LOG_CODE:
fpa11->fpreg[Fd].fSingle = float32_log(rFm);
break;
case LGN_CODE:
fpa11->fpreg[Fd].fSingle = float32_ln(rFm);
break;
case EXP_CODE:
fpa11->fpreg[Fd].fSingle = float32_exp(rFm);
break;
case SIN_CODE:
fpa11->fpreg[Fd].fSingle = float32_sin(rFm);
break;
case COS_CODE:
fpa11->fpreg[Fd].fSingle = float32_cos(rFm);
break;
case TAN_CODE:
fpa11->fpreg[Fd].fSingle = float32_tan(rFm);
break;
case ASN_CODE:
fpa11->fpreg[Fd].fSingle = float32_arcsin(rFm);
break;
case ACS_CODE:
fpa11->fpreg[Fd].fSingle = float32_arccos(rFm);
break;
case ATN_CODE:
fpa11->fpreg[Fd].fSingle = float32_arctan(rFm);
break;
#endif
case NRM_CODE:
break;
default:
{
nRc = 0;
}
}
if (0 != nRc) fpa11->fType[Fd] = typeSingle;
return nRc;
}
#if 0
float32 float32_exp(float32 Fm)
{
//series
return float32_sub(rFm, rFn);
}
float32 float32_ln(float32 Fm)
static float32 float32_rdv(float32 rFn, float32 rFm)
{
//series
return float32_div(rFm, rFn);
}
float32 float32_sin(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,
[RSF_CODE >> 20] = float32_rsf,
[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,
};
static float32 float32_mvf(float32 rFm)
{
//series
return rFm;
}
float32 float32_cos(float32 rFm)
static float32 float32_mnf(float32 rFm)
{
//series
return rFm ^ 0x80000000;
}
float32 float32_arcsin(float32 rFm)
static float32 float32_abs(float32 rFm)
{
//series
return rFm & 0x7fffffff;
}
float32 float32_arctan(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,
[RND_CODE >> 20] = float32_round_to_int,
[URD_CODE >> 20] = float32_round_to_int,
[SQT_CODE >> 20] = float32_sqrt,
[NRM_CODE >> 20] = float32_mvf,
};
unsigned int SingleCPDO(const unsigned int opcode, FPREG * rFd)
{
//series
}
float32 float32_arccos(float32 rFm)
{
//return float32_sub(halfPi,float32_arcsin(rFm));
}
FPA11 *fpa11 = GET_FPA11();
float32 rFm;
unsigned int Fm, opc_mask_shift;
float32 float32_log(float32 rFm)
{
return float32_div(float32_ln(rFm),getSingleConstant(7));
}
Fm = getFm(opcode);
if (CONSTANT_FM(opcode)) {
rFm = getSingleConstant(Fm);
} else if (fpa11->fType[Fm] == typeSingle) {
rFm = fpa11->fpreg[Fm].fSingle;
} else {
return 0;
}
float32 float32_tan(float32 rFm)
{
return float32_div(float32_sin(rFm),float32_cos(rFm));
}
opc_mask_shift = (opcode & MASK_ARITHMETIC_OPCODE) >> 20;
if (!MONADIC_INSTRUCTION(opcode)) {
unsigned int Fn = getFn(opcode);
float32 rFn;
float32 float32_pow(float32 rFn,float32 rFm)
{
return float32_exp(float32_mul(rFm,float32_ln(rFn)));
}
if (fpa11->fType[Fn] == typeSingle &&
dyadic_single[opc_mask_shift]) {
rFn = fpa11->fpreg[Fn].fSingle;
rFd->fSingle = dyadic_single[opc_mask_shift](rFn, rFm);
} else {
return 0;
}
} else {
if (monadic_single[opc_mask_shift]) {
rFd->fSingle = monadic_single[opc_mask_shift](rFm);
} else {
return 0;
}
}
float32 float32_pol(float32 rFn,float32 rFm)
{
return float32_arctan(float32_div(rFn,rFm));
return 1;
}
#endif
......@@ -29,8 +29,8 @@ this code that are retained.
*/
#include "fpa11.h"
#include "milieu.h"
#include "softfloat.h"
//#include "milieu.h"
//#include "softfloat.h"
/*
-------------------------------------------------------------------------------
......@@ -142,12 +142,14 @@ INLINE int16 extractFloat32Exp( float32 a )
Returns the sign bit of the single-precision floating-point value `a'.
-------------------------------------------------------------------------------
*/
#if 0 /* in softfloat.h */
INLINE flag extractFloat32Sign( float32 a )
{
return a>>31;
}
#endif
/*
-------------------------------------------------------------------------------
......@@ -184,9 +186,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)
......@@ -321,12 +323,14 @@ INLINE int16 extractFloat64Exp( float64 a )
Returns the sign bit of the double-precision floating-point value `a'.
-------------------------------------------------------------------------------
*/
#if 0 /* in softfloat.h */
INLINE flag extractFloat64Sign( float64 a )
{
return a>>63;
}
#endif
/*
-------------------------------------------------------------------------------
......
......@@ -40,7 +40,9 @@ floating-point format `floatx80'. If this macro is not defined, the
input or output the `floatx80' type will be defined.
-------------------------------------------------------------------------------
*/
#ifdef CONFIG_FPE_NWFPE_XP
#define FLOATX80
#endif
/*
-------------------------------------------------------------------------------
......@@ -229,4 +231,46 @@ char floatx80_is_signaling_nan( floatx80 );
#endif
static inline flag extractFloat32Sign(float32 a)
{
return a >> 31;
}
static inline flag float32_eq_nocheck(float32 a, float32 b)
{
return (a == b) || ((bits32) ((a | b) << 1) == 0);
}
static inline flag float32_lt_nocheck(float32 a, float32 b)
{
flag aSign, bSign;
aSign = extractFloat32Sign(a);
bSign = extractFloat32Sign(b);
if (aSign != bSign)
return aSign && ((bits32) ((a | b) << 1) != 0);
return (a != b) && (aSign ^ (a < b));
}
static inline flag extractFloat64Sign(float64 a)
{
return a >> 63;
}
static inline flag float64_eq_nocheck(float64 a, float64 b)
{
return (a == b) || ((bits64) ((a | b) << 1) == 0);
}
static inline flag float64_lt_nocheck(float64 a, float64 b)
{
flag aSign, bSign;
aSign = extractFloat64Sign(a);
bSign = extractFloat64Sign(b);
if (aSign != bSign)
return aSign && ((bits64) ((a | b) << 1) != 0);
return (a != b) && (aSign ^ (a < b));
}
#endif
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