Commit 4737ce4e authored by Russell King's avatar Russell King

[ARM] NWFPE 1: Convert instruction decoding from switch() to table.

parent 5a236669
......@@ -23,6 +23,12 @@
#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);
......@@ -35,11 +41,73 @@ float64 float64_arccos(float64 rFm);
float64 float64_pow(float64 rFn,float64 rFm);
float64 float64_pol(float64 rFn,float64 rFm);
static float64 float64_rsf(float64 rFn, float64 rFm)
{
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;
}
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)
{
FPA11 *fpa11 = GET_FPA11();
float64 rFm, rFn;
unsigned int Fd, Fm, Fn, nRc = 1;
float64 rFm, rFd;
unsigned int Fd, Fm, opc;
//printk("DoubleCPDO(0x%08x)\n",opcode);
......@@ -58,24 +126,18 @@ unsigned int DoubleCPDO(const unsigned int opcode)
case typeDouble:
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;
break;
default: return 0;
}
}
opc = opcode & MASK_ARITHMETIC_OPCODE;
if (!MONADIC_INSTRUCTION(opcode))
{
Fn = getFn(opcode);
unsigned int Fn = getFn(opcode);
float64 rFn;
switch (fpa11->fType[Fn])
{
case typeSingle:
......@@ -88,201 +150,31 @@ unsigned int DoubleCPDO(const unsigned int opcode)
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:
if (dyadic_double[opc >> 20])
{
unsigned int *p = (unsigned int*)&rFm;
p[1] ^= 0x80000000;
fpa11->fpreg[Fd].fDouble = rFm;
rFd = dyadic_double[opc >> 20](rFn, rFm);
}
break;
case ABS_CODE:
else
{
unsigned int *p = (unsigned int*)&rFm;
p[1] &= 0x7fffffff;
fpa11->fpreg[Fd].fDouble = rFm;
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:
}
else
{
if (monadic_double[opc >> 20])
{
rFd = monadic_double[opc >> 20](rFm);
}
else
{
nRc = 0;
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)));
}
Fd = getFd(opcode);
fpa11->fpreg[Fd].fDouble = rFd;
fpa11->fType[Fd] = typeDouble;
float64 float64_pol(float64 rFn,float64 rFm)
{
return float64_arctan(float64_div(rFn,rFm));
return 1;
}
#endif
......@@ -35,11 +35,65 @@ floatx80 floatx80_arccos(floatx80 rFm);
floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm);
floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm);
static floatx80 floatx80_rsf(floatx80 rFn, floatx80 rFm)
{
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;
}
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)
{
FPA11 *fpa11 = GET_FPA11();
floatx80 rFm, rFn;
unsigned int Fd, Fm, Fn, nRc = 1;
floatx80 rFm, rFd;
unsigned int Fd, Fm, opc;
//printk("ExtendedCPDO(0x%08x)\n",opcode);
......@@ -68,9 +122,12 @@ unsigned int ExtendedCPDO(const unsigned int opcode)
}
}
opc = opcode & MASK_ARITHMETIC_OPCODE;
if (!MONADIC_INSTRUCTION(opcode))
{
Fn = getFn(opcode);
unsigned int Fn = getFn(opcode);
floatx80 rFn;
switch (fpa11->fType[Fn])
{
case typeSingle:
......@@ -87,187 +144,31 @@ unsigned int ExtendedCPDO(const unsigned int opcode)
default: return 0;
}
}
Fd = getFd(opcode);
switch (opcode & MASK_ARITHMETIC_OPCODE)
if (dyadic_extended[opc >> 20])
{
rFd = dyadic_extended[opc >> 20](rFn, rFm);
}
else
{
return 0;
}
}
else
{
/* 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:
if (monadic_extended[opc >> 20])
{
nRc = 0;
rFd = monadic_extended[opc >> 20](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)));
}
Fd = getFd(opcode);
fpa11->fpreg[Fd].fExtended = rFd;
fpa11->fType[Fd] = typeExtended;
floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm)
{
return floatx80_arctan(floatx80_div(rFn,rFm));
return 1;
}
#endif
......@@ -35,221 +35,108 @@ float32 float32_arccos(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;
return float32_sub(rFm, rFn);
}
#if 0
float32 float32_exp(float32 Fm)
static float32 float32_rdv(float32 rFn, float32 rFm)
{
//series
return float32_div(rFm, rFn);
}
float32 float32_ln(float32 Fm)
static float32 (* const dyadic_single[16])(float32 rFn, float32 rFm) =
{
//series
}
float32 float32_sin(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) =
{
//series
}
[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,
};
float32 float32_arccos(float32 rFm)
unsigned int SingleCPDO(const unsigned int opcode)
{
//return float32_sub(halfPi,float32_arcsin(rFm));
}
FPA11 *fpa11 = GET_FPA11();
float32 rFm, rFd;
unsigned int Fd, Fm, opc;
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 = opcode & MASK_ARITHMETIC_OPCODE;
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 >> 20])
{
rFn = fpa11->fpreg[Fn].fSingle;
rFd = dyadic_single[opc >> 20](rFn, rFm);
}
else
{
return 0;
}
}
else
{
if (monadic_single[opc >> 20])
{
rFd = monadic_single[opc >> 20](rFm);
}
else
{
return 0;
}
}
float32 float32_pol(float32 rFn,float32 rFm)
{
return float32_arctan(float32_div(rFn,rFm));
Fd = getFd(opcode);
fpa11->fpreg[Fd].fSingle = rFd;
fpa11->fType[Fd] = typeSingle;
return 1;
}
#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