Commit 3d0d14f9 authored by Ingo Molnar's avatar Ingo Molnar

x86: lindent arch/i386/math-emu

lindent these files:
                                       errors   lines of code   errors/KLOC
 arch/x86/math-emu/                      2236            9424         237.2
 arch/x86/math-emu/                       128            8706          14.7

no other changes. No code changed:

   text    data     bss     dec     hex filename
   5589802  612739 3833856 10036397         9924ad vmlinux.before
   5589802  612739 3833856 10036397         9924ad vmlinux.after

the intent of this patch is to ease the automated tracking of kernel
code quality - it's just much easier for us to maintain it if every file
in arch/x86 is supposed to be clean.

NOTE: it is a known problem of lindent that it causes some style damage
of its own, but it's a safe tool (well, except for the gcc array range
initializers extension), so we did the bulk of the changes via lindent,
and did the manual fixups in a followup patch.

the resulting math-emu code has been tested by Thomas Gleixner on a real
386 DX CPU as well, and it works fine.
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent a4ec1eff
......@@ -33,7 +33,6 @@
#undef PRINT_MESSAGES
/* */
#if 0
void Un_impl(void)
{
......@@ -42,13 +41,12 @@ void Un_impl(void)
RE_ENTRANT_CHECK_OFF;
/* No need to check access_ok(), we have previously fetched these bytes. */
printk("Unimplemented FPU Opcode at eip=%p : ", (void __user *) address);
if ( FPU_CS == __USER_CS )
{
while ( 1 )
{
printk("Unimplemented FPU Opcode at eip=%p : ", (void __user *)address);
if (FPU_CS == __USER_CS) {
while (1) {
FPU_get_user(byte1, (u_char __user *) address);
if ( (byte1 & 0xf8) == 0xd8 ) break;
if ((byte1 & 0xf8) == 0xd8)
break;
printk("[%02x]", byte1);
address++;
}
......@@ -56,12 +54,11 @@ void Un_impl(void)
FPU_get_user(FPU_modrm, 1 + (u_char __user *) address);
if (FPU_modrm >= 0300)
printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8,
FPU_modrm & 7);
else
printk("/%d\n", (FPU_modrm >> 3) & 7);
}
else
{
} else {
printk("cs selector = %04x\n", FPU_CS);
}
......@@ -72,105 +69,115 @@ void Un_impl(void)
}
#endif /* 0 */
/*
Called for opcodes which are illegal and which are known to result in a
SIGILL with a real 80486.
*/
void FPU_illegal(void)
{
math_abort(FPU_info,SIGILL);
math_abort(FPU_info, SIGILL);
}
void FPU_printall(void)
{
int i;
static const char *tag_desc[] = { "Valid", "Zero", "ERROR", "Empty",
"DeNorm", "Inf", "NaN" };
"DeNorm", "Inf", "NaN"
};
u_char byte1, FPU_modrm;
unsigned long address = FPU_ORIG_EIP;
RE_ENTRANT_CHECK_OFF;
/* No need to check access_ok(), we have previously fetched these bytes. */
printk("At %p:", (void *) address);
if ( FPU_CS == __USER_CS )
{
printk("At %p:", (void *)address);
if (FPU_CS == __USER_CS) {
#define MAX_PRINTED_BYTES 20
for ( i = 0; i < MAX_PRINTED_BYTES; i++ )
{
for (i = 0; i < MAX_PRINTED_BYTES; i++) {
FPU_get_user(byte1, (u_char __user *) address);
if ( (byte1 & 0xf8) == 0xd8 )
{
if ((byte1 & 0xf8) == 0xd8) {
printk(" %02x", byte1);
break;
}
printk(" [%02x]", byte1);
address++;
}
if ( i == MAX_PRINTED_BYTES )
if (i == MAX_PRINTED_BYTES)
printk(" [more..]\n");
else
{
else {
FPU_get_user(FPU_modrm, 1 + (u_char __user *) address);
if (FPU_modrm >= 0300)
printk(" %02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
printk(" %02x (%02x+%d)\n", FPU_modrm,
FPU_modrm & 0xf8, FPU_modrm & 7);
else
printk(" /%d, mod=%d rm=%d\n",
(FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7);
}
(FPU_modrm >> 3) & 7,
(FPU_modrm >> 6) & 3, FPU_modrm & 7);
}
else
{
} else {
printk("%04x\n", FPU_CS);
}
partial_status = status_word();
#ifdef DEBUGGING
if ( partial_status & SW_Backward ) printk("SW: backward compatibility\n");
if ( partial_status & SW_C3 ) printk("SW: condition bit 3\n");
if ( partial_status & SW_C2 ) printk("SW: condition bit 2\n");
if ( partial_status & SW_C1 ) printk("SW: condition bit 1\n");
if ( partial_status & SW_C0 ) printk("SW: condition bit 0\n");
if ( partial_status & SW_Summary ) printk("SW: exception summary\n");
if ( partial_status & SW_Stack_Fault ) printk("SW: stack fault\n");
if ( partial_status & SW_Precision ) printk("SW: loss of precision\n");
if ( partial_status & SW_Underflow ) printk("SW: underflow\n");
if ( partial_status & SW_Overflow ) printk("SW: overflow\n");
if ( partial_status & SW_Zero_Div ) printk("SW: divide by zero\n");
if ( partial_status & SW_Denorm_Op ) printk("SW: denormalized operand\n");
if ( partial_status & SW_Invalid ) printk("SW: invalid operation\n");
if (partial_status & SW_Backward)
printk("SW: backward compatibility\n");
if (partial_status & SW_C3)
printk("SW: condition bit 3\n");
if (partial_status & SW_C2)
printk("SW: condition bit 2\n");
if (partial_status & SW_C1)
printk("SW: condition bit 1\n");
if (partial_status & SW_C0)
printk("SW: condition bit 0\n");
if (partial_status & SW_Summary)
printk("SW: exception summary\n");
if (partial_status & SW_Stack_Fault)
printk("SW: stack fault\n");
if (partial_status & SW_Precision)
printk("SW: loss of precision\n");
if (partial_status & SW_Underflow)
printk("SW: underflow\n");
if (partial_status & SW_Overflow)
printk("SW: overflow\n");
if (partial_status & SW_Zero_Div)
printk("SW: divide by zero\n");
if (partial_status & SW_Denorm_Op)
printk("SW: denormalized operand\n");
if (partial_status & SW_Invalid)
printk("SW: invalid operation\n");
#endif /* DEBUGGING */
printk(" SW: b=%d st=%ld es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n",
partial_status & 0x8000 ? 1 : 0, /* busy */
printk(" SW: b=%d st=%ld es=%d sf=%d cc=%d%d%d%d ef=%d%d%d%d%d%d\n", partial_status & 0x8000 ? 1 : 0, /* busy */
(partial_status & 0x3800) >> 11, /* stack top pointer */
partial_status & 0x80 ? 1 : 0, /* Error summary status */
partial_status & 0x40 ? 1 : 0, /* Stack flag */
partial_status & SW_C3?1:0, partial_status & SW_C2?1:0, /* cc */
partial_status & SW_C1?1:0, partial_status & SW_C0?1:0, /* cc */
partial_status & SW_Precision?1:0, partial_status & SW_Underflow?1:0,
partial_status & SW_Overflow?1:0, partial_status & SW_Zero_Div?1:0,
partial_status & SW_Denorm_Op?1:0, partial_status & SW_Invalid?1:0);
printk(" CW: ic=%d rc=%ld%ld pc=%ld%ld iem=%d ef=%d%d%d%d%d%d\n",
partial_status & SW_C3 ? 1 : 0, partial_status & SW_C2 ? 1 : 0, /* cc */
partial_status & SW_C1 ? 1 : 0, partial_status & SW_C0 ? 1 : 0, /* cc */
partial_status & SW_Precision ? 1 : 0,
partial_status & SW_Underflow ? 1 : 0,
partial_status & SW_Overflow ? 1 : 0,
partial_status & SW_Zero_Div ? 1 : 0,
partial_status & SW_Denorm_Op ? 1 : 0,
partial_status & SW_Invalid ? 1 : 0);
printk(" CW: ic=%d rc=%ld%ld pc=%ld%ld iem=%d ef=%d%d%d%d%d%d\n",
control_word & 0x1000 ? 1 : 0,
(control_word & 0x800) >> 11, (control_word & 0x400) >> 10,
(control_word & 0x200) >> 9, (control_word & 0x100) >> 8,
control_word & 0x80 ? 1 : 0,
control_word & SW_Precision?1:0, control_word & SW_Underflow?1:0,
control_word & SW_Overflow?1:0, control_word & SW_Zero_Div?1:0,
control_word & SW_Denorm_Op?1:0, control_word & SW_Invalid?1:0);
for ( i = 0; i < 8; i++ )
{
control_word & SW_Precision ? 1 : 0,
control_word & SW_Underflow ? 1 : 0,
control_word & SW_Overflow ? 1 : 0,
control_word & SW_Zero_Div ? 1 : 0,
control_word & SW_Denorm_Op ? 1 : 0,
control_word & SW_Invalid ? 1 : 0);
for (i = 0; i < 8; i++) {
FPU_REG *r = &st(i);
u_char tagi = FPU_gettagi(i);
switch (tagi)
{
switch (tagi) {
case TAG_Empty:
continue;
break;
......@@ -187,11 +194,12 @@ printk(" CW: ic=%d rc=%ld%ld pc=%ld%ld iem=%d ef=%d%d%d%d%d%d\n",
exponent(r) - EXP_BIAS + 1);
break;
default:
printk("Whoops! Error in errors.c: tag%d is %d ", i, tagi);
printk("Whoops! Error in errors.c: tag%d is %d ", i,
tagi);
continue;
break;
}
printk("%s\n", tag_desc[(int) (unsigned) tagi]);
printk("%s\n", tag_desc[(int)(unsigned)tagi]);
}
RE_ENTRANT_CHECK_ON;
......@@ -202,16 +210,17 @@ static struct {
int type;
const char *name;
} exception_names[] = {
{ EX_StackOver, "stack overflow" },
{ EX_StackUnder, "stack underflow" },
{ EX_Precision, "loss of precision" },
{ EX_Underflow, "underflow" },
{ EX_Overflow, "overflow" },
{ EX_ZeroDiv, "divide by zero" },
{ EX_Denormal, "denormalized operand" },
{ EX_Invalid, "invalid operation" },
{ EX_INTERNAL, "INTERNAL BUG in "FPU_VERSION },
{ 0, NULL }
{
EX_StackOver, "stack overflow"}, {
EX_StackUnder, "stack underflow"}, {
EX_Precision, "loss of precision"}, {
EX_Underflow, "underflow"}, {
EX_Overflow, "overflow"}, {
EX_ZeroDiv, "divide by zero"}, {
EX_Denormal, "denormalized operand"}, {
EX_Invalid, "invalid operation"}, {
EX_INTERNAL, "INTERNAL BUG in " FPU_VERSION}, {
0, NULL}
};
/*
......@@ -298,25 +307,21 @@ asmlinkage void FPU_exception(int n)
int i, int_type;
int_type = 0; /* Needed only to stop compiler warnings */
if ( n & EX_INTERNAL )
{
if (n & EX_INTERNAL) {
int_type = n - EX_INTERNAL;
n = EX_INTERNAL;
/* Set lots of exception bits! */
partial_status |= (SW_Exc_Mask | SW_Summary | SW_Backward);
}
else
{
} else {
/* Extract only the bits which we use to set the status word */
n &= (SW_Exc_Mask);
/* Set the corresponding exception bit */
partial_status |= n;
/* Set summary bits iff exception isn't masked */
if ( partial_status & ~control_word & CW_Exceptions )
if (partial_status & ~control_word & CW_Exceptions)
partial_status |= (SW_Summary | SW_Backward);
if ( n & (SW_Stack_Fault | EX_Precision) )
{
if ( !(n & SW_C1) )
if (n & (SW_Stack_Fault | EX_Precision)) {
if (!(n & SW_C1))
/* This bit distinguishes over- from underflow for a stack fault,
and roundup from round-down for precision loss. */
partial_status &= ~SW_C1;
......@@ -324,30 +329,28 @@ asmlinkage void FPU_exception(int n)
}
RE_ENTRANT_CHECK_OFF;
if ( (~control_word & n & CW_Exceptions) || (n == EX_INTERNAL) )
{
if ((~control_word & n & CW_Exceptions) || (n == EX_INTERNAL)) {
#ifdef PRINT_MESSAGES
/* My message from the sponsor */
printk(FPU_VERSION" "__DATE__" (C) W. Metzenthen.\n");
printk(FPU_VERSION " " __DATE__ " (C) W. Metzenthen.\n");
#endif /* PRINT_MESSAGES */
/* Get a name string for error reporting */
for (i=0; exception_names[i].type; i++)
if ( (exception_names[i].type & n) == exception_names[i].type )
for (i = 0; exception_names[i].type; i++)
if ((exception_names[i].type & n) ==
exception_names[i].type)
break;
if (exception_names[i].type)
{
if (exception_names[i].type) {
#ifdef PRINT_MESSAGES
printk("FP Exception: %s!\n", exception_names[i].name);
#endif /* PRINT_MESSAGES */
}
else
} else
printk("FPU emulator: Unknown Exception: 0x%04x!\n", n);
if ( n == EX_INTERNAL )
{
printk("FPU emulator: Internal error type 0x%04x\n", int_type);
if (n == EX_INTERNAL) {
printk("FPU emulator: Internal error type 0x%04x\n",
int_type);
FPU_printall();
}
#ifdef PRINT_MESSAGES
......@@ -364,15 +367,14 @@ asmlinkage void FPU_exception(int n)
RE_ENTRANT_CHECK_ON;
#ifdef __DEBUG__
math_abort(FPU_info,SIGFPE);
math_abort(FPU_info, SIGFPE);
#endif /* __DEBUG__ */
}
/* Real operation attempted on a NaN. */
/* Returns < 0 if the exception is unmasked */
int real_1op_NaN(FPU_REG *a)
int real_1op_NaN(FPU_REG * a)
{
int signalling, isNaN;
......@@ -382,26 +384,22 @@ int real_1op_NaN(FPU_REG *a)
differ) is chosen to reproduce 80486 behaviour */
signalling = isNaN && !(a->sigh & 0x40000000);
if ( !signalling )
{
if ( !isNaN ) /* pseudo-NaN, or other unsupported? */
{
if ( control_word & CW_Invalid )
{
if (!signalling) {
if (!isNaN) { /* pseudo-NaN, or other unsupported? */
if (control_word & CW_Invalid) {
/* Masked response */
reg_copy(&CONST_QNaN, a);
}
EXCEPTION(EX_Invalid);
return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
return (!(control_word & CW_Invalid) ? FPU_Exception :
0) | TAG_Special;
}
return TAG_Special;
}
if ( control_word & CW_Invalid )
{
if (control_word & CW_Invalid) {
/* The masked response */
if ( !(a->sigh & 0x80000000) ) /* pseudo-NaN ? */
{
if (!(a->sigh & 0x80000000)) { /* pseudo-NaN ? */
reg_copy(&CONST_QNaN, a);
}
/* ensure a Quiet NaN */
......@@ -413,12 +411,10 @@ int real_1op_NaN(FPU_REG *a)
return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
}
/* Real operation attempted on two operands, one a NaN. */
/* Returns < 0 if the exception is unmasked */
int real_2op_NaN(FPU_REG const *b, u_char tagb,
int deststnr,
FPU_REG const *defaultNaN)
int deststnr, FPU_REG const *defaultNaN)
{
FPU_REG *dest = &st(deststnr);
FPU_REG const *a = dest;
......@@ -426,49 +422,43 @@ int real_2op_NaN(FPU_REG const *b, u_char tagb,
FPU_REG const *x;
int signalling, unsupported;
if ( taga == TAG_Special )
if (taga == TAG_Special)
taga = FPU_Special(a);
if ( tagb == TAG_Special )
if (tagb == TAG_Special)
tagb = FPU_Special(b);
/* TW_NaN is also used for unsupported data types. */
unsupported = ((taga == TW_NaN)
&& !((exponent(a) == EXP_OVER) && (a->sigh & 0x80000000)))
&& !((exponent(a) == EXP_OVER)
&& (a->sigh & 0x80000000)))
|| ((tagb == TW_NaN)
&& !((exponent(b) == EXP_OVER) && (b->sigh & 0x80000000)));
if ( unsupported )
{
if ( control_word & CW_Invalid )
{
if (unsupported) {
if (control_word & CW_Invalid) {
/* Masked response */
FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr);
}
EXCEPTION(EX_Invalid);
return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
return (!(control_word & CW_Invalid) ? FPU_Exception : 0) |
TAG_Special;
}
if (taga == TW_NaN)
{
if (taga == TW_NaN) {
x = a;
if (tagb == TW_NaN)
{
if (tagb == TW_NaN) {
signalling = !(a->sigh & b->sigh & 0x40000000);
if ( significand(b) > significand(a) )
if (significand(b) > significand(a))
x = b;
else if ( significand(b) == significand(a) )
{
else if (significand(b) == significand(a)) {
/* The default result for the case of two "equal" NaNs (signs may
differ) is chosen to reproduce 80486 behaviour */
x = defaultNaN;
}
}
else
{
} else {
/* return the quiet version of the NaN in a */
signalling = !(a->sigh & 0x40000000);
}
}
else
} else
#ifdef PARANOID
if (tagb == TW_NaN)
#endif /* PARANOID */
......@@ -477,25 +467,23 @@ int real_2op_NaN(FPU_REG const *b, u_char tagb,
x = b;
}
#ifdef PARANOID
else
{
else {
signalling = 0;
EXCEPTION(EX_INTERNAL|0x113);
EXCEPTION(EX_INTERNAL | 0x113);
x = &CONST_QNaN;
}
#endif /* PARANOID */
if ( (!signalling) || (control_word & CW_Invalid) )
{
if ( ! x )
if ((!signalling) || (control_word & CW_Invalid)) {
if (!x)
x = b;
if ( !(x->sigh & 0x80000000) ) /* pseudo-NaN ? */
if (!(x->sigh & 0x80000000)) /* pseudo-NaN ? */
x = &CONST_QNaN;
FPU_copy_to_regi(x, TAG_Special, deststnr);
if ( !signalling )
if (!signalling)
return TAG_Special;
/* ensure a Quiet NaN */
......@@ -507,7 +495,6 @@ int real_2op_NaN(FPU_REG const *b, u_char tagb,
return (!(control_word & CW_Invalid) ? FPU_Exception : 0) | TAG_Special;
}
/* Invalid arith operation on Valid registers */
/* Returns < 0 if the exception is unmasked */
asmlinkage int arith_invalid(int deststnr)
......@@ -515,8 +502,7 @@ asmlinkage int arith_invalid(int deststnr)
EXCEPTION(EX_Invalid);
if ( control_word & CW_Invalid )
{
if (control_word & CW_Invalid) {
/* The masked response */
FPU_copy_to_regi(&CONST_QNaN, TAG_Special, deststnr);
}
......@@ -525,15 +511,13 @@ asmlinkage int arith_invalid(int deststnr)
}
/* Divide a finite number by zero */
asmlinkage int FPU_divide_by_zero(int deststnr, u_char sign)
{
FPU_REG *dest = &st(deststnr);
int tag = TAG_Valid;
if ( control_word & CW_ZeroDiv )
{
if (control_word & CW_ZeroDiv) {
/* The masked response */
FPU_copy_to_regi(&CONST_INF, TAG_Special, deststnr);
setsign(dest, sign);
......@@ -546,82 +530,65 @@ asmlinkage int FPU_divide_by_zero(int deststnr, u_char sign)
}
/* This may be called often, so keep it lean */
int set_precision_flag(int flags)
{
if ( control_word & CW_Precision )
{
if (control_word & CW_Precision) {
partial_status &= ~(SW_C1 & flags);
partial_status |= flags; /* The masked response */
return 0;
}
else
{
} else {
EXCEPTION(flags);
return 1;
}
}
/* This may be called often, so keep it lean */
asmlinkage void set_precision_flag_up(void)
{
if ( control_word & CW_Precision )
if (control_word & CW_Precision)
partial_status |= (SW_Precision | SW_C1); /* The masked response */
else
EXCEPTION(EX_Precision | SW_C1);
}
/* This may be called often, so keep it lean */
asmlinkage void set_precision_flag_down(void)
{
if ( control_word & CW_Precision )
{ /* The masked response */
if (control_word & CW_Precision) { /* The masked response */
partial_status &= ~SW_C1;
partial_status |= SW_Precision;
}
else
} else
EXCEPTION(EX_Precision);
}
asmlinkage int denormal_operand(void)
{
if ( control_word & CW_Denormal )
{ /* The masked response */
if (control_word & CW_Denormal) { /* The masked response */
partial_status |= SW_Denorm_Op;
return TAG_Special;
}
else
{
} else {
EXCEPTION(EX_Denormal);
return TAG_Special | FPU_Exception;
}
}
asmlinkage int arith_overflow(FPU_REG *dest)
asmlinkage int arith_overflow(FPU_REG * dest)
{
int tag = TAG_Valid;
if ( control_word & CW_Overflow )
{
if (control_word & CW_Overflow) {
/* The masked response */
/* ###### The response here depends upon the rounding mode */
reg_copy(&CONST_INF, dest);
tag = TAG_Special;
}
else
{
} else {
/* Subtract the magic number from the exponent */
addexponent(dest, (-3 * (1 << 13)));
}
EXCEPTION(EX_Overflow);
if ( control_word & CW_Overflow )
{
if (control_word & CW_Overflow) {
/* The overflow exception is masked. */
/* By definition, precision is lost.
The roundup bit (C1) is also set because we have
......@@ -634,34 +601,26 @@ asmlinkage int arith_overflow(FPU_REG *dest)
}
asmlinkage int arith_underflow(FPU_REG *dest)
asmlinkage int arith_underflow(FPU_REG * dest)
{
int tag = TAG_Valid;
if ( control_word & CW_Underflow )
{
if (control_word & CW_Underflow) {
/* The masked response */
if ( exponent16(dest) <= EXP_UNDER - 63 )
{
if (exponent16(dest) <= EXP_UNDER - 63) {
reg_copy(&CONST_Z, dest);
partial_status &= ~SW_C1; /* Round down. */
tag = TAG_Zero;
}
else
{
} else {
stdexp(dest);
}
}
else
{
} else {
/* Add the magic number to the exponent. */
addexponent(dest, (3 * (1 << 13)) + EXTENDED_Ebias);
}
EXCEPTION(EX_Underflow);
if ( control_word & CW_Underflow )
{
if (control_word & CW_Underflow) {
/* The underflow exception is masked. */
EXCEPTION(EX_Precision);
return tag;
......@@ -671,12 +630,10 @@ asmlinkage int arith_underflow(FPU_REG *dest)
}
void FPU_stack_overflow(void)
{
if ( control_word & CW_Invalid )
{
if (control_word & CW_Invalid) {
/* The masked response */
top--;
FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
......@@ -688,12 +645,10 @@ void FPU_stack_overflow(void)
}
void FPU_stack_underflow(void)
{
if ( control_word & CW_Invalid )
{
if (control_word & CW_Invalid) {
/* The masked response */
FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
}
......@@ -704,12 +659,10 @@ void FPU_stack_underflow(void)
}
void FPU_stack_underflow_i(int i)
{
if ( control_word & CW_Invalid )
{
if (control_word & CW_Invalid) {
/* The masked response */
FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i);
}
......@@ -720,12 +673,10 @@ void FPU_stack_underflow_i(int i)
}
void FPU_stack_underflow_pop(int i)
{
if ( control_word & CW_Invalid )
{
if (control_word & CW_Invalid) {
/* The masked response */
FPU_copy_to_regi(&CONST_QNaN, TAG_Special, i);
FPU_pop();
......@@ -736,4 +687,3 @@ void FPU_stack_underflow_pop(int i)
return;
}
......@@ -9,7 +9,6 @@
#ifndef _EXCEPTION_H_
#define _EXCEPTION_H_
#ifdef __ASSEMBLY__
#define Const_(x) $##x
#else
......@@ -34,11 +33,9 @@
#define EX_Denormal Const_(0x0002) /* denormalized operand */
#define EX_Invalid Const_(0x0001) /* invalid operation */
#define PRECISION_LOST_UP Const_((EX_Precision | SW_C1))
#define PRECISION_LOST_DOWN Const_(EX_Precision)
#ifndef __ASSEMBLY__
#ifdef DEBUG
......
......@@ -15,7 +15,6 @@
#include "control_w.h"
#include "status_w.h"
void fadd__(void)
{
/* fadd st,st(i) */
......@@ -24,7 +23,6 @@ void fadd__(void)
FPU_add(&st(i), FPU_gettagi(i), 0, control_word);
}
void fmul__(void)
{
/* fmul st,st(i) */
......@@ -33,8 +31,6 @@ void fmul__(void)
FPU_mul(&st(i), FPU_gettagi(i), 0, control_word);
}
void fsub__(void)
{
/* fsub st,st(i) */
......@@ -42,7 +38,6 @@ void fsub__(void)
FPU_sub(0, FPU_rm, control_word);
}
void fsubr_(void)
{
/* fsubr st,st(i) */
......@@ -50,7 +45,6 @@ void fsubr_(void)
FPU_sub(REV, FPU_rm, control_word);
}
void fdiv__(void)
{
/* fdiv st,st(i) */
......@@ -58,7 +52,6 @@ void fdiv__(void)
FPU_div(0, FPU_rm, control_word);
}
void fdivr_(void)
{
/* fdivr st,st(i) */
......@@ -66,8 +59,6 @@ void fdivr_(void)
FPU_div(REV, FPU_rm, control_word);
}
void fadd_i(void)
{
/* fadd st(i),st */
......@@ -76,7 +67,6 @@ void fadd_i(void)
FPU_add(&st(i), FPU_gettagi(i), i, control_word);
}
void fmul_i(void)
{
/* fmul st(i),st */
......@@ -84,7 +74,6 @@ void fmul_i(void)
FPU_mul(&st(0), FPU_gettag0(), FPU_rm, control_word);
}
void fsubri(void)
{
/* fsubr st(i),st */
......@@ -92,15 +81,13 @@ void fsubri(void)
FPU_sub(DEST_RM, FPU_rm, control_word);
}
void fsub_i(void)
{
/* fsub st(i),st */
clear_C1();
FPU_sub(REV|DEST_RM, FPU_rm, control_word);
FPU_sub(REV | DEST_RM, FPU_rm, control_word);
}
void fdivri(void)
{
/* fdivr st(i),st */
......@@ -108,67 +95,58 @@ void fdivri(void)
FPU_div(DEST_RM, FPU_rm, control_word);
}
void fdiv_i(void)
{
/* fdiv st(i),st */
clear_C1();
FPU_div(REV|DEST_RM, FPU_rm, control_word);
FPU_div(REV | DEST_RM, FPU_rm, control_word);
}
void faddp_(void)
{
/* faddp st(i),st */
int i = FPU_rm;
clear_C1();
if ( FPU_add(&st(i), FPU_gettagi(i), i, control_word) >= 0 )
if (FPU_add(&st(i), FPU_gettagi(i), i, control_word) >= 0)
FPU_pop();
}
void fmulp_(void)
{
/* fmulp st(i),st */
clear_C1();
if ( FPU_mul(&st(0), FPU_gettag0(), FPU_rm, control_word) >= 0 )
if (FPU_mul(&st(0), FPU_gettag0(), FPU_rm, control_word) >= 0)
FPU_pop();
}
void fsubrp(void)
{
/* fsubrp st(i),st */
clear_C1();
if ( FPU_sub(DEST_RM, FPU_rm, control_word) >= 0 )
if (FPU_sub(DEST_RM, FPU_rm, control_word) >= 0)
FPU_pop();
}
void fsubp_(void)
{
/* fsubp st(i),st */
clear_C1();
if ( FPU_sub(REV|DEST_RM, FPU_rm, control_word) >= 0 )
if (FPU_sub(REV | DEST_RM, FPU_rm, control_word) >= 0)
FPU_pop();
}
void fdivrp(void)
{
/* fdivrp st(i),st */
clear_C1();
if ( FPU_div(DEST_RM, FPU_rm, control_word) >= 0 )
if (FPU_div(DEST_RM, FPU_rm, control_word) >= 0)
FPU_pop();
}
void fdivp_(void)
{
/* fdivp st(i),st */
clear_C1();
if ( FPU_div(REV|DEST_RM, FPU_rm, control_word) >= 0 )
if (FPU_div(REV | DEST_RM, FPU_rm, control_word) >= 0)
FPU_pop();
}
......@@ -14,7 +14,6 @@
#define EXCEPTION FPU_exception
#define PARAM1 8(%ebp)
#define PARAM2 12(%ebp)
#define PARAM3 16(%ebp)
......
......@@ -16,15 +16,15 @@
#include "status_w.h"
#include "control_w.h"
static void fnop(void)
{
}
static void fclex(void)
{
partial_status &= ~(SW_Backward|SW_Summary|SW_Stack_Fault|SW_Precision|
SW_Underflow|SW_Overflow|SW_Zero_Div|SW_Denorm_Op|
partial_status &=
~(SW_Backward | SW_Summary | SW_Stack_Fault | SW_Precision |
SW_Underflow | SW_Overflow | SW_Zero_Div | SW_Denorm_Op |
SW_Invalid);
no_ip_update = 1;
}
......@@ -60,13 +60,12 @@ static FUNC const finit_table[] = {
void finit_(void)
{
(finit_table[FPU_rm])();
(finit_table[FPU_rm]) ();
}
static void fstsw_ax(void)
{
*(short *) &FPU_EAX = status_word();
*(short *)&FPU_EAX = status_word();
no_ip_update = 1;
}
......@@ -77,10 +76,9 @@ static FUNC const fstsw_table[] = {
void fstsw_(void)
{
(fstsw_table[FPU_rm])();
(fstsw_table[FPU_rm]) ();
}
static FUNC const fp_nop_table[] = {
fnop, FPU_illegal, FPU_illegal, FPU_illegal,
FPU_illegal, FPU_illegal, FPU_illegal, FPU_illegal
......@@ -88,42 +86,37 @@ static FUNC const fp_nop_table[] = {
void fp_nop(void)
{
(fp_nop_table[FPU_rm])();
(fp_nop_table[FPU_rm]) ();
}
void fld_i_(void)
{
FPU_REG *st_new_ptr;
int i;
u_char tag;
if ( STACK_OVERFLOW )
{ FPU_stack_overflow(); return; }
if (STACK_OVERFLOW) {
FPU_stack_overflow();
return;
}
/* fld st(i) */
i = FPU_rm;
if ( NOT_EMPTY(i) )
{
if (NOT_EMPTY(i)) {
reg_copy(&st(i), st_new_ptr);
tag = FPU_gettagi(i);
push();
FPU_settag0(tag);
}
else
{
if ( control_word & CW_Invalid )
{
} else {
if (control_word & CW_Invalid) {
/* The masked response */
FPU_stack_underflow();
}
else
} else
EXCEPTION(EX_StackUnder);
}
}
void fxch_i(void)
{
/* fxch st(i) */
......@@ -132,29 +125,24 @@ void fxch_i(void)
FPU_REG *st0_ptr = &st(0), *sti_ptr = &st(i);
long tag_word = fpu_tag_word;
int regnr = top & 7, regnri = ((regnr + i) & 7);
u_char st0_tag = (tag_word >> (regnr*2)) & 3;
u_char sti_tag = (tag_word >> (regnri*2)) & 3;
u_char st0_tag = (tag_word >> (regnr * 2)) & 3;
u_char sti_tag = (tag_word >> (regnri * 2)) & 3;
if ( st0_tag == TAG_Empty )
{
if ( sti_tag == TAG_Empty )
{
if (st0_tag == TAG_Empty) {
if (sti_tag == TAG_Empty) {
FPU_stack_underflow();
FPU_stack_underflow_i(i);
return;
}
if ( control_word & CW_Invalid )
{
if (control_word & CW_Invalid) {
/* Masked response */
FPU_copy_to_reg0(sti_ptr, sti_tag);
}
FPU_stack_underflow_i(i);
return;
}
if ( sti_tag == TAG_Empty )
{
if ( control_word & CW_Invalid )
{
if (sti_tag == TAG_Empty) {
if (control_word & CW_Invalid) {
/* Masked response */
FPU_copy_to_regi(st0_ptr, st0_tag, i);
}
......@@ -167,19 +155,17 @@ void fxch_i(void)
reg_copy(sti_ptr, st0_ptr);
reg_copy(&t, sti_ptr);
tag_word &= ~(3 << (regnr*2)) & ~(3 << (regnri*2));
tag_word |= (sti_tag << (regnr*2)) | (st0_tag << (regnri*2));
tag_word &= ~(3 << (regnr * 2)) & ~(3 << (regnri * 2));
tag_word |= (sti_tag << (regnr * 2)) | (st0_tag << (regnri * 2));
fpu_tag_word = tag_word;
}
void ffree_(void)
{
/* ffree st(i) */
FPU_settagi(FPU_rm, TAG_Empty);
}
void ffreep(void)
{
/* ffree st(i) + pop - unofficial code */
......@@ -187,18 +173,15 @@ void ffreep(void)
FPU_pop();
}
void fst_i_(void)
{
/* fst st(i) */
FPU_copy_to_regi(&st(0), FPU_gettag0(), FPU_rm);
}
void fstp_i(void)
{
/* fstp st(i) */
FPU_copy_to_regi(&st(0), FPU_gettag0(), FPU_rm);
FPU_pop();
}
......@@ -7,7 +7,6 @@
| |
+---------------------------------------------------------------------------*/
#ifndef _FPU_EMU_H_
#define _FPU_EMU_H_
......@@ -44,7 +43,6 @@
#define SIGN_Positive Const(0)
#define SIGN_Negative Const(0x8000)
/* Keep the order TAG_Valid, TAG_Zero, TW_Denormal */
/* The following fold to 2 (Special) in the Tag Word */
#define TW_Denormal Const(4) /* De-normal */
......@@ -69,7 +67,6 @@
#define FPU_Exception Const(0x80000000) /* Added to tag returns. */
#ifndef __ASSEMBLY__
#include "fpu_system.h"
......@@ -123,14 +120,17 @@ struct fpu__reg {
short exp;
};
typedef void (*FUNC)(void);
typedef void (*FUNC) (void);
typedef struct fpu__reg FPU_REG;
typedef void (*FUNC_ST0)(FPU_REG *st0_ptr, u_char st0_tag);
typedef struct { u_char address_size, operand_size, segment; }
overrides;
typedef void (*FUNC_ST0) (FPU_REG * st0_ptr, u_char st0_tag);
typedef struct {
u_char address_size, operand_size, segment;
} overrides;
/* This structure is 32 bits: */
typedef struct { overrides override;
u_char default_mode; } fpu_addr_modes;
typedef struct {
overrides override;
u_char default_mode;
} fpu_addr_modes;
/* PROTECTED has a restricted meaning in the emulator; it is used
to signal that the emulator needs to do special things to ensure
that protection is respected in a segmented model. */
......@@ -166,7 +166,7 @@ extern u_char const data_sizes_16[32];
#define signpositive(a) ( (signbyte(a) & 0x80) == 0 )
#define signnegative(a) (signbyte(a) & 0x80)
static inline void reg_copy(FPU_REG const *x, FPU_REG *y)
static inline void reg_copy(FPU_REG const *x, FPU_REG * y)
{
*(short *)&(y->exp) = *(const short *)&(x->exp);
*(long long *)&(y->sigl) = *(const long long *)&(x->sigl);
......@@ -184,29 +184,28 @@ static inline void reg_copy(FPU_REG const *x, FPU_REG *y)
#define significand(x) ( ((unsigned long long *)&((x)->sigl))[0] )
/*----- Prototypes for functions written in assembler -----*/
/* extern void reg_move(FPU_REG *a, FPU_REG *b); */
asmlinkage int FPU_normalize(FPU_REG *x);
asmlinkage int FPU_normalize_nuo(FPU_REG *x);
asmlinkage int FPU_normalize(FPU_REG * x);
asmlinkage int FPU_normalize_nuo(FPU_REG * x);
asmlinkage int FPU_u_sub(FPU_REG const *arg1, FPU_REG const *arg2,
FPU_REG *answ, unsigned int control_w, u_char sign,
FPU_REG * answ, unsigned int control_w, u_char sign,
int expa, int expb);
asmlinkage int FPU_u_mul(FPU_REG const *arg1, FPU_REG const *arg2,
FPU_REG *answ, unsigned int control_w, u_char sign,
FPU_REG * answ, unsigned int control_w, u_char sign,
int expon);
asmlinkage int FPU_u_div(FPU_REG const *arg1, FPU_REG const *arg2,
FPU_REG *answ, unsigned int control_w, u_char sign);
FPU_REG * answ, unsigned int control_w, u_char sign);
asmlinkage int FPU_u_add(FPU_REG const *arg1, FPU_REG const *arg2,
FPU_REG *answ, unsigned int control_w, u_char sign,
FPU_REG * answ, unsigned int control_w, u_char sign,
int expa, int expb);
asmlinkage int wm_sqrt(FPU_REG *n, int dummy1, int dummy2,
asmlinkage int wm_sqrt(FPU_REG * n, int dummy1, int dummy2,
unsigned int control_w, u_char sign);
asmlinkage unsigned FPU_shrx(void *l, unsigned x);
asmlinkage unsigned FPU_shrxs(void *v, unsigned x);
asmlinkage unsigned long FPU_div_small(unsigned long long *x, unsigned long y);
asmlinkage int FPU_round(FPU_REG *arg, unsigned int extent, int dummy,
asmlinkage int FPU_round(FPU_REG * arg, unsigned int extent, int dummy,
unsigned int control_w, u_char sign);
#ifndef MAKING_PROTO
......
......@@ -81,7 +81,6 @@ static FUNC const st_instr_table[64] = {
#endif /* NO_UNDOC_CODE */
#define _NONE_ 0 /* Take no special action */
#define _REG0_ 1 /* Need to check for not empty st(0) */
#define _REGI_ 2 /* Need to check for not empty st(0) and st(rm) */
......@@ -123,13 +122,12 @@ static u_char const type_table[64] = {
#endif /* NO_UNDOC_CODE */
#ifdef RE_ENTRANT_CHECKING
u_char emulating=0;
u_char emulating = 0;
#endif /* RE_ENTRANT_CHECKING */
static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
overrides *override);
static int valid_prefix(u_char * Byte, u_char __user ** fpu_eip,
overrides * override);
asmlinkage void math_emulate(long arg)
{
......@@ -148,15 +146,13 @@ asmlinkage void math_emulate(long arg)
struct desc_struct code_descriptor;
#ifdef RE_ENTRANT_CHECKING
if ( emulating )
{
if (emulating) {
printk("ERROR: wm-FPU-emu is not RE-ENTRANT!\n");
}
RE_ENTRANT_CHECK_ON;
#endif /* RE_ENTRANT_CHECKING */
if (!used_math())
{
if (!used_math()) {
finit();
set_used_math();
}
......@@ -165,27 +161,19 @@ asmlinkage void math_emulate(long arg)
FPU_ORIG_EIP = FPU_EIP;
if ( (FPU_EFLAGS & 0x00020000) != 0 )
{
if ((FPU_EFLAGS & 0x00020000) != 0) {
/* Virtual 8086 mode */
addr_modes.default_mode = VM86;
FPU_EIP += code_base = FPU_CS << 4;
code_limit = code_base + 0xffff; /* Assumes code_base <= 0xffff0000 */
}
else if ( FPU_CS == __USER_CS && FPU_DS == __USER_DS )
{
} else if (FPU_CS == __USER_CS && FPU_DS == __USER_DS) {
addr_modes.default_mode = 0;
}
else if ( FPU_CS == __KERNEL_CS )
{
printk("math_emulate: %04x:%08lx\n",FPU_CS,FPU_EIP);
} else if (FPU_CS == __KERNEL_CS) {
printk("math_emulate: %04x:%08lx\n", FPU_CS, FPU_EIP);
panic("Math emulation needed in kernel");
}
else
{
} else {
if ( (FPU_CS & 4) != 4 ) /* Must be in the LDT */
{
if ((FPU_CS & 4) != 4) { /* Must be in the LDT */
/* Can only handle segmented addressing via the LDT
for now, and it must be 16 bit */
printk("FPU emulator: Unsupported addressing mode\n");
......@@ -193,66 +181,62 @@ asmlinkage void math_emulate(long arg)
}
code_descriptor = LDT_DESCRIPTOR(FPU_CS);
if ( SEG_D_SIZE(code_descriptor) )
{
if (SEG_D_SIZE(code_descriptor)) {
/* The above test may be wrong, the book is not clear */
/* Segmented 32 bit protected mode */
addr_modes.default_mode = SEG32;
}
else
{
} else {
/* 16 bit protected mode */
addr_modes.default_mode = PM16;
}
FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor);
code_limit = code_base
+ (SEG_LIMIT(code_descriptor)+1) * SEG_GRANULARITY(code_descriptor)
+ (SEG_LIMIT(code_descriptor) +
1) * SEG_GRANULARITY(code_descriptor)
- 1;
if ( code_limit < code_base ) code_limit = 0xffffffff;
if (code_limit < code_base)
code_limit = 0xffffffff;
}
FPU_lookahead = 1;
if (current->ptrace & PT_PTRACED)
FPU_lookahead = 0;
if ( !valid_prefix(&byte1, (u_char __user **)&FPU_EIP,
&addr_modes.override) )
{
if (!valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
&addr_modes.override)) {
RE_ENTRANT_CHECK_OFF;
printk("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
printk
("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
"FPU emulator: self-modifying code! (emulation impossible)\n",
byte1);
RE_ENTRANT_CHECK_ON;
EXCEPTION(EX_INTERNAL|0x126);
math_abort(FPU_info,SIGILL);
EXCEPTION(EX_INTERNAL | 0x126);
math_abort(FPU_info, SIGILL);
}
do_another_FPU_instruction:
do_another_FPU_instruction:
no_ip_update = 0;
FPU_EIP++; /* We have fetched the prefix and first code bytes. */
if ( addr_modes.default_mode )
{
if (addr_modes.default_mode) {
/* This checks for the minimum instruction bytes.
We also need to check any extra (address mode) code access. */
if ( FPU_EIP > code_limit )
math_abort(FPU_info,SIGSEGV);
if (FPU_EIP > code_limit)
math_abort(FPU_info, SIGSEGV);
}
if ( (byte1 & 0xf8) != 0xd8 )
{
if ( byte1 == FWAIT_OPCODE )
{
if ((byte1 & 0xf8) != 0xd8) {
if (byte1 == FWAIT_OPCODE) {
if (partial_status & SW_Summary)
goto do_the_FPU_interrupt;
else
goto FPU_fwait_done;
}
#ifdef PARANOID
EXCEPTION(EX_INTERNAL|0x128);
math_abort(FPU_info,SIGILL);
EXCEPTION(EX_INTERNAL | 0x128);
math_abort(FPU_info, SIGILL);
#endif /* PARANOID */
}
......@@ -262,8 +246,7 @@ asmlinkage void math_emulate(long arg)
RE_ENTRANT_CHECK_ON;
FPU_EIP++;
if (partial_status & SW_Summary)
{
if (partial_status & SW_Summary) {
/* Ignore the error for now if the current instruction is a no-wait
control instruction */
/* The 80486 manual contradicts itself on this topic,
......@@ -271,11 +254,10 @@ asmlinkage void math_emulate(long arg)
fninit, fnstenv, fnsave, fnstsw, fnstenv, fnclex.
*/
code = (FPU_modrm << 8) | byte1;
if ( ! ( (((code & 0xf803) == 0xe003) || /* fnclex, fninit, fnstsw */
if (!((((code & 0xf803) == 0xe003) || /* fnclex, fninit, fnstsw */
(((code & 0x3003) == 0x3001) && /* fnsave, fnstcw, fnstenv,
fnstsw */
((code & 0xc000) != 0xc000))) ) )
{
((code & 0xc000) != 0xc000))))) {
/*
* We need to simulate the action of the kernel to FPU
* interrupts here.
......@@ -298,62 +280,69 @@ asmlinkage void math_emulate(long arg)
FPU_rm = FPU_modrm & 7;
if ( FPU_modrm < 0300 )
{
if (FPU_modrm < 0300) {
/* All of these instructions use the mod/rm byte to get a data address */
if ( (addr_modes.default_mode & SIXTEEN)
^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX) )
data_address = FPU_get_address_16(FPU_modrm, &FPU_EIP, &data_sel_off,
addr_modes);
if ((addr_modes.default_mode & SIXTEEN)
^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX))
data_address =
FPU_get_address_16(FPU_modrm, &FPU_EIP,
&data_sel_off, addr_modes);
else
data_address = FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off,
data_address =
FPU_get_address(FPU_modrm, &FPU_EIP, &data_sel_off,
addr_modes);
if ( addr_modes.default_mode )
{
if ( FPU_EIP-1 > code_limit )
math_abort(FPU_info,SIGSEGV);
if (addr_modes.default_mode) {
if (FPU_EIP - 1 > code_limit)
math_abort(FPU_info, SIGSEGV);
}
if ( !(byte1 & 1) )
{
if (!(byte1 & 1)) {
unsigned short status1 = partial_status;
st0_ptr = &st(0);
st0_tag = FPU_gettag0();
/* Stack underflow has priority */
if ( NOT_EMPTY_ST0 )
{
if ( addr_modes.default_mode & PROTECTED )
{
if (NOT_EMPTY_ST0) {
if (addr_modes.default_mode & PROTECTED) {
/* This table works for 16 and 32 bit protected mode */
if ( access_limit < data_sizes_16[(byte1 >> 1) & 3] )
math_abort(FPU_info,SIGSEGV);
if (access_limit <
data_sizes_16[(byte1 >> 1) & 3])
math_abort(FPU_info, SIGSEGV);
}
unmasked = 0; /* Do this here to stop compiler warnings. */
switch ( (byte1 >> 1) & 3 )
{
switch ((byte1 >> 1) & 3) {
case 0:
unmasked = FPU_load_single((float __user *)data_address,
unmasked =
FPU_load_single((float __user *)
data_address,
&loaded_data);
loaded_tag = unmasked & 0xff;
unmasked &= ~0xff;
break;
case 1:
loaded_tag = FPU_load_int32((long __user *)data_address, &loaded_data);
loaded_tag =
FPU_load_int32((long __user *)
data_address,
&loaded_data);
break;
case 2:
unmasked = FPU_load_double((double __user *)data_address,
unmasked =
FPU_load_double((double __user *)
data_address,
&loaded_data);
loaded_tag = unmasked & 0xff;
unmasked &= ~0xff;
break;
case 3:
default: /* Used here to suppress gcc warnings. */
loaded_tag = FPU_load_int16((short __user *)data_address, &loaded_data);
loaded_tag =
FPU_load_int16((short __user *)
data_address,
&loaded_data);
break;
}
......@@ -363,134 +352,152 @@ asmlinkage void math_emulate(long arg)
/* NaN operands have the next priority. */
/* We have to delay looking at st(0) until after
loading the data, because that data might contain an SNaN */
if ( ((st0_tag == TAG_Special) && isNaN(st0_ptr)) ||
((loaded_tag == TAG_Special) && isNaN(&loaded_data)) )
{
if (((st0_tag == TAG_Special) && isNaN(st0_ptr))
|| ((loaded_tag == TAG_Special)
&& isNaN(&loaded_data))) {
/* Restore the status word; we might have loaded a
denormal. */
partial_status = status1;
if ( (FPU_modrm & 0x30) == 0x10 )
{
if ((FPU_modrm & 0x30) == 0x10) {
/* fcom or fcomp */
EXCEPTION(EX_Invalid);
setcc(SW_C3 | SW_C2 | SW_C0);
if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) )
if ((FPU_modrm & 0x08)
&& (control_word &
CW_Invalid))
FPU_pop(); /* fcomp, masked, so we pop. */
}
else
{
if ( loaded_tag == TAG_Special )
loaded_tag = FPU_Special(&loaded_data);
} else {
if (loaded_tag == TAG_Special)
loaded_tag =
FPU_Special
(&loaded_data);
#ifdef PECULIAR_486
/* This is not really needed, but gives behaviour
identical to an 80486 */
if ( (FPU_modrm & 0x28) == 0x20 )
if ((FPU_modrm & 0x28) == 0x20)
/* fdiv or fsub */
real_2op_NaN(&loaded_data, loaded_tag, 0, &loaded_data);
real_2op_NaN
(&loaded_data,
loaded_tag, 0,
&loaded_data);
else
#endif /* PECULIAR_486 */
/* fadd, fdivr, fmul, or fsubr */
real_2op_NaN(&loaded_data, loaded_tag, 0, st0_ptr);
real_2op_NaN
(&loaded_data,
loaded_tag, 0,
st0_ptr);
}
goto reg_mem_instr_done;
}
if ( unmasked && !((FPU_modrm & 0x30) == 0x10) )
{
if (unmasked && !((FPU_modrm & 0x30) == 0x10)) {
/* Is not a comparison instruction. */
if ( (FPU_modrm & 0x38) == 0x38 )
{
if ((FPU_modrm & 0x38) == 0x38) {
/* fdivr */
if ( (st0_tag == TAG_Zero) &&
if ((st0_tag == TAG_Zero) &&
((loaded_tag == TAG_Valid)
|| (loaded_tag == TAG_Special
&& isdenormal(&loaded_data))) )
{
if ( FPU_divide_by_zero(0, getsign(&loaded_data))
< 0 )
{
|| (loaded_tag ==
TAG_Special
&&
isdenormal
(&loaded_data)))) {
if (FPU_divide_by_zero
(0,
getsign
(&loaded_data))
< 0) {
/* We use the fact here that the unmasked
exception in the loaded data was for a
denormal operand */
/* Restore the state of the denormal op bit */
partial_status &= ~SW_Denorm_Op;
partial_status |= status1 & SW_Denorm_Op;
}
else
setsign(st0_ptr, getsign(&loaded_data));
partial_status
&=
~SW_Denorm_Op;
partial_status
|=
status1 &
SW_Denorm_Op;
} else
setsign(st0_ptr,
getsign
(&loaded_data));
}
}
goto reg_mem_instr_done;
}
switch ( (FPU_modrm >> 3) & 7 )
{
switch ((FPU_modrm >> 3) & 7) {
case 0: /* fadd */
clear_C1();
FPU_add(&loaded_data, loaded_tag, 0, control_word);
FPU_add(&loaded_data, loaded_tag, 0,
control_word);
break;
case 1: /* fmul */
clear_C1();
FPU_mul(&loaded_data, loaded_tag, 0, control_word);
FPU_mul(&loaded_data, loaded_tag, 0,
control_word);
break;
case 2: /* fcom */
FPU_compare_st_data(&loaded_data, loaded_tag);
FPU_compare_st_data(&loaded_data,
loaded_tag);
break;
case 3: /* fcomp */
if ( !FPU_compare_st_data(&loaded_data, loaded_tag)
&& !unmasked )
if (!FPU_compare_st_data
(&loaded_data, loaded_tag)
&& !unmasked)
FPU_pop();
break;
case 4: /* fsub */
clear_C1();
FPU_sub(LOADED|loaded_tag, (int)&loaded_data, control_word);
FPU_sub(LOADED | loaded_tag,
(int)&loaded_data,
control_word);
break;
case 5: /* fsubr */
clear_C1();
FPU_sub(REV|LOADED|loaded_tag, (int)&loaded_data, control_word);
FPU_sub(REV | LOADED | loaded_tag,
(int)&loaded_data,
control_word);
break;
case 6: /* fdiv */
clear_C1();
FPU_div(LOADED|loaded_tag, (int)&loaded_data, control_word);
FPU_div(LOADED | loaded_tag,
(int)&loaded_data,
control_word);
break;
case 7: /* fdivr */
clear_C1();
if ( st0_tag == TAG_Zero )
if (st0_tag == TAG_Zero)
partial_status = status1; /* Undo any denorm tag,
zero-divide has priority. */
FPU_div(REV|LOADED|loaded_tag, (int)&loaded_data, control_word);
FPU_div(REV | LOADED | loaded_tag,
(int)&loaded_data,
control_word);
break;
}
}
else
{
if ( (FPU_modrm & 0x30) == 0x10 )
{
} else {
if ((FPU_modrm & 0x30) == 0x10) {
/* The instruction is fcom or fcomp */
EXCEPTION(EX_StackUnder);
setcc(SW_C3 | SW_C2 | SW_C0);
if ( (FPU_modrm & 0x08) && (control_word & CW_Invalid) )
if ((FPU_modrm & 0x08)
&& (control_word & CW_Invalid))
FPU_pop(); /* fcomp */
}
else
} else
FPU_stack_underflow();
}
reg_mem_instr_done:
operand_address = data_sel_off;
}
else
{
if ( !(no_ip_update =
FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6)) >> 1,
addr_modes, data_address)) )
{
} else {
if (!(no_ip_update =
FPU_load_store(((FPU_modrm & 0x38) | (byte1 & 6))
>> 1, addr_modes, data_address))) {
operand_address = data_sel_off;
}
}
}
else
{
} else {
/* None of these instructions access user memory */
u_char instr_index = (FPU_modrm & 0x38) | (byte1 & 7);
......@@ -503,34 +510,29 @@ asmlinkage void math_emulate(long arg)
st0_ptr = &st(0);
st0_tag = FPU_gettag0();
switch ( type_table[(int) instr_index] )
{
switch (type_table[(int)instr_index]) {
case _NONE_: /* also _REGIc: _REGIn */
break;
case _REG0_:
if ( !NOT_EMPTY_ST0 )
{
if (!NOT_EMPTY_ST0) {
FPU_stack_underflow();
goto FPU_instruction_done;
}
break;
case _REGIi:
if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
{
if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
FPU_stack_underflow_i(FPU_rm);
goto FPU_instruction_done;
}
break;
case _REGIp:
if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
{
if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
FPU_stack_underflow_pop(FPU_rm);
goto FPU_instruction_done;
}
break;
case _REGI_:
if ( !NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm) )
{
if (!NOT_EMPTY_ST0 || !NOT_EMPTY(FPU_rm)) {
FPU_stack_underflow();
goto FPU_instruction_done;
}
......@@ -541,19 +543,19 @@ asmlinkage void math_emulate(long arg)
FPU_illegal();
goto FPU_instruction_done;
default:
EXCEPTION(EX_INTERNAL|0x111);
EXCEPTION(EX_INTERNAL | 0x111);
goto FPU_instruction_done;
}
(*st_instr_table[(int) instr_index])();
(*st_instr_table[(int)instr_index]) ();
FPU_instruction_done:
FPU_instruction_done:
;
}
if ( ! no_ip_update )
if (!no_ip_update)
instruction_address = entry_sel_off;
FPU_fwait_done:
FPU_fwait_done:
#ifdef DEBUG
RE_ENTRANT_CHECK_OFF;
......@@ -561,42 +563,39 @@ asmlinkage void math_emulate(long arg)
RE_ENTRANT_CHECK_ON;
#endif /* DEBUG */
if (FPU_lookahead && !need_resched())
{
if (FPU_lookahead && !need_resched()) {
FPU_ORIG_EIP = FPU_EIP - code_base;
if ( valid_prefix(&byte1, (u_char __user **)&FPU_EIP,
&addr_modes.override) )
if (valid_prefix(&byte1, (u_char __user **) & FPU_EIP,
&addr_modes.override))
goto do_another_FPU_instruction;
}
if ( addr_modes.default_mode )
if (addr_modes.default_mode)
FPU_EIP -= code_base;
RE_ENTRANT_CHECK_OFF;
}
/* Support for prefix bytes is not yet complete. To properly handle
all prefix bytes, further changes are needed in the emulator code
which accesses user address space. Access to separate segments is
important for msdos emulation. */
static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
overrides *override)
static int valid_prefix(u_char * Byte, u_char __user ** fpu_eip,
overrides * override)
{
u_char byte;
u_char __user *ip = *fpu_eip;
*override = (overrides) { 0, 0, PREFIX_DEFAULT }; /* defaults */
*override = (overrides) {
0, 0, PREFIX_DEFAULT}; /* defaults */
RE_ENTRANT_CHECK_OFF;
FPU_code_access_ok(1);
FPU_get_user(byte, ip);
RE_ENTRANT_CHECK_ON;
while ( 1 )
{
switch ( byte )
{
while (1) {
switch (byte) {
case ADDR_SIZE_PREFIX:
override->address_size = ADDR_SIZE_PREFIX;
goto do_next_byte;
......@@ -643,14 +642,11 @@ static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
*Byte = byte;
return 1;
default:
if ( (byte & 0xf8) == 0xd8 )
{
if ((byte & 0xf8) == 0xd8) {
*Byte = byte;
*fpu_eip = ip;
return 1;
}
else
{
} else {
/* Not a valid sequence of prefix bytes followed by
an FPU instruction. */
*Byte = byte; /* Needed for error message. */
......@@ -660,38 +656,35 @@ static int valid_prefix(u_char *Byte, u_char __user **fpu_eip,
}
}
void math_abort(struct info * info, unsigned int signal)
void math_abort(struct info *info, unsigned int signal)
{
FPU_EIP = FPU_ORIG_EIP;
current->thread.trap_no = 16;
current->thread.error_code = 0;
send_sig(signal,current,1);
send_sig(signal, current, 1);
RE_ENTRANT_CHECK_OFF;
__asm__("movl %0,%%esp ; ret": :"g" (((long) info)-4));
__asm__("movl %0,%%esp ; ret": :"g"(((long)info) - 4));
#ifdef PARANOID
printk("ERROR: wm-FPU-emu math_abort failed!\n");
#endif /* PARANOID */
}
#define S387 ((struct i387_soft_struct *)s387)
#define sstatus_word() \
((S387->swd & ~SW_Top & 0xffff) | ((S387->ftop << SW_Top_Shift) & SW_Top))
int restore_i387_soft(void *s387, struct _fpstate __user *buf)
int restore_i387_soft(void *s387, struct _fpstate __user * buf)
{
u_char __user *d = (u_char __user *)buf;
u_char __user *d = (u_char __user *) buf;
int offset, other, i, tags, regnr, tag, newtop;
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_READ, d, 7*4 + 8*10);
if (__copy_from_user(&S387->cwd, d, 7*4))
FPU_access_ok(VERIFY_READ, d, 7 * 4 + 8 * 10);
if (__copy_from_user(&S387->cwd, d, 7 * 4))
return -1;
RE_ENTRANT_CHECK_ON;
d += 7*4;
d += 7 * 4;
S387->ftop = (S387->swd >> SW_Top_Shift) & 7;
offset = (S387->ftop & 7) * 10;
......@@ -699,25 +692,26 @@ int restore_i387_soft(void *s387, struct _fpstate __user *buf)
RE_ENTRANT_CHECK_OFF;
/* Copy all registers in stack order. */
if (__copy_from_user(((u_char *)&S387->st_space)+offset, d, other))
if (__copy_from_user(((u_char *) & S387->st_space) + offset, d, other))
return -1;
if ( offset )
if (__copy_from_user((u_char *)&S387->st_space, d+other, offset))
if (offset)
if (__copy_from_user
((u_char *) & S387->st_space, d + other, offset))
return -1;
RE_ENTRANT_CHECK_ON;
/* The tags may need to be corrected now. */
tags = S387->twd;
newtop = S387->ftop;
for ( i = 0; i < 8; i++ )
{
regnr = (i+newtop) & 7;
if ( ((tags >> ((regnr & 7)*2)) & 3) != TAG_Empty )
{
for (i = 0; i < 8; i++) {
regnr = (i + newtop) & 7;
if (((tags >> ((regnr & 7) * 2)) & 3) != TAG_Empty) {
/* The loaded data over-rides all other cases. */
tag = FPU_tagof((FPU_REG *)((u_char *)S387->st_space + 10*regnr));
tags &= ~(3 << (regnr*2));
tags |= (tag & 3) << (regnr*2);
tag =
FPU_tagof((FPU_REG *) ((u_char *) S387->st_space +
10 * regnr));
tags &= ~(3 << (regnr * 2));
tags |= (tag & 3) << (regnr * 2);
}
}
S387->twd = tags;
......@@ -725,14 +719,13 @@ int restore_i387_soft(void *s387, struct _fpstate __user *buf)
return 0;
}
int save_i387_soft(void *s387, struct _fpstate __user * buf)
{
u_char __user *d = (u_char __user *)buf;
u_char __user *d = (u_char __user *) buf;
int offset = (S387->ftop & 7) * 10, other = 80 - offset;
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE, d, 7*4 + 8*10);
FPU_access_ok(VERIFY_WRITE, d, 7 * 4 + 8 * 10);
#ifdef PECULIAR_486
S387->cwd &= ~0xe080;
/* An 80486 sets nearly all of the reserved bits to 1. */
......@@ -742,18 +735,19 @@ int save_i387_soft(void *s387, struct _fpstate __user * buf)
S387->fcs &= ~0xf8000000;
S387->fos |= 0xffff0000;
#endif /* PECULIAR_486 */
if (__copy_to_user(d, &S387->cwd, 7*4))
if (__copy_to_user(d, &S387->cwd, 7 * 4))
return -1;
RE_ENTRANT_CHECK_ON;
d += 7*4;
d += 7 * 4;
RE_ENTRANT_CHECK_OFF;
/* Copy all registers in stack order. */
if (__copy_to_user(d, ((u_char *)&S387->st_space)+offset, other))
if (__copy_to_user(d, ((u_char *) & S387->st_space) + offset, other))
return -1;
if ( offset )
if (__copy_to_user(d+other, (u_char *)&S387->st_space, offset))
if (offset)
if (__copy_to_user
(d + other, (u_char *) & S387->st_space, offset))
return -1;
RE_ENTRANT_CHECK_ON;
......
......@@ -16,35 +16,27 @@
#include "status_w.h"
#include "reg_constant.h"
static void fchs(FPU_REG *st0_ptr, u_char st0tag)
static void fchs(FPU_REG * st0_ptr, u_char st0tag)
{
if ( st0tag ^ TAG_Empty )
{
if (st0tag ^ TAG_Empty) {
signbyte(st0_ptr) ^= SIGN_NEG;
clear_C1();
}
else
} else
FPU_stack_underflow();
}
static void fabs(FPU_REG *st0_ptr, u_char st0tag)
static void fabs(FPU_REG * st0_ptr, u_char st0tag)
{
if ( st0tag ^ TAG_Empty )
{
if (st0tag ^ TAG_Empty) {
setpositive(st0_ptr);
clear_C1();
}
else
} else
FPU_stack_underflow();
}
static void ftst_(FPU_REG *st0_ptr, u_char st0tag)
static void ftst_(FPU_REG * st0_ptr, u_char st0tag)
{
switch (st0tag)
{
switch (st0tag) {
case TAG_Zero:
setcc(SW_C3);
break;
......@@ -55,15 +47,13 @@ static void ftst_(FPU_REG *st0_ptr, u_char st0tag)
setcc(SW_C0);
break;
case TAG_Special:
switch ( FPU_Special(st0_ptr) )
{
switch (FPU_Special(st0_ptr)) {
case TW_Denormal:
if (getsign(st0_ptr) == SIGN_POS)
setcc(0);
else
setcc(SW_C0);
if ( denormal_operand() < 0 )
{
if (denormal_operand() < 0) {
#ifdef PECULIAR_486
/* This is weird! */
if (getsign(st0_ptr) == SIGN_POS)
......@@ -73,7 +63,7 @@ static void ftst_(FPU_REG *st0_ptr, u_char st0tag)
}
break;
case TW_NaN:
setcc(SW_C0|SW_C2|SW_C3); /* Operand is not comparable */
setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */
EXCEPTION(EX_Invalid);
break;
case TW_Infinity:
......@@ -83,26 +73,24 @@ static void ftst_(FPU_REG *st0_ptr, u_char st0tag)
setcc(SW_C0);
break;
default:
setcc(SW_C0|SW_C2|SW_C3); /* Operand is not comparable */
EXCEPTION(EX_INTERNAL|0x14);
setcc(SW_C0 | SW_C2 | SW_C3); /* Operand is not comparable */
EXCEPTION(EX_INTERNAL | 0x14);
break;
}
break;
case TAG_Empty:
setcc(SW_C0|SW_C2|SW_C3);
setcc(SW_C0 | SW_C2 | SW_C3);
EXCEPTION(EX_StackUnder);
break;
}
}
static void fxam(FPU_REG *st0_ptr, u_char st0tag)
static void fxam(FPU_REG * st0_ptr, u_char st0tag)
{
int c = 0;
switch (st0tag)
{
switch (st0tag) {
case TAG_Empty:
c = SW_C3|SW_C0;
c = SW_C3 | SW_C0;
break;
case TAG_Zero:
c = SW_C3;
......@@ -111,33 +99,32 @@ static void fxam(FPU_REG *st0_ptr, u_char st0tag)
c = SW_C2;
break;
case TAG_Special:
switch ( FPU_Special(st0_ptr) )
{
switch (FPU_Special(st0_ptr)) {
case TW_Denormal:
c = SW_C2|SW_C3; /* Denormal */
c = SW_C2 | SW_C3; /* Denormal */
break;
case TW_NaN:
/* We also use NaN for unsupported types. */
if ( (st0_ptr->sigh & 0x80000000) && (exponent(st0_ptr) == EXP_OVER) )
if ((st0_ptr->sigh & 0x80000000)
&& (exponent(st0_ptr) == EXP_OVER))
c = SW_C0;
break;
case TW_Infinity:
c = SW_C2|SW_C0;
c = SW_C2 | SW_C0;
break;
}
}
if ( getsign(st0_ptr) == SIGN_NEG )
if (getsign(st0_ptr) == SIGN_NEG)
c |= SW_C1;
setcc(c);
}
static FUNC_ST0 const fp_etc_table[] = {
fchs, fabs, (FUNC_ST0)FPU_illegal, (FUNC_ST0)FPU_illegal,
ftst_, fxam, (FUNC_ST0)FPU_illegal, (FUNC_ST0)FPU_illegal
fchs, fabs, (FUNC_ST0) FPU_illegal, (FUNC_ST0) FPU_illegal,
ftst_, fxam, (FUNC_ST0) FPU_illegal, (FUNC_ST0) FPU_illegal
};
void FPU_etc(void)
{
(fp_etc_table[FPU_rm])(&st(0), FPU_gettag0());
(fp_etc_table[FPU_rm]) (&st(0), FPU_gettag0());
}
......@@ -5,7 +5,7 @@
extern void FPU_illegal(void);
extern void FPU_printall(void);
asmlinkage void FPU_exception(int n);
extern int real_1op_NaN(FPU_REG *a);
extern int real_1op_NaN(FPU_REG * a);
extern int real_2op_NaN(FPU_REG const *b, u_char tagb, int deststnr,
FPU_REG const *defaultNaN);
asmlinkage int arith_invalid(int deststnr);
......@@ -14,8 +14,8 @@ extern int set_precision_flag(int flags);
asmlinkage void set_precision_flag_up(void);
asmlinkage void set_precision_flag_down(void);
asmlinkage int denormal_operand(void);
asmlinkage int arith_overflow(FPU_REG *dest);
asmlinkage int arith_underflow(FPU_REG *dest);
asmlinkage int arith_overflow(FPU_REG * dest);
asmlinkage int arith_underflow(FPU_REG * dest);
extern void FPU_stack_overflow(void);
extern void FPU_stack_underflow(void);
extern void FPU_stack_underflow_i(int i);
......@@ -66,7 +66,7 @@ extern int FPU_Special(FPU_REG const *ptr);
extern int isNaN(FPU_REG const *ptr);
extern void FPU_pop(void);
extern int FPU_empty_i(int stnr);
extern int FPU_stackoverflow(FPU_REG **st_new_ptr);
extern int FPU_stackoverflow(FPU_REG ** st_new_ptr);
extern void FPU_copy_to_regi(FPU_REG const *r, u_char tag, int stnr);
extern void FPU_copy_to_reg1(FPU_REG const *r, u_char tag);
extern void FPU_copy_to_reg0(FPU_REG const *r, u_char tag);
......@@ -75,26 +75,28 @@ extern void FPU_triga(void);
extern void FPU_trigb(void);
/* get_address.c */
extern void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
struct address *addr, fpu_addr_modes addr_modes);
struct address *addr,
fpu_addr_modes addr_modes);
extern void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
struct address *addr, fpu_addr_modes addr_modes);
struct address *addr,
fpu_addr_modes addr_modes);
/* load_store.c */
extern int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
void __user *data_address);
void __user * data_address);
/* poly_2xm1.c */
extern int poly_2xm1(u_char sign, FPU_REG *arg, FPU_REG *result);
extern int poly_2xm1(u_char sign, FPU_REG * arg, FPU_REG * result);
/* poly_atan.c */
extern void poly_atan(FPU_REG *st0_ptr, u_char st0_tag, FPU_REG *st1_ptr,
extern void poly_atan(FPU_REG * st0_ptr, u_char st0_tag, FPU_REG * st1_ptr,
u_char st1_tag);
/* poly_l2.c */
extern void poly_l2(FPU_REG *st0_ptr, FPU_REG *st1_ptr, u_char st1_sign);
extern int poly_l2p1(u_char s0, u_char s1, FPU_REG *r0, FPU_REG *r1,
FPU_REG *d);
extern void poly_l2(FPU_REG * st0_ptr, FPU_REG * st1_ptr, u_char st1_sign);
extern int poly_l2p1(u_char s0, u_char s1, FPU_REG * r0, FPU_REG * r1,
FPU_REG * d);
/* poly_sin.c */
extern void poly_sine(FPU_REG *st0_ptr);
extern void poly_cos(FPU_REG *st0_ptr);
extern void poly_sine(FPU_REG * st0_ptr);
extern void poly_cos(FPU_REG * st0_ptr);
/* poly_tan.c */
extern void poly_tan(FPU_REG *st0_ptr);
extern void poly_tan(FPU_REG * st0_ptr);
/* reg_add_sub.c */
extern int FPU_add(FPU_REG const *b, u_char tagb, int destrnr, int control_w);
extern int FPU_sub(int flags, int rm, int control_w);
......@@ -109,32 +111,34 @@ extern void fucompp(void);
/* reg_constant.c */
extern void fconst(void);
/* reg_ld_str.c */
extern int FPU_load_extended(long double __user *s, int stnr);
extern int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data);
extern int FPU_load_single(float __user *single, FPU_REG *loaded_data);
extern int FPU_load_int64(long long __user *_s);
extern int FPU_load_int32(long __user *_s, FPU_REG *loaded_data);
extern int FPU_load_int16(short __user *_s, FPU_REG *loaded_data);
extern int FPU_load_bcd(u_char __user *s);
extern int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag,
long double __user *d);
extern int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat);
extern int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single);
extern int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d);
extern int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long __user *d);
extern int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short __user *d);
extern int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d);
extern int FPU_round_to_int(FPU_REG *r, u_char tag);
extern u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s);
extern void frstor(fpu_addr_modes addr_modes, u_char __user *data_address);
extern u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d);
extern void fsave(fpu_addr_modes addr_modes, u_char __user *data_address);
extern int FPU_tagof(FPU_REG *ptr);
extern int FPU_load_extended(long double __user * s, int stnr);
extern int FPU_load_double(double __user * dfloat, FPU_REG * loaded_data);
extern int FPU_load_single(float __user * single, FPU_REG * loaded_data);
extern int FPU_load_int64(long long __user * _s);
extern int FPU_load_int32(long __user * _s, FPU_REG * loaded_data);
extern int FPU_load_int16(short __user * _s, FPU_REG * loaded_data);
extern int FPU_load_bcd(u_char __user * s);
extern int FPU_store_extended(FPU_REG * st0_ptr, u_char st0_tag,
long double __user * d);
extern int FPU_store_double(FPU_REG * st0_ptr, u_char st0_tag,
double __user * dfloat);
extern int FPU_store_single(FPU_REG * st0_ptr, u_char st0_tag,
float __user * single);
extern int FPU_store_int64(FPU_REG * st0_ptr, u_char st0_tag,
long long __user * d);
extern int FPU_store_int32(FPU_REG * st0_ptr, u_char st0_tag, long __user * d);
extern int FPU_store_int16(FPU_REG * st0_ptr, u_char st0_tag, short __user * d);
extern int FPU_store_bcd(FPU_REG * st0_ptr, u_char st0_tag, u_char __user * d);
extern int FPU_round_to_int(FPU_REG * r, u_char tag);
extern u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user * s);
extern void frstor(fpu_addr_modes addr_modes, u_char __user * data_address);
extern u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user * d);
extern void fsave(fpu_addr_modes addr_modes, u_char __user * data_address);
extern int FPU_tagof(FPU_REG * ptr);
/* reg_mul.c */
extern int FPU_mul(FPU_REG const *b, u_char tagb, int deststnr, int control_w);
extern int FPU_div(int flags, int regrm, int control_w);
/* reg_convert.c */
extern int FPU_to_exp16(FPU_REG const *a, FPU_REG *x);
extern int FPU_to_exp16(FPU_REG const *a, FPU_REG * x);
#endif /* _FPU_PROTO_H */
......@@ -14,95 +14,83 @@
#include "fpu_system.h"
#include "exception.h"
void FPU_pop(void)
{
fpu_tag_word |= 3 << ((top & 7)*2);
fpu_tag_word |= 3 << ((top & 7) * 2);
top++;
}
int FPU_gettag0(void)
{
return (fpu_tag_word >> ((top & 7)*2)) & 3;
return (fpu_tag_word >> ((top & 7) * 2)) & 3;
}
int FPU_gettagi(int stnr)
{
return (fpu_tag_word >> (((top+stnr) & 7)*2)) & 3;
return (fpu_tag_word >> (((top + stnr) & 7) * 2)) & 3;
}
int FPU_gettag(int regnr)
{
return (fpu_tag_word >> ((regnr & 7)*2)) & 3;
return (fpu_tag_word >> ((regnr & 7) * 2)) & 3;
}
void FPU_settag0(int tag)
{
int regnr = top;
regnr &= 7;
fpu_tag_word &= ~(3 << (regnr*2));
fpu_tag_word |= (tag & 3) << (regnr*2);
fpu_tag_word &= ~(3 << (regnr * 2));
fpu_tag_word |= (tag & 3) << (regnr * 2);
}
void FPU_settagi(int stnr, int tag)
{
int regnr = stnr+top;
int regnr = stnr + top;
regnr &= 7;
fpu_tag_word &= ~(3 << (regnr*2));
fpu_tag_word |= (tag & 3) << (regnr*2);
fpu_tag_word &= ~(3 << (regnr * 2));
fpu_tag_word |= (tag & 3) << (regnr * 2);
}
void FPU_settag(int regnr, int tag)
{
regnr &= 7;
fpu_tag_word &= ~(3 << (regnr*2));
fpu_tag_word |= (tag & 3) << (regnr*2);
fpu_tag_word &= ~(3 << (regnr * 2));
fpu_tag_word |= (tag & 3) << (regnr * 2);
}
int FPU_Special(FPU_REG const *ptr)
{
int exp = exponent(ptr);
if ( exp == EXP_BIAS+EXP_UNDER )
if (exp == EXP_BIAS + EXP_UNDER)
return TW_Denormal;
else if ( exp != EXP_BIAS+EXP_OVER )
else if (exp != EXP_BIAS + EXP_OVER)
return TW_NaN;
else if ( (ptr->sigh == 0x80000000) && (ptr->sigl == 0) )
else if ((ptr->sigh == 0x80000000) && (ptr->sigl == 0))
return TW_Infinity;
return TW_NaN;
}
int isNaN(FPU_REG const *ptr)
{
return ( (exponent(ptr) == EXP_BIAS+EXP_OVER)
&& !((ptr->sigh == 0x80000000) && (ptr->sigl == 0)) );
return ((exponent(ptr) == EXP_BIAS + EXP_OVER)
&& !((ptr->sigh == 0x80000000) && (ptr->sigl == 0)));
}
int FPU_empty_i(int stnr)
{
int regnr = (top+stnr) & 7;
int regnr = (top + stnr) & 7;
return ((fpu_tag_word >> (regnr*2)) & 3) == TAG_Empty;
return ((fpu_tag_word >> (regnr * 2)) & 3) == TAG_Empty;
}
int FPU_stackoverflow(FPU_REG **st_new_ptr)
int FPU_stackoverflow(FPU_REG ** st_new_ptr)
{
*st_new_ptr = &st(-1);
return ((fpu_tag_word >> (((top - 1) & 7)*2)) & 3) != TAG_Empty;
return ((fpu_tag_word >> (((top - 1) & 7) * 2)) & 3) != TAG_Empty;
}
void FPU_copy_to_regi(FPU_REG const *r, u_char tag, int stnr)
{
reg_copy(r, &st(stnr));
......@@ -122,6 +110,6 @@ void FPU_copy_to_reg0(FPU_REG const *r, u_char tag)
reg_copy(r, &st(0));
fpu_tag_word &= ~(3 << (regnr*2));
fpu_tag_word |= (tag & 3) << (regnr*2);
fpu_tag_word &= ~(3 << (regnr * 2));
fpu_tag_word |= (tag & 3) << (regnr * 2);
}
......@@ -18,8 +18,7 @@
#include "reg_constant.h"
static void rem_kernel(unsigned long long st0, unsigned long long *y,
unsigned long long st1,
unsigned long long q, int n);
unsigned long long st1, unsigned long long q, int n);
#define BETTER_THAN_486
......@@ -31,7 +30,7 @@ static void rem_kernel(unsigned long long st0, unsigned long long *y,
/* Limited measurements show no results worse than 64 bit precision
except for the results for arguments close to 2^63, where the
precision of the result sometimes degrades to about 63.9 bits */
static int trig_arg(FPU_REG *st0_ptr, int even)
static int trig_arg(FPU_REG * st0_ptr, int even)
{
FPU_REG tmp;
u_char tmptag;
......@@ -39,8 +38,7 @@ static int trig_arg(FPU_REG *st0_ptr, int even)
int old_cw = control_word, saved_status = partial_status;
int tag, st0_tag = TAG_Valid;
if ( exponent(st0_ptr) >= 63 )
{
if (exponent(st0_ptr) >= 63) {
partial_status |= SW_C2; /* Reduction incomplete. */
return -1;
}
......@@ -55,8 +53,7 @@ static int trig_arg(FPU_REG *st0_ptr, int even)
FPU_round_to_int(&tmp, tag); /* Fortunately, this can't overflow
to 2^64 */
q = significand(&tmp);
if ( q )
{
if (q) {
rem_kernel(significand(st0_ptr),
&significand(&tmp),
significand(&CONST_PI2),
......@@ -66,17 +63,18 @@ static int trig_arg(FPU_REG *st0_ptr, int even)
FPU_copy_to_reg0(&tmp, st0_tag);
}
if ( (even && !(q & 1)) || (!even && (q & 1)) )
{
st0_tag = FPU_sub(REV|LOADED|TAG_Valid, (int)&CONST_PI2, FULL_PRECISION);
if ((even && !(q & 1)) || (!even && (q & 1))) {
st0_tag =
FPU_sub(REV | LOADED | TAG_Valid, (int)&CONST_PI2,
FULL_PRECISION);
#ifdef BETTER_THAN_486
/* So far, the results are exact but based upon a 64 bit
precision approximation to pi/2. The technique used
now is equivalent to using an approximation to pi/2 which
is accurate to about 128 bits. */
if ( (exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64) || (q > 1) )
{
if ((exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64)
|| (q > 1)) {
/* This code gives the effect of having pi/2 to better than
128 bits precision. */
......@@ -84,12 +82,13 @@ static int trig_arg(FPU_REG *st0_ptr, int even)
setexponent16(&tmp, 63);
FPU_normalize(&tmp);
tmptag =
FPU_u_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION, SIGN_POS,
exponent(&CONST_PI2extra) + exponent(&tmp));
FPU_u_mul(&CONST_PI2extra, &tmp, &tmp,
FULL_PRECISION, SIGN_POS,
exponent(&CONST_PI2extra) +
exponent(&tmp));
setsign(&tmp, getsign(&CONST_PI2extra));
st0_tag = FPU_add(&tmp, tmptag, 0, FULL_PRECISION);
if ( signnegative(st0_ptr) )
{
if (signnegative(st0_ptr)) {
/* CONST_PI2extra is negative, so the result of the addition
can be negative. This means that the argument is actually
in a different quadrant. The correction is always < pi/2,
......@@ -101,39 +100,40 @@ static int trig_arg(FPU_REG *st0_ptr, int even)
#endif /* BETTER_THAN_486 */
}
#ifdef BETTER_THAN_486
else
{
else {
/* So far, the results are exact but based upon a 64 bit
precision approximation to pi/2. The technique used
now is equivalent to using an approximation to pi/2 which
is accurate to about 128 bits. */
if ( ((q > 0) && (exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64))
|| (q > 1) )
{
if (((q > 0)
&& (exponent(st0_ptr) <= exponent(&CONST_PI2extra) + 64))
|| (q > 1)) {
/* This code gives the effect of having p/2 to better than
128 bits precision. */
significand(&tmp) = q;
setexponent16(&tmp, 63);
FPU_normalize(&tmp); /* This must return TAG_Valid */
tmptag = FPU_u_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION,
SIGN_POS,
exponent(&CONST_PI2extra) + exponent(&tmp));
tmptag =
FPU_u_mul(&CONST_PI2extra, &tmp, &tmp,
FULL_PRECISION, SIGN_POS,
exponent(&CONST_PI2extra) +
exponent(&tmp));
setsign(&tmp, getsign(&CONST_PI2extra));
st0_tag = FPU_sub(LOADED|(tmptag & 0x0f), (int)&tmp,
st0_tag = FPU_sub(LOADED | (tmptag & 0x0f), (int)&tmp,
FULL_PRECISION);
if ( (exponent(st0_ptr) == exponent(&CONST_PI2)) &&
if ((exponent(st0_ptr) == exponent(&CONST_PI2)) &&
((st0_ptr->sigh > CONST_PI2.sigh)
|| ((st0_ptr->sigh == CONST_PI2.sigh)
&& (st0_ptr->sigl > CONST_PI2.sigl))) )
{
&& (st0_ptr->sigl > CONST_PI2.sigl)))) {
/* CONST_PI2extra is negative, so the result of the
subtraction can be larger than pi/2. This means
that the argument is actually in a different quadrant.
The correction is always < pi/2, so it can't overflow
into yet another quadrant. */
st0_tag = FPU_sub(REV|LOADED|TAG_Valid, (int)&CONST_PI2,
FULL_PRECISION);
st0_tag =
FPU_sub(REV | LOADED | TAG_Valid,
(int)&CONST_PI2, FULL_PRECISION);
q++;
}
}
......@@ -147,7 +147,6 @@ static int trig_arg(FPU_REG *st0_ptr, int even)
return (q & 3) | even;
}
/* Convert a long to register */
static void convert_l2reg(long const *arg, int deststnr)
{
......@@ -156,16 +155,17 @@ static void convert_l2reg(long const *arg, int deststnr)
u_char sign;
FPU_REG *dest = &st(deststnr);
if (num == 0)
{
if (num == 0) {
FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
return;
}
if (num > 0)
{ sign = SIGN_POS; }
else
{ num = -num; sign = SIGN_NEG; }
if (num > 0) {
sign = SIGN_POS;
} else {
num = -num;
sign = SIGN_NEG;
}
dest->sigh = num;
dest->sigl = 0;
......@@ -176,52 +176,43 @@ static void convert_l2reg(long const *arg, int deststnr)
return;
}
static void single_arg_error(FPU_REG *st0_ptr, u_char st0_tag)
static void single_arg_error(FPU_REG * st0_ptr, u_char st0_tag)
{
if ( st0_tag == TAG_Empty )
if (st0_tag == TAG_Empty)
FPU_stack_underflow(); /* Puts a QNaN in st(0) */
else if ( st0_tag == TW_NaN )
else if (st0_tag == TW_NaN)
real_1op_NaN(st0_ptr); /* return with a NaN in st(0) */
#ifdef PARANOID
else
EXCEPTION(EX_INTERNAL|0x0112);
EXCEPTION(EX_INTERNAL | 0x0112);
#endif /* PARANOID */
}
static void single_arg_2_error(FPU_REG *st0_ptr, u_char st0_tag)
static void single_arg_2_error(FPU_REG * st0_ptr, u_char st0_tag)
{
int isNaN;
switch ( st0_tag )
{
switch (st0_tag) {
case TW_NaN:
isNaN = (exponent(st0_ptr) == EXP_OVER) && (st0_ptr->sigh & 0x80000000);
if ( isNaN && !(st0_ptr->sigh & 0x40000000) ) /* Signaling ? */
{
isNaN = (exponent(st0_ptr) == EXP_OVER)
&& (st0_ptr->sigh & 0x80000000);
if (isNaN && !(st0_ptr->sigh & 0x40000000)) { /* Signaling ? */
EXCEPTION(EX_Invalid);
if ( control_word & CW_Invalid )
{
if (control_word & CW_Invalid) {
/* The masked response */
/* Convert to a QNaN */
st0_ptr->sigh |= 0x40000000;
push();
FPU_copy_to_reg0(st0_ptr, TAG_Special);
}
}
else if ( isNaN )
{
} else if (isNaN) {
/* A QNaN */
push();
FPU_copy_to_reg0(st0_ptr, TAG_Special);
}
else
{
} else {
/* pseudoNaN or other unsupported */
EXCEPTION(EX_Invalid);
if ( control_word & CW_Invalid )
{
if (control_word & CW_Invalid) {
/* The masked response */
FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
push();
......@@ -231,25 +222,22 @@ static void single_arg_2_error(FPU_REG *st0_ptr, u_char st0_tag)
break; /* return with a NaN in st(0) */
#ifdef PARANOID
default:
EXCEPTION(EX_INTERNAL|0x0112);
EXCEPTION(EX_INTERNAL | 0x0112);
#endif /* PARANOID */
}
}
/*---------------------------------------------------------------------------*/
static void f2xm1(FPU_REG *st0_ptr, u_char tag)
static void f2xm1(FPU_REG * st0_ptr, u_char tag)
{
FPU_REG a;
clear_C1();
if ( tag == TAG_Valid )
{
if (tag == TAG_Valid) {
/* For an 80486 FPU, the result is undefined if the arg is >= 1.0 */
if ( exponent(st0_ptr) < 0 )
{
if (exponent(st0_ptr) < 0) {
denormal_arg:
FPU_to_exp16(st0_ptr, &a);
......@@ -261,21 +249,19 @@ static void f2xm1(FPU_REG *st0_ptr, u_char tag)
return;
}
if ( tag == TAG_Zero )
if (tag == TAG_Zero)
return;
if ( tag == TAG_Special )
if (tag == TAG_Special)
tag = FPU_Special(st0_ptr);
switch ( tag )
{
switch (tag) {
case TW_Denormal:
if ( denormal_operand() < 0 )
if (denormal_operand() < 0)
return;
goto denormal_arg;
case TW_Infinity:
if ( signnegative(st0_ptr) )
{
if (signnegative(st0_ptr)) {
/* -infinity gives -1 (p16-10) */
FPU_copy_to_reg0(&CONST_1, TAG_Valid);
setnegative(st0_ptr);
......@@ -286,19 +272,16 @@ static void f2xm1(FPU_REG *st0_ptr, u_char tag)
}
}
static void fptan(FPU_REG *st0_ptr, u_char st0_tag)
static void fptan(FPU_REG * st0_ptr, u_char st0_tag)
{
FPU_REG *st_new_ptr;
int q;
u_char arg_sign = getsign(st0_ptr);
/* Stack underflow has higher priority */
if ( st0_tag == TAG_Empty )
{
if (st0_tag == TAG_Empty) {
FPU_stack_underflow(); /* Puts a QNaN in st(0) */
if ( control_word & CW_Invalid )
{
if (control_word & CW_Invalid) {
st_new_ptr = &st(-1);
push();
FPU_stack_underflow(); /* Puts a QNaN in the new st(0) */
......@@ -306,15 +289,14 @@ static void fptan(FPU_REG *st0_ptr, u_char st0_tag)
return;
}
if ( STACK_OVERFLOW )
{ FPU_stack_overflow(); return; }
if (STACK_OVERFLOW) {
FPU_stack_overflow();
return;
}
if ( st0_tag == TAG_Valid )
{
if ( exponent(st0_ptr) > -40 )
{
if ( (q = trig_arg(st0_ptr, 0)) == -1 )
{
if (st0_tag == TAG_Valid) {
if (exponent(st0_ptr) > -40) {
if ((q = trig_arg(st0_ptr, 0)) == -1) {
/* Operand is out of range */
return;
}
......@@ -322,9 +304,7 @@ static void fptan(FPU_REG *st0_ptr, u_char st0_tag)
poly_tan(st0_ptr);
setsign(st0_ptr, (q & 1) ^ (arg_sign != 0));
set_precision_flag_up(); /* We do not really know if up or down */
}
else
{
} else {
/* For a small arg, the result == the argument */
/* Underflow may happen */
......@@ -332,7 +312,8 @@ static void fptan(FPU_REG *st0_ptr, u_char st0_tag)
FPU_to_exp16(st0_ptr, st0_ptr);
st0_tag = FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign);
st0_tag =
FPU_round(st0_ptr, 1, 0, FULL_PRECISION, arg_sign);
FPU_settag0(st0_tag);
}
push();
......@@ -340,30 +321,26 @@ static void fptan(FPU_REG *st0_ptr, u_char st0_tag)
return;
}
if ( st0_tag == TAG_Zero )
{
if (st0_tag == TAG_Zero) {
push();
FPU_copy_to_reg0(&CONST_1, TAG_Valid);
setcc(0);
return;
}
if ( st0_tag == TAG_Special )
if (st0_tag == TAG_Special)
st0_tag = FPU_Special(st0_ptr);
if ( st0_tag == TW_Denormal )
{
if ( denormal_operand() < 0 )
if (st0_tag == TW_Denormal) {
if (denormal_operand() < 0)
return;
goto denormal_arg;
}
if ( st0_tag == TW_Infinity )
{
if (st0_tag == TW_Infinity) {
/* The 80486 treats infinity as an invalid operand */
if ( arith_invalid(0) >= 0 )
{
if (arith_invalid(0) >= 0) {
st_new_ptr = &st(-1);
push();
arith_invalid(0);
......@@ -374,20 +351,20 @@ static void fptan(FPU_REG *st0_ptr, u_char st0_tag)
single_arg_2_error(st0_ptr, st0_tag);
}
static void fxtract(FPU_REG *st0_ptr, u_char st0_tag)
static void fxtract(FPU_REG * st0_ptr, u_char st0_tag)
{
FPU_REG *st_new_ptr;
u_char sign;
register FPU_REG *st1_ptr = st0_ptr; /* anticipate */
if ( STACK_OVERFLOW )
{ FPU_stack_overflow(); return; }
if (STACK_OVERFLOW) {
FPU_stack_overflow();
return;
}
clear_C1();
if ( st0_tag == TAG_Valid )
{
if (st0_tag == TAG_Valid) {
long e;
push();
......@@ -403,12 +380,10 @@ static void fxtract(FPU_REG *st0_ptr, u_char st0_tag)
setsign(st_new_ptr, sign);
FPU_settag0(TAG_Valid); /* Needed if arg was a denormal */
return;
}
else if ( st0_tag == TAG_Zero )
{
} else if (st0_tag == TAG_Zero) {
sign = getsign(st0_ptr);
if ( FPU_divide_by_zero(0, SIGN_NEG) < 0 )
if (FPU_divide_by_zero(0, SIGN_NEG) < 0)
return;
push();
......@@ -417,47 +392,38 @@ static void fxtract(FPU_REG *st0_ptr, u_char st0_tag)
return;
}
if ( st0_tag == TAG_Special )
if (st0_tag == TAG_Special)
st0_tag = FPU_Special(st0_ptr);
if ( st0_tag == TW_Denormal )
{
if (denormal_operand() < 0 )
if (st0_tag == TW_Denormal) {
if (denormal_operand() < 0)
return;
push();
sign = getsign(st1_ptr);
FPU_to_exp16(st1_ptr, st_new_ptr);
goto denormal_arg;
}
else if ( st0_tag == TW_Infinity )
{
} else if (st0_tag == TW_Infinity) {
sign = getsign(st0_ptr);
setpositive(st0_ptr);
push();
FPU_copy_to_reg0(&CONST_INF, TAG_Special);
setsign(st_new_ptr, sign);
return;
}
else if ( st0_tag == TW_NaN )
{
if ( real_1op_NaN(st0_ptr) < 0 )
} else if (st0_tag == TW_NaN) {
if (real_1op_NaN(st0_ptr) < 0)
return;
push();
FPU_copy_to_reg0(st0_ptr, TAG_Special);
return;
}
else if ( st0_tag == TAG_Empty )
{
} else if (st0_tag == TAG_Empty) {
/* Is this the correct behaviour? */
if ( control_word & EX_Invalid )
{
if (control_word & EX_Invalid) {
FPU_stack_underflow();
push();
FPU_stack_underflow();
}
else
} else
EXCEPTION(EX_StackUnder);
}
#ifdef PARANOID
......@@ -466,7 +432,6 @@ static void fxtract(FPU_REG *st0_ptr, u_char st0_tag)
#endif /* PARANOID */
}
static void fdecstp(void)
{
clear_C1();
......@@ -479,19 +444,16 @@ static void fincstp(void)
top++;
}
static void fsqrt_(FPU_REG *st0_ptr, u_char st0_tag)
static void fsqrt_(FPU_REG * st0_ptr, u_char st0_tag)
{
int expon;
clear_C1();
if ( st0_tag == TAG_Valid )
{
if (st0_tag == TAG_Valid) {
u_char tag;
if (signnegative(st0_ptr))
{
if (signnegative(st0_ptr)) {
arith_invalid(0); /* sqrt(negative) is invalid */
return;
}
......@@ -510,27 +472,23 @@ static void fsqrt_(FPU_REG *st0_ptr, u_char st0_tag)
return;
}
if ( st0_tag == TAG_Zero )
if (st0_tag == TAG_Zero)
return;
if ( st0_tag == TAG_Special )
if (st0_tag == TAG_Special)
st0_tag = FPU_Special(st0_ptr);
if ( st0_tag == TW_Infinity )
{
if ( signnegative(st0_ptr) )
if (st0_tag == TW_Infinity) {
if (signnegative(st0_ptr))
arith_invalid(0); /* sqrt(-Infinity) is invalid */
return;
}
else if ( st0_tag == TW_Denormal )
{
if (signnegative(st0_ptr))
{
} else if (st0_tag == TW_Denormal) {
if (signnegative(st0_ptr)) {
arith_invalid(0); /* sqrt(negative) is invalid */
return;
}
if ( denormal_operand() < 0 )
if (denormal_operand() < 0)
return;
FPU_to_exp16(st0_ptr, st0_ptr);
......@@ -544,13 +502,11 @@ static void fsqrt_(FPU_REG *st0_ptr, u_char st0_tag)
}
static void frndint_(FPU_REG *st0_ptr, u_char st0_tag)
static void frndint_(FPU_REG * st0_ptr, u_char st0_tag)
{
int flags, tag;
if ( st0_tag == TAG_Valid )
{
if (st0_tag == TAG_Valid) {
u_char sign;
denormal_arg:
......@@ -560,14 +516,13 @@ static void frndint_(FPU_REG *st0_ptr, u_char st0_tag)
if (exponent(st0_ptr) > 63)
return;
if ( st0_tag == TW_Denormal )
{
if (denormal_operand() < 0 )
if (st0_tag == TW_Denormal) {
if (denormal_operand() < 0)
return;
}
/* Fortunately, this can't overflow to 2^64 */
if ( (flags = FPU_round_to_int(st0_ptr, st0_tag)) )
if ((flags = FPU_round_to_int(st0_ptr, st0_tag)))
set_precision_flag(flags);
setexponent16(st0_ptr, 63);
......@@ -577,33 +532,29 @@ static void frndint_(FPU_REG *st0_ptr, u_char st0_tag)
return;
}
if ( st0_tag == TAG_Zero )
if (st0_tag == TAG_Zero)
return;
if ( st0_tag == TAG_Special )
if (st0_tag == TAG_Special)
st0_tag = FPU_Special(st0_ptr);
if ( st0_tag == TW_Denormal )
if (st0_tag == TW_Denormal)
goto denormal_arg;
else if ( st0_tag == TW_Infinity )
else if (st0_tag == TW_Infinity)
return;
else
single_arg_error(st0_ptr, st0_tag);
}
static int fsin(FPU_REG *st0_ptr, u_char tag)
static int fsin(FPU_REG * st0_ptr, u_char tag)
{
u_char arg_sign = getsign(st0_ptr);
if ( tag == TAG_Valid )
{
if (tag == TAG_Valid) {
int q;
if ( exponent(st0_ptr) > -40 )
{
if ( (q = trig_arg(st0_ptr, 0)) == -1 )
{
if (exponent(st0_ptr) > -40) {
if ((q = trig_arg(st0_ptr, 0)) == -1) {
/* Operand is out of range */
return 1;
}
......@@ -618,27 +569,23 @@ static int fsin(FPU_REG *st0_ptr, u_char tag)
/* We do not really know if up or down */
set_precision_flag_up();
return 0;
}
else
{
} else {
/* For a small arg, the result == the argument */
set_precision_flag_up(); /* Must be up. */
return 0;
}
}
if ( tag == TAG_Zero )
{
if (tag == TAG_Zero) {
setcc(0);
return 0;
}
if ( tag == TAG_Special )
if (tag == TAG_Special)
tag = FPU_Special(st0_ptr);
if ( tag == TW_Denormal )
{
if ( denormal_operand() < 0 )
if (tag == TW_Denormal) {
if (denormal_operand() < 0)
return 1;
/* For a small arg, the result == the argument */
......@@ -650,64 +597,51 @@ static int fsin(FPU_REG *st0_ptr, u_char tag)
FPU_settag0(tag);
return 0;
}
else if ( tag == TW_Infinity )
{
} else if (tag == TW_Infinity) {
/* The 80486 treats infinity as an invalid operand */
arith_invalid(0);
return 1;
}
else
{
} else {
single_arg_error(st0_ptr, tag);
return 1;
}
}
static int f_cos(FPU_REG *st0_ptr, u_char tag)
static int f_cos(FPU_REG * st0_ptr, u_char tag)
{
u_char st0_sign;
st0_sign = getsign(st0_ptr);
if ( tag == TAG_Valid )
{
if (tag == TAG_Valid) {
int q;
if ( exponent(st0_ptr) > -40 )
{
if ( (exponent(st0_ptr) < 0)
if (exponent(st0_ptr) > -40) {
if ((exponent(st0_ptr) < 0)
|| ((exponent(st0_ptr) == 0)
&& (significand(st0_ptr) <= 0xc90fdaa22168c234LL)) )
{
&& (significand(st0_ptr) <=
0xc90fdaa22168c234LL))) {
poly_cos(st0_ptr);
/* We do not really know if up or down */
set_precision_flag_down();
return 0;
}
else if ( (q = trig_arg(st0_ptr, FCOS)) != -1 )
{
} else if ((q = trig_arg(st0_ptr, FCOS)) != -1) {
poly_sine(st0_ptr);
if ((q+1) & 2)
if ((q + 1) & 2)
changesign(st0_ptr);
/* We do not really know if up or down */
set_precision_flag_down();
return 0;
}
else
{
} else {
/* Operand is out of range */
return 1;
}
}
else
{
} else {
denormal_arg:
setcc(0);
......@@ -719,56 +653,45 @@ static int f_cos(FPU_REG *st0_ptr, u_char tag)
#endif /* PECULIAR_486 */
return 0;
}
}
else if ( tag == TAG_Zero )
{
} else if (tag == TAG_Zero) {
FPU_copy_to_reg0(&CONST_1, TAG_Valid);
setcc(0);
return 0;
}
if ( tag == TAG_Special )
if (tag == TAG_Special)
tag = FPU_Special(st0_ptr);
if ( tag == TW_Denormal )
{
if ( denormal_operand() < 0 )
if (tag == TW_Denormal) {
if (denormal_operand() < 0)
return 1;
goto denormal_arg;
}
else if ( tag == TW_Infinity )
{
} else if (tag == TW_Infinity) {
/* The 80486 treats infinity as an invalid operand */
arith_invalid(0);
return 1;
}
else
{
} else {
single_arg_error(st0_ptr, tag); /* requires st0_ptr == &st(0) */
return 1;
}
}
static void fcos(FPU_REG *st0_ptr, u_char st0_tag)
static void fcos(FPU_REG * st0_ptr, u_char st0_tag)
{
f_cos(st0_ptr, st0_tag);
}
static void fsincos(FPU_REG *st0_ptr, u_char st0_tag)
static void fsincos(FPU_REG * st0_ptr, u_char st0_tag)
{
FPU_REG *st_new_ptr;
FPU_REG arg;
u_char tag;
/* Stack underflow has higher priority */
if ( st0_tag == TAG_Empty )
{
if (st0_tag == TAG_Empty) {
FPU_stack_underflow(); /* Puts a QNaN in st(0) */
if ( control_word & CW_Invalid )
{
if (control_word & CW_Invalid) {
st_new_ptr = &st(-1);
push();
FPU_stack_underflow(); /* Puts a QNaN in the new st(0) */
......@@ -776,24 +699,22 @@ static void fsincos(FPU_REG *st0_ptr, u_char st0_tag)
return;
}
if ( STACK_OVERFLOW )
{ FPU_stack_overflow(); return; }
if (STACK_OVERFLOW) {
FPU_stack_overflow();
return;
}
if ( st0_tag == TAG_Special )
if (st0_tag == TAG_Special)
tag = FPU_Special(st0_ptr);
else
tag = st0_tag;
if ( tag == TW_NaN )
{
if (tag == TW_NaN) {
single_arg_2_error(st0_ptr, TW_NaN);
return;
}
else if ( tag == TW_Infinity )
{
} else if (tag == TW_Infinity) {
/* The 80486 treats infinity as an invalid operand */
if ( arith_invalid(0) >= 0 )
{
if (arith_invalid(0) >= 0) {
/* Masked response */
push();
arith_invalid(0);
......@@ -802,20 +723,16 @@ static void fsincos(FPU_REG *st0_ptr, u_char st0_tag)
}
reg_copy(st0_ptr, &arg);
if ( !fsin(st0_ptr, st0_tag) )
{
if (!fsin(st0_ptr, st0_tag)) {
push();
FPU_copy_to_reg0(&arg, st0_tag);
f_cos(&st(0), st0_tag);
}
else
{
} else {
/* An error, so restore st(0) */
FPU_copy_to_reg0(&arg, st0_tag);
}
}
/*---------------------------------------------------------------------------*/
/* The following all require two arguments: st(0) and st(1) */
......@@ -826,8 +743,7 @@ static void fsincos(FPU_REG *st0_ptr, u_char st0_tag)
result must be zero.
*/
static void rem_kernel(unsigned long long st0, unsigned long long *y,
unsigned long long st1,
unsigned long long q, int n)
unsigned long long st1, unsigned long long q, int n)
{
int dummy;
unsigned long long x;
......@@ -837,36 +753,34 @@ static void rem_kernel(unsigned long long st0, unsigned long long *y,
/* Do the required multiplication and subtraction in the one operation */
/* lsw x -= lsw st1 * lsw q */
asm volatile ("mull %4; subl %%eax,%0; sbbl %%edx,%1"
:"=m" (((unsigned *)&x)[0]), "=m" (((unsigned *)&x)[1]),
"=a" (dummy)
:"2" (((unsigned *)&st1)[0]), "m" (((unsigned *)&q)[0])
asm volatile ("mull %4; subl %%eax,%0; sbbl %%edx,%1":"=m"
(((unsigned *)&x)[0]), "=m"(((unsigned *)&x)[1]),
"=a"(dummy)
:"2"(((unsigned *)&st1)[0]), "m"(((unsigned *)&q)[0])
:"%dx");
/* msw x -= msw st1 * lsw q */
asm volatile ("mull %3; subl %%eax,%0"
:"=m" (((unsigned *)&x)[1]), "=a" (dummy)
:"1" (((unsigned *)&st1)[1]), "m" (((unsigned *)&q)[0])
asm volatile ("mull %3; subl %%eax,%0":"=m" (((unsigned *)&x)[1]),
"=a"(dummy)
:"1"(((unsigned *)&st1)[1]), "m"(((unsigned *)&q)[0])
:"%dx");
/* msw x -= lsw st1 * msw q */
asm volatile ("mull %3; subl %%eax,%0"
:"=m" (((unsigned *)&x)[1]), "=a" (dummy)
:"1" (((unsigned *)&st1)[0]), "m" (((unsigned *)&q)[1])
asm volatile ("mull %3; subl %%eax,%0":"=m" (((unsigned *)&x)[1]),
"=a"(dummy)
:"1"(((unsigned *)&st1)[0]), "m"(((unsigned *)&q)[1])
:"%dx");
*y = x;
}
/* Remainder of st(0) / st(1) */
/* This routine produces exact results, i.e. there is never any
rounding or truncation, etc of the result. */
static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round)
static void do_fprem(FPU_REG * st0_ptr, u_char st0_tag, int round)
{
FPU_REG *st1_ptr = &st(1);
u_char st1_tag = FPU_gettagi(1);
if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
{
if (!((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid))) {
FPU_REG tmp, st0, st1;
u_char st0_sign, st1_sign;
u_char tmptag;
......@@ -892,20 +806,17 @@ static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round)
control_word &= ~CW_RC;
control_word |= RC_CHOP;
if ( expdif < 64 )
{
if (expdif < 64) {
/* This should be the most common case */
if ( expdif > -2 )
{
if (expdif > -2) {
u_char sign = st0_sign ^ st1_sign;
tag = FPU_u_div(&st0, &st1, &tmp,
PR_64_BITS | RC_CHOP | 0x3f,
sign);
setsign(&tmp, sign);
if ( exponent(&tmp) >= 0 )
{
if (exponent(&tmp) >= 0) {
FPU_round_to_int(&tmp, tag); /* Fortunately, this can't
overflow to 2^64 */
q = significand(&tmp);
......@@ -916,49 +827,49 @@ static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round)
q, expdif);
setexponent16(&tmp, exponent16(&st1));
}
else
{
} else {
reg_copy(&st0, &tmp);
q = 0;
}
if ( (round == RC_RND) && (tmp.sigh & 0xc0000000) )
{
if ((round == RC_RND)
&& (tmp.sigh & 0xc0000000)) {
/* We may need to subtract st(1) once more,
to get a result <= 1/2 of st(1). */
unsigned long long x;
expdif = exponent16(&st1) - exponent16(&tmp);
if ( expdif <= 1 )
{
if ( expdif == 0 )
x = significand(&st1) - significand(&tmp);
expdif =
exponent16(&st1) - exponent16(&tmp);
if (expdif <= 1) {
if (expdif == 0)
x = significand(&st1) -
significand(&tmp);
else /* expdif is 1 */
x = (significand(&st1) << 1) - significand(&tmp);
if ( (x < significand(&tmp)) ||
x = (significand(&st1)
<< 1) -
significand(&tmp);
if ((x < significand(&tmp)) ||
/* or equi-distant (from 0 & st(1)) and q is odd */
((x == significand(&tmp)) && (q & 1) ) )
{
st0_sign = ! st0_sign;
((x == significand(&tmp))
&& (q & 1))) {
st0_sign = !st0_sign;
significand(&tmp) = x;
q++;
}
}
}
if (q & 4) cc |= SW_C0;
if (q & 2) cc |= SW_C3;
if (q & 1) cc |= SW_C1;
}
else
{
if (q & 4)
cc |= SW_C0;
if (q & 2)
cc |= SW_C3;
if (q & 1)
cc |= SW_C1;
} else {
control_word = old_cw;
setcc(0);
return;
}
}
else
{
} else {
/* There is a large exponent difference ( >= 64 ) */
/* To make much sense, the code in this section should
be done at high precision. */
......@@ -977,8 +888,9 @@ static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round)
expdif -= N;
sign = getsign(&tmp) ^ st1_sign;
tag = FPU_u_div(&tmp, &st1, &tmp, PR_64_BITS | RC_CHOP | 0x3f,
sign);
tag =
FPU_u_div(&tmp, &st1, &tmp,
PR_64_BITS | RC_CHOP | 0x3f, sign);
setsign(&tmp, sign);
FPU_round_to_int(&tmp, tag); /* Fortunately, this can't
......@@ -987,8 +899,7 @@ static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round)
rem_kernel(significand(&st0),
&significand(&tmp),
significand(&st1),
significand(&tmp),
exponent(&tmp)
significand(&tmp), exponent(&tmp)
);
setexponent16(&tmp, exp_1 + expdif);
......@@ -997,8 +908,7 @@ static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round)
implies that the operation will never be completed at this
point, and the behaviour of a real 80486 confirms this.
*/
if ( !(tmp.sigh | tmp.sigl) )
{
if (!(tmp.sigh | tmp.sigl)) {
/* The result is zero */
control_word = old_cw;
partial_status = saved_status;
......@@ -1021,23 +931,19 @@ static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round)
/* The only condition to be looked for is underflow,
and it can occur here only if underflow is unmasked. */
if ( (exponent16(&tmp) <= EXP_UNDER) && (tag != TAG_Zero)
&& !(control_word & CW_Underflow) )
{
if ((exponent16(&tmp) <= EXP_UNDER) && (tag != TAG_Zero)
&& !(control_word & CW_Underflow)) {
setcc(cc);
tag = arith_underflow(st0_ptr);
setsign(st0_ptr, st0_sign);
FPU_settag0(tag);
return;
}
else if ( (exponent16(&tmp) > EXP_UNDER) || (tag == TAG_Zero) )
{
} else if ((exponent16(&tmp) > EXP_UNDER) || (tag == TAG_Zero)) {
stdexp(st0_ptr);
setsign(st0_ptr, st0_sign);
}
else
{
tag = FPU_round(st0_ptr, 0, 0, FULL_PRECISION, st0_sign);
} else {
tag =
FPU_round(st0_ptr, 0, 0, FULL_PRECISION, st0_sign);
}
FPU_settag0(tag);
setcc(cc);
......@@ -1045,65 +951,55 @@ static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round)
return;
}
if ( st0_tag == TAG_Special )
if (st0_tag == TAG_Special)
st0_tag = FPU_Special(st0_ptr);
if ( st1_tag == TAG_Special )
if (st1_tag == TAG_Special)
st1_tag = FPU_Special(st1_ptr);
if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
if (((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
|| ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
|| ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) )
{
if ( denormal_operand() < 0 )
|| ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal))) {
if (denormal_operand() < 0)
return;
goto fprem_valid;
}
else if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) )
{
} else if ((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) {
FPU_stack_underflow();
return;
}
else if ( st0_tag == TAG_Zero )
{
if ( st1_tag == TAG_Valid )
{
setcc(0); return;
}
else if ( st1_tag == TW_Denormal )
{
if ( denormal_operand() < 0 )
} else if (st0_tag == TAG_Zero) {
if (st1_tag == TAG_Valid) {
setcc(0);
return;
} else if (st1_tag == TW_Denormal) {
if (denormal_operand() < 0)
return;
setcc(0);
return;
} else if (st1_tag == TAG_Zero) {
arith_invalid(0);
return;
} /* fprem(?,0) always invalid */
else if (st1_tag == TW_Infinity) {
setcc(0);
return;
setcc(0); return;
}
else if ( st1_tag == TAG_Zero )
{ arith_invalid(0); return; } /* fprem(?,0) always invalid */
else if ( st1_tag == TW_Infinity )
{ setcc(0); return; }
}
else if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )
{
if ( st1_tag == TAG_Zero )
{
} else if ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal)) {
if (st1_tag == TAG_Zero) {
arith_invalid(0); /* fprem(Valid,Zero) is invalid */
return;
}
else if ( st1_tag != TW_NaN )
{
if ( ((st0_tag == TW_Denormal) || (st1_tag == TW_Denormal))
&& (denormal_operand() < 0) )
} else if (st1_tag != TW_NaN) {
if (((st0_tag == TW_Denormal)
|| (st1_tag == TW_Denormal))
&& (denormal_operand() < 0))
return;
if ( st1_tag == TW_Infinity )
{
if (st1_tag == TW_Infinity) {
/* fprem(Valid,Infinity) is o.k. */
setcc(0); return;
}
setcc(0);
return;
}
}
else if ( st0_tag == TW_Infinity )
{
if ( st1_tag != TW_NaN )
{
} else if (st0_tag == TW_Infinity) {
if (st1_tag != TW_NaN) {
arith_invalid(0); /* fprem(Infinity,?) is invalid */
return;
}
......@@ -1112,7 +1008,7 @@ static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round)
/* One of the registers must contain a NaN if we got here. */
#ifdef PARANOID
if ( (st0_tag != TW_NaN) && (st1_tag != TW_NaN) )
if ((st0_tag != TW_NaN) && (st1_tag != TW_NaN))
EXCEPTION(EX_INTERNAL | 0x118);
#endif /* PARANOID */
......@@ -1120,9 +1016,8 @@ static void do_fprem(FPU_REG *st0_ptr, u_char st0_tag, int round)
}
/* ST(1) <- ST(1) * log ST; pop ST */
static void fyl2x(FPU_REG *st0_ptr, u_char st0_tag)
static void fyl2x(FPU_REG * st0_ptr, u_char st0_tag)
{
FPU_REG *st1_ptr = &st(1), exponent;
u_char st1_tag = FPU_gettagi(1);
......@@ -1131,30 +1026,25 @@ static void fyl2x(FPU_REG *st0_ptr, u_char st0_tag)
clear_C1();
if ( (st0_tag == TAG_Valid) && (st1_tag == TAG_Valid) )
{
if ((st0_tag == TAG_Valid) && (st1_tag == TAG_Valid)) {
both_valid:
/* Both regs are Valid or Denormal */
if ( signpositive(st0_ptr) )
{
if ( st0_tag == TW_Denormal )
if (signpositive(st0_ptr)) {
if (st0_tag == TW_Denormal)
FPU_to_exp16(st0_ptr, st0_ptr);
else
/* Convert st(0) for internal use. */
setexponent16(st0_ptr, exponent(st0_ptr));
if ( (st0_ptr->sigh == 0x80000000) && (st0_ptr->sigl == 0) )
{
if ((st0_ptr->sigh == 0x80000000)
&& (st0_ptr->sigl == 0)) {
/* Special case. The result can be precise. */
u_char esign;
e = exponent16(st0_ptr);
if ( e >= 0 )
{
if (e >= 0) {
exponent.sigh = e;
esign = SIGN_POS;
}
else
{
} else {
exponent.sigh = -e;
esign = SIGN_NEG;
}
......@@ -1163,26 +1053,24 @@ static void fyl2x(FPU_REG *st0_ptr, u_char st0_tag)
tag = FPU_normalize_nuo(&exponent);
stdexp(&exponent);
setsign(&exponent, esign);
tag = FPU_mul(&exponent, tag, 1, FULL_PRECISION);
if ( tag >= 0 )
tag =
FPU_mul(&exponent, tag, 1, FULL_PRECISION);
if (tag >= 0)
FPU_settagi(1, tag);
}
else
{
} else {
/* The usual case */
sign = getsign(st1_ptr);
if ( st1_tag == TW_Denormal )
if (st1_tag == TW_Denormal)
FPU_to_exp16(st1_ptr, st1_ptr);
else
/* Convert st(1) for internal use. */
setexponent16(st1_ptr, exponent(st1_ptr));
setexponent16(st1_ptr,
exponent(st1_ptr));
poly_l2(st0_ptr, st1_ptr, sign);
}
}
else
{
} else {
/* negative */
if ( arith_invalid(1) < 0 )
if (arith_invalid(1) < 0)
return;
}
......@@ -1191,86 +1079,68 @@ static void fyl2x(FPU_REG *st0_ptr, u_char st0_tag)
return;
}
if ( st0_tag == TAG_Special )
if (st0_tag == TAG_Special)
st0_tag = FPU_Special(st0_ptr);
if ( st1_tag == TAG_Special )
if (st1_tag == TAG_Special)
st1_tag = FPU_Special(st1_ptr);
if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) )
{
if ((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) {
FPU_stack_underflow_pop(1);
return;
}
else if ( (st0_tag <= TW_Denormal) && (st1_tag <= TW_Denormal) )
{
if ( st0_tag == TAG_Zero )
{
if ( st1_tag == TAG_Zero )
{
} else if ((st0_tag <= TW_Denormal) && (st1_tag <= TW_Denormal)) {
if (st0_tag == TAG_Zero) {
if (st1_tag == TAG_Zero) {
/* Both args zero is invalid */
if ( arith_invalid(1) < 0 )
if (arith_invalid(1) < 0)
return;
}
else
{
} else {
u_char sign;
sign = getsign(st1_ptr)^SIGN_NEG;
if ( FPU_divide_by_zero(1, sign) < 0 )
sign = getsign(st1_ptr) ^ SIGN_NEG;
if (FPU_divide_by_zero(1, sign) < 0)
return;
setsign(st1_ptr, sign);
}
}
else if ( st1_tag == TAG_Zero )
{
} else if (st1_tag == TAG_Zero) {
/* st(1) contains zero, st(0) valid <> 0 */
/* Zero is the valid answer */
sign = getsign(st1_ptr);
if ( signnegative(st0_ptr) )
{
if (signnegative(st0_ptr)) {
/* log(negative) */
if ( arith_invalid(1) < 0 )
if (arith_invalid(1) < 0)
return;
}
else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
} else if ((st0_tag == TW_Denormal)
&& (denormal_operand() < 0))
return;
else
{
if ( exponent(st0_ptr) < 0 )
else {
if (exponent(st0_ptr) < 0)
sign ^= SIGN_NEG;
FPU_copy_to_reg1(&CONST_Z, TAG_Zero);
setsign(st1_ptr, sign);
}
}
else
{
} else {
/* One or both operands are denormals. */
if ( denormal_operand() < 0 )
if (denormal_operand() < 0)
return;
goto both_valid;
}
}
else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) )
{
if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
} else if ((st0_tag == TW_NaN) || (st1_tag == TW_NaN)) {
if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0)
return;
}
/* One or both arg must be an infinity */
else if ( st0_tag == TW_Infinity )
{
if ( (signnegative(st0_ptr)) || (st1_tag == TAG_Zero) )
{
else if (st0_tag == TW_Infinity) {
if ((signnegative(st0_ptr)) || (st1_tag == TAG_Zero)) {
/* log(-infinity) or 0*log(infinity) */
if ( arith_invalid(1) < 0 )
if (arith_invalid(1) < 0)
return;
}
else
{
} else {
u_char sign = getsign(st1_ptr);
if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
if ((st1_tag == TW_Denormal)
&& (denormal_operand() < 0))
return;
FPU_copy_to_reg1(&CONST_INF, TAG_Special);
......@@ -1278,64 +1148,54 @@ static void fyl2x(FPU_REG *st0_ptr, u_char st0_tag)
}
}
/* st(1) must be infinity here */
else if ( ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal))
&& ( signpositive(st0_ptr) ) )
{
if ( exponent(st0_ptr) >= 0 )
{
if ( (exponent(st0_ptr) == 0) &&
else if (((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal))
&& (signpositive(st0_ptr))) {
if (exponent(st0_ptr) >= 0) {
if ((exponent(st0_ptr) == 0) &&
(st0_ptr->sigh == 0x80000000) &&
(st0_ptr->sigl == 0) )
{
(st0_ptr->sigl == 0)) {
/* st(0) holds 1.0 */
/* infinity*log(1) */
if ( arith_invalid(1) < 0 )
if (arith_invalid(1) < 0)
return;
}
/* else st(0) is positive and > 1.0 */
}
else
{
} else {
/* st(0) is positive and < 1.0 */
if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
if ((st0_tag == TW_Denormal)
&& (denormal_operand() < 0))
return;
changesign(st1_ptr);
}
}
else
{
} else {
/* st(0) must be zero or negative */
if ( st0_tag == TAG_Zero )
{
if (st0_tag == TAG_Zero) {
/* This should be invalid, but a real 80486 is happy with it. */
#ifndef PECULIAR_486
sign = getsign(st1_ptr);
if ( FPU_divide_by_zero(1, sign) < 0 )
if (FPU_divide_by_zero(1, sign) < 0)
return;
#endif /* PECULIAR_486 */
changesign(st1_ptr);
}
else if ( arith_invalid(1) < 0 ) /* log(negative) */
} else if (arith_invalid(1) < 0) /* log(negative) */
return;
}
FPU_pop();
}
static void fpatan(FPU_REG *st0_ptr, u_char st0_tag)
static void fpatan(FPU_REG * st0_ptr, u_char st0_tag)
{
FPU_REG *st1_ptr = &st(1);
u_char st1_tag = FPU_gettagi(1);
int tag;
clear_C1();
if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
{
if (!((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid))) {
valid_atan:
poly_atan(st0_ptr, st0_tag, st1_ptr, st1_tag);
......@@ -1345,90 +1205,73 @@ static void fpatan(FPU_REG *st0_ptr, u_char st0_tag)
return;
}
if ( st0_tag == TAG_Special )
if (st0_tag == TAG_Special)
st0_tag = FPU_Special(st0_ptr);
if ( st1_tag == TAG_Special )
if (st1_tag == TAG_Special)
st1_tag = FPU_Special(st1_ptr);
if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
if (((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
|| ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
|| ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) )
{
if ( denormal_operand() < 0 )
|| ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal))) {
if (denormal_operand() < 0)
return;
goto valid_atan;
}
else if ( (st0_tag == TAG_Empty) || (st1_tag == TAG_Empty) )
{
} else if ((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) {
FPU_stack_underflow_pop(1);
return;
}
else if ( (st0_tag == TW_NaN) || (st1_tag == TW_NaN) )
{
if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) >= 0 )
} else if ((st0_tag == TW_NaN) || (st1_tag == TW_NaN)) {
if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) >= 0)
FPU_pop();
return;
}
else if ( (st0_tag == TW_Infinity) || (st1_tag == TW_Infinity) )
{
} else if ((st0_tag == TW_Infinity) || (st1_tag == TW_Infinity)) {
u_char sign = getsign(st1_ptr);
if ( st0_tag == TW_Infinity )
{
if ( st1_tag == TW_Infinity )
{
if ( signpositive(st0_ptr) )
{
if (st0_tag == TW_Infinity) {
if (st1_tag == TW_Infinity) {
if (signpositive(st0_ptr)) {
FPU_copy_to_reg1(&CONST_PI4, TAG_Valid);
}
else
{
} else {
setpositive(st1_ptr);
tag = FPU_u_add(&CONST_PI4, &CONST_PI2, st1_ptr,
FULL_PRECISION, SIGN_POS,
exponent(&CONST_PI4), exponent(&CONST_PI2));
if ( tag >= 0 )
tag =
FPU_u_add(&CONST_PI4, &CONST_PI2,
st1_ptr, FULL_PRECISION,
SIGN_POS,
exponent(&CONST_PI4),
exponent(&CONST_PI2));
if (tag >= 0)
FPU_settagi(1, tag);
}
}
else
{
if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
} else {
if ((st1_tag == TW_Denormal)
&& (denormal_operand() < 0))
return;
if ( signpositive(st0_ptr) )
{
if (signpositive(st0_ptr)) {
FPU_copy_to_reg1(&CONST_Z, TAG_Zero);
setsign(st1_ptr, sign); /* An 80486 preserves the sign */
FPU_pop();
return;
}
else
{
} else {
FPU_copy_to_reg1(&CONST_PI, TAG_Valid);
}
}
}
else
{
} else {
/* st(1) is infinity, st(0) not infinity */
if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
if ((st0_tag == TW_Denormal)
&& (denormal_operand() < 0))
return;
FPU_copy_to_reg1(&CONST_PI2, TAG_Valid);
}
setsign(st1_ptr, sign);
}
else if ( st1_tag == TAG_Zero )
{
} else if (st1_tag == TAG_Zero) {
/* st(0) must be valid or zero */
u_char sign = getsign(st1_ptr);
if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
if ((st0_tag == TW_Denormal) && (denormal_operand() < 0))
return;
if ( signpositive(st0_ptr) )
{
if (signpositive(st0_ptr)) {
/* An 80486 preserves the sign */
FPU_pop();
return;
......@@ -1436,13 +1279,11 @@ static void fpatan(FPU_REG *st0_ptr, u_char st0_tag)
FPU_copy_to_reg1(&CONST_PI, TAG_Valid);
setsign(st1_ptr, sign);
}
else if ( st0_tag == TAG_Zero )
{
} else if (st0_tag == TAG_Zero) {
/* st(1) must be TAG_Valid here */
u_char sign = getsign(st1_ptr);
if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
if ((st1_tag == TW_Denormal) && (denormal_operand() < 0))
return;
FPU_copy_to_reg1(&CONST_PI2, TAG_Valid);
......@@ -1457,28 +1298,24 @@ static void fpatan(FPU_REG *st0_ptr, u_char st0_tag)
set_precision_flag_up(); /* We do not really know if up or down */
}
static void fprem(FPU_REG *st0_ptr, u_char st0_tag)
static void fprem(FPU_REG * st0_ptr, u_char st0_tag)
{
do_fprem(st0_ptr, st0_tag, RC_CHOP);
}
static void fprem1(FPU_REG *st0_ptr, u_char st0_tag)
static void fprem1(FPU_REG * st0_ptr, u_char st0_tag)
{
do_fprem(st0_ptr, st0_tag, RC_RND);
}
static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag)
static void fyl2xp1(FPU_REG * st0_ptr, u_char st0_tag)
{
u_char sign, sign1;
FPU_REG *st1_ptr = &st(1), a, b;
u_char st1_tag = FPU_gettagi(1);
clear_C1();
if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
{
if (!((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid))) {
valid_yl2xp1:
sign = getsign(st0_ptr);
......@@ -1487,38 +1324,32 @@ static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag)
FPU_to_exp16(st0_ptr, &a);
FPU_to_exp16(st1_ptr, &b);
if ( poly_l2p1(sign, sign1, &a, &b, st1_ptr) )
if (poly_l2p1(sign, sign1, &a, &b, st1_ptr))
return;
FPU_pop();
return;
}
if ( st0_tag == TAG_Special )
if (st0_tag == TAG_Special)
st0_tag = FPU_Special(st0_ptr);
if ( st1_tag == TAG_Special )
if (st1_tag == TAG_Special)
st1_tag = FPU_Special(st1_ptr);
if ( ((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
if (((st0_tag == TAG_Valid) && (st1_tag == TW_Denormal))
|| ((st0_tag == TW_Denormal) && (st1_tag == TAG_Valid))
|| ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal)) )
{
if ( denormal_operand() < 0 )
|| ((st0_tag == TW_Denormal) && (st1_tag == TW_Denormal))) {
if (denormal_operand() < 0)
return;
goto valid_yl2xp1;
}
else if ( (st0_tag == TAG_Empty) | (st1_tag == TAG_Empty) )
{
} else if ((st0_tag == TAG_Empty) | (st1_tag == TAG_Empty)) {
FPU_stack_underflow_pop(1);
return;
}
else if ( st0_tag == TAG_Zero )
{
switch ( st1_tag )
{
} else if (st0_tag == TAG_Zero) {
switch (st1_tag) {
case TW_Denormal:
if ( denormal_operand() < 0 )
if (denormal_operand() < 0)
return;
case TAG_Zero:
......@@ -1529,12 +1360,12 @@ static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag)
case TW_Infinity:
/* Infinity*log(1) */
if ( arith_invalid(1) < 0 )
if (arith_invalid(1) < 0)
return;
break;
case TW_NaN:
if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0)
return;
break;
......@@ -1545,113 +1376,97 @@ static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag)
#endif /* PARANOID */
break;
}
}
else if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )
{
switch ( st1_tag )
{
} else if ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal)) {
switch (st1_tag) {
case TAG_Zero:
if ( signnegative(st0_ptr) )
{
if ( exponent(st0_ptr) >= 0 )
{
if (signnegative(st0_ptr)) {
if (exponent(st0_ptr) >= 0) {
/* st(0) holds <= -1.0 */
#ifdef PECULIAR_486 /* Stupid 80486 doesn't worry about log(negative). */
changesign(st1_ptr);
#else
if ( arith_invalid(1) < 0 )
if (arith_invalid(1) < 0)
return;
#endif /* PECULIAR_486 */
}
else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
} else if ((st0_tag == TW_Denormal)
&& (denormal_operand() < 0))
return;
else
changesign(st1_ptr);
}
else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
} else if ((st0_tag == TW_Denormal)
&& (denormal_operand() < 0))
return;
break;
case TW_Infinity:
if ( signnegative(st0_ptr) )
{
if ( (exponent(st0_ptr) >= 0) &&
if (signnegative(st0_ptr)) {
if ((exponent(st0_ptr) >= 0) &&
!((st0_ptr->sigh == 0x80000000) &&
(st0_ptr->sigl == 0)) )
{
(st0_ptr->sigl == 0))) {
/* st(0) holds < -1.0 */
#ifdef PECULIAR_486 /* Stupid 80486 doesn't worry about log(negative). */
changesign(st1_ptr);
#else
if ( arith_invalid(1) < 0 ) return;
if (arith_invalid(1) < 0)
return;
#endif /* PECULIAR_486 */
}
else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
} else if ((st0_tag == TW_Denormal)
&& (denormal_operand() < 0))
return;
else
changesign(st1_ptr);
}
else if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
} else if ((st0_tag == TW_Denormal)
&& (denormal_operand() < 0))
return;
break;
case TW_NaN:
if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0)
return;
}
}
else if ( st0_tag == TW_NaN )
{
if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
} else if (st0_tag == TW_NaN) {
if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0)
return;
}
else if ( st0_tag == TW_Infinity )
{
if ( st1_tag == TW_NaN )
{
if ( real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0 )
} else if (st0_tag == TW_Infinity) {
if (st1_tag == TW_NaN) {
if (real_2op_NaN(st0_ptr, st0_tag, 1, st0_ptr) < 0)
return;
}
else if ( signnegative(st0_ptr) )
{
} else if (signnegative(st0_ptr)) {
#ifndef PECULIAR_486
/* This should have higher priority than denormals, but... */
if ( arith_invalid(1) < 0 ) /* log(-infinity) */
if (arith_invalid(1) < 0) /* log(-infinity) */
return;
#endif /* PECULIAR_486 */
if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
if ((st1_tag == TW_Denormal)
&& (denormal_operand() < 0))
return;
#ifdef PECULIAR_486
/* Denormal operands actually get higher priority */
if ( arith_invalid(1) < 0 ) /* log(-infinity) */
if (arith_invalid(1) < 0) /* log(-infinity) */
return;
#endif /* PECULIAR_486 */
}
else if ( st1_tag == TAG_Zero )
{
} else if (st1_tag == TAG_Zero) {
/* log(infinity) */
if ( arith_invalid(1) < 0 )
if (arith_invalid(1) < 0)
return;
}
/* st(1) must be valid here. */
else if ( (st1_tag == TW_Denormal) && (denormal_operand() < 0) )
else if ((st1_tag == TW_Denormal) && (denormal_operand() < 0))
return;
/* The Manual says that log(Infinity) is invalid, but a real
80486 sensibly says that it is o.k. */
else
{
else {
u_char sign = getsign(st1_ptr);
FPU_copy_to_reg1(&CONST_INF, TAG_Special);
setsign(st1_ptr, sign);
}
}
#ifdef PARANOID
else
{
else {
EXCEPTION(EX_INTERNAL | 0x117);
return;
}
......@@ -1662,8 +1477,7 @@ static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag)
}
static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
static void fscale(FPU_REG * st0_ptr, u_char st0_tag)
{
FPU_REG *st1_ptr = &st(1);
u_char st1_tag = FPU_gettagi(1);
......@@ -1671,8 +1485,7 @@ static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
u_char sign = getsign(st0_ptr);
clear_C1();
if ( !((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid)) )
{
if (!((st0_tag ^ TAG_Valid) | (st1_tag ^ TAG_Valid))) {
long scale;
FPU_REG tmp;
......@@ -1681,17 +1494,13 @@ static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
valid_scale:
if ( exponent(st1_ptr) > 30 )
{
if (exponent(st1_ptr) > 30) {
/* 2^31 is far too large, would require 2^(2^30) or 2^(-2^30) */
if ( signpositive(st1_ptr) )
{
if (signpositive(st1_ptr)) {
EXCEPTION(EX_Overflow);
FPU_copy_to_reg0(&CONST_INF, TAG_Special);
}
else
{
} else {
EXCEPTION(EX_Underflow);
FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
}
......@@ -1715,25 +1524,24 @@ static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
return;
}
if ( st0_tag == TAG_Special )
if (st0_tag == TAG_Special)
st0_tag = FPU_Special(st0_ptr);
if ( st1_tag == TAG_Special )
if (st1_tag == TAG_Special)
st1_tag = FPU_Special(st1_ptr);
if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )
{
switch ( st1_tag )
{
if ((st0_tag == TAG_Valid) || (st0_tag == TW_Denormal)) {
switch (st1_tag) {
case TAG_Valid:
/* st(0) must be a denormal */
if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
if ((st0_tag == TW_Denormal)
&& (denormal_operand() < 0))
return;
FPU_to_exp16(st0_ptr, st0_ptr); /* Will not be left on stack */
goto valid_scale;
case TAG_Zero:
if ( st0_tag == TW_Denormal )
if (st0_tag == TW_Denormal)
denormal_operand();
return;
......@@ -1742,10 +1550,11 @@ static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
return;
case TW_Infinity:
if ( (st0_tag == TW_Denormal) && (denormal_operand() < 0) )
if ((st0_tag == TW_Denormal)
&& (denormal_operand() < 0))
return;
if ( signpositive(st1_ptr) )
if (signpositive(st1_ptr))
FPU_copy_to_reg0(&CONST_INF, TAG_Special);
else
FPU_copy_to_reg0(&CONST_Z, TAG_Zero);
......@@ -1756,11 +1565,8 @@ static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
return;
}
}
else if ( st0_tag == TAG_Zero )
{
switch ( st1_tag )
{
} else if (st0_tag == TAG_Zero) {
switch (st1_tag) {
case TAG_Valid:
case TAG_Zero:
return;
......@@ -1770,7 +1576,7 @@ static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
return;
case TW_Infinity:
if ( signpositive(st1_ptr) )
if (signpositive(st1_ptr))
arith_invalid(0); /* Zero scaled by +Infinity */
return;
......@@ -1778,11 +1584,8 @@ static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
return;
}
}
else if ( st0_tag == TW_Infinity )
{
switch ( st1_tag )
{
} else if (st0_tag == TW_Infinity) {
switch (st1_tag) {
case TAG_Valid:
case TAG_Zero:
return;
......@@ -1792,7 +1595,7 @@ static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
return;
case TW_Infinity:
if ( signnegative(st1_ptr) )
if (signnegative(st1_ptr))
arith_invalid(0); /* Infinity scaled by -Infinity */
return;
......@@ -1800,16 +1603,14 @@ static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
return;
}
} else if (st0_tag == TW_NaN) {
if (st1_tag != TAG_Empty) {
real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr);
return;
}
else if ( st0_tag == TW_NaN )
{
if ( st1_tag != TAG_Empty )
{ real_2op_NaN(st1_ptr, st1_tag, 0, st0_ptr); return; }
}
#ifdef PARANOID
if ( !((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty)) )
{
if (!((st0_tag == TAG_Empty) || (st1_tag == TAG_Empty))) {
EXCEPTION(EX_INTERNAL | 0x115);
return;
}
......@@ -1820,26 +1621,23 @@ static void fscale(FPU_REG *st0_ptr, u_char st0_tag)
}
/*---------------------------------------------------------------------------*/
static FUNC_ST0 const trig_table_a[] = {
f2xm1, fyl2x, fptan, fpatan,
fxtract, fprem1, (FUNC_ST0)fdecstp, (FUNC_ST0)fincstp
fxtract, fprem1, (FUNC_ST0) fdecstp, (FUNC_ST0) fincstp
};
void FPU_triga(void)
{
(trig_table_a[FPU_rm])(&st(0), FPU_gettag0());
(trig_table_a[FPU_rm]) (&st(0), FPU_gettag0());
}
static FUNC_ST0 const trig_table_b[] =
{
fprem, fyl2xp1, fsqrt_, fsincos, frndint_, fscale, (FUNC_ST0)fsin, fcos
};
static FUNC_ST0 const trig_table_b[] = {
fprem, fyl2xp1, fsqrt_, fsincos, frndint_, fscale, (FUNC_ST0) fsin, fcos
};
void FPU_trigb(void)
{
(trig_table_b[FPU_rm])(&st(0), FPU_gettag0());
(trig_table_b[FPU_rm]) (&st(0), FPU_gettag0());
}
......@@ -17,7 +17,6 @@
| other processes using the emulator while swapping is in progress. |
+---------------------------------------------------------------------------*/
#include <linux/stddef.h>
#include <asm/uaccess.h>
......@@ -27,31 +26,30 @@
#include "exception.h"
#include "fpu_emu.h"
#define FPU_WRITE_BIT 0x10
static int reg_offset[] = {
offsetof(struct info,___eax),
offsetof(struct info,___ecx),
offsetof(struct info,___edx),
offsetof(struct info,___ebx),
offsetof(struct info,___esp),
offsetof(struct info,___ebp),
offsetof(struct info,___esi),
offsetof(struct info,___edi)
offsetof(struct info, ___eax),
offsetof(struct info, ___ecx),
offsetof(struct info, ___edx),
offsetof(struct info, ___ebx),
offsetof(struct info, ___esp),
offsetof(struct info, ___ebp),
offsetof(struct info, ___esi),
offsetof(struct info, ___edi)
};
#define REG_(x) (*(long *)(reg_offset[(x)]+(u_char *) FPU_info))
static int reg_offset_vm86[] = {
offsetof(struct info,___cs),
offsetof(struct info,___vm86_ds),
offsetof(struct info,___vm86_es),
offsetof(struct info,___vm86_fs),
offsetof(struct info,___vm86_gs),
offsetof(struct info,___ss),
offsetof(struct info,___vm86_ds)
};
offsetof(struct info, ___cs),
offsetof(struct info, ___vm86_ds),
offsetof(struct info, ___vm86_es),
offsetof(struct info, ___vm86_fs),
offsetof(struct info, ___vm86_gs),
offsetof(struct info, ___ss),
offsetof(struct info, ___vm86_ds)
};
#define VM86_REG_(x) (*(unsigned short *) \
(reg_offset_vm86[((unsigned)x)]+(u_char *) FPU_info))
......@@ -60,23 +58,22 @@ static int reg_offset_vm86[] = {
#define ___GS ___ds
static int reg_offset_pm[] = {
offsetof(struct info,___cs),
offsetof(struct info,___ds),
offsetof(struct info,___es),
offsetof(struct info,___fs),
offsetof(struct info,___GS),
offsetof(struct info,___ss),
offsetof(struct info,___ds)
};
offsetof(struct info, ___cs),
offsetof(struct info, ___ds),
offsetof(struct info, ___es),
offsetof(struct info, ___fs),
offsetof(struct info, ___GS),
offsetof(struct info, ___ss),
offsetof(struct info, ___ds)
};
#define PM_REG_(x) (*(unsigned short *) \
(reg_offset_pm[((unsigned)x)]+(u_char *) FPU_info))
/* Decode the SIB byte. This function assumes mod != 0 */
static int sib(int mod, unsigned long *fpu_eip)
{
u_char ss,index,base;
u_char ss, index, base;
long offset;
RE_ENTRANT_CHECK_OFF;
......@@ -93,36 +90,30 @@ static int sib(int mod, unsigned long *fpu_eip)
else
offset = REG_(base);
if (index == 4)
{
if (index == 4) {
/* No index register */
/* A non-zero ss is illegal */
if ( ss )
if (ss)
EXCEPTION(EX_Invalid);
}
else
{
} else {
offset += (REG_(index)) << ss;
}
if (mod == 1)
{
if (mod == 1) {
/* 8 bit signed displacement */
long displacement;
RE_ENTRANT_CHECK_OFF;
FPU_code_access_ok(1);
FPU_get_user(displacement, (signed char __user *) (*fpu_eip));
FPU_get_user(displacement, (signed char __user *)(*fpu_eip));
offset += displacement;
RE_ENTRANT_CHECK_ON;
(*fpu_eip)++;
}
else if (mod == 2 || base == 5) /* The second condition also has mod==0 */
{
} else if (mod == 2 || base == 5) { /* The second condition also has mod==0 */
/* 32 bit displacement */
long displacement;
RE_ENTRANT_CHECK_OFF;
FPU_code_access_ok(4);
FPU_get_user(displacement, (long __user *) (*fpu_eip));
FPU_get_user(displacement, (long __user *)(*fpu_eip));
offset += displacement;
RE_ENTRANT_CHECK_ON;
(*fpu_eip) += 4;
......@@ -131,23 +122,19 @@ static int sib(int mod, unsigned long *fpu_eip)
return offset;
}
static unsigned long vm86_segment(u_char segment,
struct address *addr)
static unsigned long vm86_segment(u_char segment, struct address *addr)
{
segment--;
#ifdef PARANOID
if ( segment > PREFIX_SS_ )
{
EXCEPTION(EX_INTERNAL|0x130);
math_abort(FPU_info,SIGSEGV);
if (segment > PREFIX_SS_) {
EXCEPTION(EX_INTERNAL | 0x130);
math_abort(FPU_info, SIGSEGV);
}
#endif /* PARANOID */
addr->selector = VM86_REG_(segment);
return (unsigned long)VM86_REG_(segment) << 4;
}
/* This should work for 16 and 32 bit protected mode. */
static long pm_address(u_char FPU_modrm, u_char segment,
struct address *addr, long offset)
......@@ -159,18 +146,16 @@ static long pm_address(u_char FPU_modrm, u_char segment,
#ifdef PARANOID
/* segment is unsigned, so this also detects if segment was 0: */
if ( segment > PREFIX_SS_ )
{
EXCEPTION(EX_INTERNAL|0x132);
math_abort(FPU_info,SIGSEGV);
if (segment > PREFIX_SS_) {
EXCEPTION(EX_INTERNAL | 0x132);
math_abort(FPU_info, SIGSEGV);
}
#endif /* PARANOID */
switch ( segment )
{
switch (segment) {
/* gs isn't used by the kernel, so it still has its
user-space value. */
case PREFIX_GS_-1:
case PREFIX_GS_ - 1:
/* N.B. - movl %seg, mem is a 2 byte write regardless of prefix */
savesegment(gs, addr->selector);
break;
......@@ -182,37 +167,33 @@ static long pm_address(u_char FPU_modrm, u_char segment,
base_address = SEG_BASE_ADDR(descriptor);
address = base_address + offset;
limit = base_address
+ (SEG_LIMIT(descriptor)+1) * SEG_GRANULARITY(descriptor) - 1;
if ( limit < base_address ) limit = 0xffffffff;
+ (SEG_LIMIT(descriptor) + 1) * SEG_GRANULARITY(descriptor) - 1;
if (limit < base_address)
limit = 0xffffffff;
if ( SEG_EXPAND_DOWN(descriptor) )
{
if ( SEG_G_BIT(descriptor) )
if (SEG_EXPAND_DOWN(descriptor)) {
if (SEG_G_BIT(descriptor))
seg_top = 0xffffffff;
else
{
else {
seg_top = base_address + (1 << 20);
if ( seg_top < base_address ) seg_top = 0xffffffff;
if (seg_top < base_address)
seg_top = 0xffffffff;
}
access_limit =
(address <= limit) || (address >= seg_top) ? 0 :
((seg_top-address) >= 255 ? 255 : seg_top-address);
}
else
{
((seg_top - address) >= 255 ? 255 : seg_top - address);
} else {
access_limit =
(address > limit) || (address < base_address) ? 0 :
((limit-address) >= 254 ? 255 : limit-address+1);
((limit - address) >= 254 ? 255 : limit - address + 1);
}
if ( SEG_EXECUTE_ONLY(descriptor) ||
(!SEG_WRITE_PERM(descriptor) && (FPU_modrm & FPU_WRITE_BIT)) )
{
if (SEG_EXECUTE_ONLY(descriptor) ||
(!SEG_WRITE_PERM(descriptor) && (FPU_modrm & FPU_WRITE_BIT))) {
access_limit = 0;
}
return address;
}
/*
MOD R/M byte: MOD == 3 has a special use for the FPU
SIB byte used iff R/M = 100b
......@@ -221,7 +202,6 @@ static long pm_address(u_char FPU_modrm, u_char segment,
..... ......... .........
MOD OPCODE(2) R/M
SIB byte
7 6 5 4 3 2 1 0
......@@ -231,8 +211,7 @@ static long pm_address(u_char FPU_modrm, u_char segment,
*/
void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
struct address *addr,
fpu_addr_modes addr_modes)
struct address *addr, fpu_addr_modes addr_modes)
{
u_char mod;
unsigned rm = FPU_modrm & 7;
......@@ -241,49 +220,43 @@ void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
/* Memory accessed via the cs selector is write protected
in `non-segmented' 32 bit protected mode. */
if ( !addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT)
&& (addr_modes.override.segment == PREFIX_CS_) )
{
math_abort(FPU_info,SIGSEGV);
if (!addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT)
&& (addr_modes.override.segment == PREFIX_CS_)) {
math_abort(FPU_info, SIGSEGV);
}
addr->selector = FPU_DS; /* Default, for 32 bit non-segmented mode. */
mod = (FPU_modrm >> 6) & 3;
if (rm == 4 && mod != 3)
{
if (rm == 4 && mod != 3) {
address = sib(mod, fpu_eip);
}
else
{
cpu_reg_ptr = & REG_(rm);
switch (mod)
{
} else {
cpu_reg_ptr = &REG_(rm);
switch (mod) {
case 0:
if (rm == 5)
{
if (rm == 5) {
/* Special case: disp32 */
RE_ENTRANT_CHECK_OFF;
FPU_code_access_ok(4);
FPU_get_user(address, (unsigned long __user *) (*fpu_eip));
FPU_get_user(address,
(unsigned long __user
*)(*fpu_eip));
(*fpu_eip) += 4;
RE_ENTRANT_CHECK_ON;
addr->offset = address;
return (void __user *) address;
}
else
{
return (void __user *)address;
} else {
address = *cpu_reg_ptr; /* Just return the contents
of the cpu register */
addr->offset = address;
return (void __user *) address;
return (void __user *)address;
}
case 1:
/* 8 bit signed displacement */
RE_ENTRANT_CHECK_OFF;
FPU_code_access_ok(1);
FPU_get_user(address, (signed char __user *) (*fpu_eip));
FPU_get_user(address, (signed char __user *)(*fpu_eip));
RE_ENTRANT_CHECK_ON;
(*fpu_eip)++;
break;
......@@ -291,7 +264,7 @@ void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
/* 32 bit displacement */
RE_ENTRANT_CHECK_OFF;
FPU_code_access_ok(4);
FPU_get_user(address, (long __user *) (*fpu_eip));
FPU_get_user(address, (long __user *)(*fpu_eip));
(*fpu_eip) += 4;
RE_ENTRANT_CHECK_ON;
break;
......@@ -304,8 +277,7 @@ void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
addr->offset = address;
switch ( addr_modes.default_mode )
{
switch (addr_modes.default_mode) {
case 0:
break;
case VM86:
......@@ -317,16 +289,14 @@ void __user *FPU_get_address(u_char FPU_modrm, unsigned long *fpu_eip,
addr, address);
break;
default:
EXCEPTION(EX_INTERNAL|0x133);
EXCEPTION(EX_INTERNAL | 0x133);
}
return (void __user *)address;
}
void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
struct address *addr,
fpu_addr_modes addr_modes)
struct address *addr, fpu_addr_modes addr_modes)
{
u_char mod;
unsigned rm = FPU_modrm & 7;
......@@ -334,25 +304,23 @@ void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
/* Memory accessed via the cs selector is write protected
in `non-segmented' 32 bit protected mode. */
if ( !addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT)
&& (addr_modes.override.segment == PREFIX_CS_) )
{
math_abort(FPU_info,SIGSEGV);
if (!addr_modes.default_mode && (FPU_modrm & FPU_WRITE_BIT)
&& (addr_modes.override.segment == PREFIX_CS_)) {
math_abort(FPU_info, SIGSEGV);
}
addr->selector = FPU_DS; /* Default, for 32 bit non-segmented mode. */
mod = (FPU_modrm >> 6) & 3;
switch (mod)
{
switch (mod) {
case 0:
if (rm == 6)
{
if (rm == 6) {
/* Special case: disp16 */
RE_ENTRANT_CHECK_OFF;
FPU_code_access_ok(2);
FPU_get_user(address, (unsigned short __user *) (*fpu_eip));
FPU_get_user(address,
(unsigned short __user *)(*fpu_eip));
(*fpu_eip) += 2;
RE_ENTRANT_CHECK_ON;
goto add_segment;
......@@ -362,7 +330,7 @@ void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
/* 8 bit signed displacement */
RE_ENTRANT_CHECK_OFF;
FPU_code_access_ok(1);
FPU_get_user(address, (signed char __user *) (*fpu_eip));
FPU_get_user(address, (signed char __user *)(*fpu_eip));
RE_ENTRANT_CHECK_ON;
(*fpu_eip)++;
break;
......@@ -370,7 +338,7 @@ void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
/* 16 bit displacement */
RE_ENTRANT_CHECK_OFF;
FPU_code_access_ok(2);
FPU_get_user(address, (unsigned short __user *) (*fpu_eip));
FPU_get_user(address, (unsigned short __user *)(*fpu_eip));
(*fpu_eip) += 2;
RE_ENTRANT_CHECK_ON;
break;
......@@ -379,8 +347,7 @@ void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
EXCEPTION(EX_Invalid);
break;
}
switch ( rm )
{
switch (rm) {
case 0:
address += FPU_info->___ebx + FPU_info->___esi;
break;
......@@ -389,12 +356,12 @@ void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
break;
case 2:
address += FPU_info->___ebp + FPU_info->___esi;
if ( addr_modes.override.segment == PREFIX_DEFAULT )
if (addr_modes.override.segment == PREFIX_DEFAULT)
addr_modes.override.segment = PREFIX_SS_;
break;
case 3:
address += FPU_info->___ebp + FPU_info->___edi;
if ( addr_modes.override.segment == PREFIX_DEFAULT )
if (addr_modes.override.segment == PREFIX_DEFAULT)
addr_modes.override.segment = PREFIX_SS_;
break;
case 4:
......@@ -405,7 +372,7 @@ void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
break;
case 6:
address += FPU_info->___ebp;
if ( addr_modes.override.segment == PREFIX_DEFAULT )
if (addr_modes.override.segment == PREFIX_DEFAULT)
addr_modes.override.segment = PREFIX_SS_;
break;
case 7:
......@@ -418,8 +385,7 @@ void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
addr->offset = address;
switch ( addr_modes.default_mode )
{
switch (addr_modes.default_mode) {
case 0:
break;
case VM86:
......@@ -431,8 +397,8 @@ void __user *FPU_get_address_16(u_char FPU_modrm, unsigned long *fpu_eip,
addr, address);
break;
default:
EXCEPTION(EX_INTERNAL|0x131);
EXCEPTION(EX_INTERNAL | 0x131);
}
return (void __user *)address ;
return (void __user *)address;
}
......@@ -26,7 +26,6 @@
#include "status_w.h"
#include "control_w.h"
#define _NONE_ 0 /* st0_ptr etc not needed */
#define _REG0_ 1 /* Will be storing st(0) */
#define _PUSH_ 3 /* Need to check for space to push onto stack */
......@@ -34,7 +33,6 @@
#define pop_0() { FPU_settag0(TAG_Empty); top++; }
static u_char const type_table[32] = {
_PUSH_, _PUSH_, _PUSH_, _PUSH_,
_null_, _null_, _null_, _null_,
......@@ -44,7 +42,7 @@ static u_char const type_table[32] = {
_NONE_, _PUSH_, _null_, _PUSH_,
_NONE_, _null_, _NONE_, _REG0_,
_NONE_, _REG0_, _NONE_, _REG0_
};
};
u_char const data_sizes_16[32] = {
4, 4, 8, 2, 0, 0, 0, 0,
......@@ -56,12 +54,12 @@ u_char const data_sizes_16[32] = {
static u_char const data_sizes_32[32] = {
4, 4, 8, 2, 0, 0, 0, 0,
4, 4, 8, 2, 4, 4, 8, 2,
28, 0,108, 10, 2, 10, 0, 8,
28, 0,108, 10, 2, 10, 2, 8
28, 0, 108, 10, 2, 10, 0, 8,
28, 0, 108, 10, 2, 10, 2, 8
};
int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
void __user *data_address)
void __user * data_address)
{
FPU_REG loaded_data;
FPU_REG *st0_ptr;
......@@ -70,26 +68,21 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
st0_ptr = NULL; /* Initialized just to stop compiler warnings. */
if ( addr_modes.default_mode & PROTECTED )
{
if ( addr_modes.default_mode == SEG32 )
{
if ( access_limit < data_sizes_32[type] )
math_abort(FPU_info,SIGSEGV);
}
else if ( addr_modes.default_mode == PM16 )
{
if ( access_limit < data_sizes_16[type] )
math_abort(FPU_info,SIGSEGV);
if (addr_modes.default_mode & PROTECTED) {
if (addr_modes.default_mode == SEG32) {
if (access_limit < data_sizes_32[type])
math_abort(FPU_info, SIGSEGV);
} else if (addr_modes.default_mode == PM16) {
if (access_limit < data_sizes_16[type])
math_abort(FPU_info, SIGSEGV);
}
#ifdef PARANOID
else
EXCEPTION(EX_INTERNAL|0x140);
EXCEPTION(EX_INTERNAL | 0x140);
#endif /* PARANOID */
}
switch ( type_table[type] )
{
switch (type_table[type]) {
case _NONE_:
break;
case _REG0_:
......@@ -99,8 +92,10 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
break;
case _PUSH_:
{
if ( FPU_gettagi(-1) != TAG_Empty )
{ FPU_stack_overflow(); return 0; }
if (FPU_gettagi(-1) != TAG_Empty) {
FPU_stack_overflow();
return 0;
}
top--;
st0_ptr = &st(0);
}
......@@ -110,20 +105,19 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
return 0;
#ifdef PARANOID
default:
EXCEPTION(EX_INTERNAL|0x141);
EXCEPTION(EX_INTERNAL | 0x141);
return 0;
#endif /* PARANOID */
}
switch ( type )
{
switch (type) {
case 000: /* fld m32real */
clear_C1();
loaded_tag = FPU_load_single((float __user *)data_address, &loaded_data);
if ( (loaded_tag == TAG_Special)
loaded_tag =
FPU_load_single((float __user *)data_address, &loaded_data);
if ((loaded_tag == TAG_Special)
&& isNaN(&loaded_data)
&& (real_1op_NaN(&loaded_data) < 0) )
{
&& (real_1op_NaN(&loaded_data) < 0)) {
top++;
break;
}
......@@ -131,16 +125,18 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
break;
case 001: /* fild m32int */
clear_C1();
loaded_tag = FPU_load_int32((long __user *)data_address, &loaded_data);
loaded_tag =
FPU_load_int32((long __user *)data_address, &loaded_data);
FPU_copy_to_reg0(&loaded_data, loaded_tag);
break;
case 002: /* fld m64real */
clear_C1();
loaded_tag = FPU_load_double((double __user *)data_address, &loaded_data);
if ( (loaded_tag == TAG_Special)
loaded_tag =
FPU_load_double((double __user *)data_address,
&loaded_data);
if ((loaded_tag == TAG_Special)
&& isNaN(&loaded_data)
&& (real_1op_NaN(&loaded_data) < 0) )
{
&& (real_1op_NaN(&loaded_data) < 0)) {
top++;
break;
}
......@@ -148,12 +144,14 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
break;
case 003: /* fild m16int */
clear_C1();
loaded_tag = FPU_load_int16((short __user *)data_address, &loaded_data);
loaded_tag =
FPU_load_int16((short __user *)data_address, &loaded_data);
FPU_copy_to_reg0(&loaded_data, loaded_tag);
break;
case 010: /* fst m32real */
clear_C1();
FPU_store_single(st0_ptr, st0_tag, (float __user *)data_address);
FPU_store_single(st0_ptr, st0_tag,
(float __user *)data_address);
break;
case 011: /* fist m32int */
clear_C1();
......@@ -161,7 +159,8 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
break;
case 012: /* fst m64real */
clear_C1();
FPU_store_double(st0_ptr, st0_tag, (double __user *)data_address);
FPU_store_double(st0_ptr, st0_tag,
(double __user *)data_address);
break;
case 013: /* fist m16int */
clear_C1();
......@@ -169,49 +168,54 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
break;
case 014: /* fstp m32real */
clear_C1();
if ( FPU_store_single(st0_ptr, st0_tag, (float __user *)data_address) )
if (FPU_store_single
(st0_ptr, st0_tag, (float __user *)data_address))
pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */
break;
case 015: /* fistp m32int */
clear_C1();
if ( FPU_store_int32(st0_ptr, st0_tag, (long __user *)data_address) )
if (FPU_store_int32
(st0_ptr, st0_tag, (long __user *)data_address))
pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */
break;
case 016: /* fstp m64real */
clear_C1();
if ( FPU_store_double(st0_ptr, st0_tag, (double __user *)data_address) )
if (FPU_store_double
(st0_ptr, st0_tag, (double __user *)data_address))
pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */
break;
case 017: /* fistp m16int */
clear_C1();
if ( FPU_store_int16(st0_ptr, st0_tag, (short __user *)data_address) )
if (FPU_store_int16
(st0_ptr, st0_tag, (short __user *)data_address))
pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */
break;
case 020: /* fldenv m14/28byte */
fldenv(addr_modes, (u_char __user *)data_address);
fldenv(addr_modes, (u_char __user *) data_address);
/* Ensure that the values just loaded are not changed by
fix-up operations. */
return 1;
case 022: /* frstor m94/108byte */
frstor(addr_modes, (u_char __user *)data_address);
frstor(addr_modes, (u_char __user *) data_address);
/* Ensure that the values just loaded are not changed by
fix-up operations. */
return 1;
case 023: /* fbld m80dec */
clear_C1();
loaded_tag = FPU_load_bcd((u_char __user *)data_address);
loaded_tag = FPU_load_bcd((u_char __user *) data_address);
FPU_settag0(loaded_tag);
break;
case 024: /* fldcw */
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_READ, data_address, 2);
FPU_get_user(control_word, (unsigned short __user *) data_address);
FPU_get_user(control_word,
(unsigned short __user *)data_address);
RE_ENTRANT_CHECK_ON;
if ( partial_status & ~control_word & CW_Exceptions )
if (partial_status & ~control_word & CW_Exceptions)
partial_status |= (SW_Summary | SW_Backward);
else
partial_status &= ~(SW_Summary | SW_Backward);
......@@ -221,7 +225,8 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
return 1;
case 025: /* fld m80real */
clear_C1();
loaded_tag = FPU_load_extended((long double __user *)data_address, 0);
loaded_tag =
FPU_load_extended((long double __user *)data_address, 0);
FPU_settag0(loaded_tag);
break;
case 027: /* fild m64int */
......@@ -232,38 +237,43 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
FPU_settag0(loaded_tag);
break;
case 030: /* fstenv m14/28byte */
fstenv(addr_modes, (u_char __user *)data_address);
fstenv(addr_modes, (u_char __user *) data_address);
return 1;
case 032: /* fsave */
fsave(addr_modes, (u_char __user *)data_address);
fsave(addr_modes, (u_char __user *) data_address);
return 1;
case 033: /* fbstp m80dec */
clear_C1();
if ( FPU_store_bcd(st0_ptr, st0_tag, (u_char __user *)data_address) )
if (FPU_store_bcd
(st0_ptr, st0_tag, (u_char __user *) data_address))
pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */
break;
case 034: /* fstcw m16int */
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE,data_address,2);
FPU_put_user(control_word, (unsigned short __user *) data_address);
FPU_access_ok(VERIFY_WRITE, data_address, 2);
FPU_put_user(control_word,
(unsigned short __user *)data_address);
RE_ENTRANT_CHECK_ON;
return 1;
case 035: /* fstp m80real */
clear_C1();
if ( FPU_store_extended(st0_ptr, st0_tag, (long double __user *)data_address) )
if (FPU_store_extended
(st0_ptr, st0_tag, (long double __user *)data_address))
pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */
break;
case 036: /* fstsw m2byte */
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE,data_address,2);
FPU_put_user(status_word(),(unsigned short __user *) data_address);
FPU_access_ok(VERIFY_WRITE, data_address, 2);
FPU_put_user(status_word(),
(unsigned short __user *)data_address);
RE_ENTRANT_CHECK_ON;
return 1;
case 037: /* fistp m64int */
clear_C1();
if ( FPU_store_int64(st0_ptr, st0_tag, (long long __user *)data_address) )
if (FPU_store_int64
(st0_ptr, st0_tag, (long long __user *)data_address))
pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */
break;
......
......@@ -33,12 +33,12 @@ asmlinkage void polynomial_Xsig(Xsig *, const unsigned long long *x,
asmlinkage void mul32_Xsig(Xsig *, const unsigned long mult);
asmlinkage void mul64_Xsig(Xsig *, const unsigned long long *mult);
asmlinkage void mul_Xsig_Xsig(Xsig *dest, const Xsig *mult);
asmlinkage void mul_Xsig_Xsig(Xsig * dest, const Xsig * mult);
asmlinkage void shr_Xsig(Xsig *, const int n);
asmlinkage int round_Xsig(Xsig *);
asmlinkage int norm_Xsig(Xsig *);
asmlinkage void div_Xsig(Xsig *x1, const Xsig *x2, const Xsig *dest);
asmlinkage void div_Xsig(Xsig * x1, const Xsig * x2, const Xsig * dest);
/* Macro to extract the most significant 32 bits from a long long */
#define LL_MSW(x) (((unsigned long *)&x)[1])
......@@ -49,7 +49,6 @@ asmlinkage void div_Xsig(Xsig *x1, const Xsig *x2, const Xsig *dest);
/* Macro to access the 8 ms bytes of an Xsig as a long long */
#define XSIG_LL(x) (*(unsigned long long *)&x.midw)
/*
Need to run gcc with optimizations on to get these to
actually be in-line.
......@@ -64,31 +63,28 @@ static inline unsigned long mul_32_32(const unsigned long arg1,
const unsigned long arg2)
{
int retval;
asm volatile ("mull %2; movl %%edx,%%eax" \
:"=a" (retval) \
:"0" (arg1), "g" (arg2) \
asm volatile ("mull %2; movl %%edx,%%eax":"=a" (retval)
:"0"(arg1), "g"(arg2)
:"dx");
return retval;
}
/* Add the 12 byte Xsig x2 to Xsig dest, with no checks for overflow. */
static inline void add_Xsig_Xsig(Xsig *dest, const Xsig *x2)
static inline void add_Xsig_Xsig(Xsig * dest, const Xsig * x2)
{
asm volatile ("movl %1,%%edi; movl %2,%%esi;\n"
"movl (%%esi),%%eax; addl %%eax,(%%edi);\n"
"movl 4(%%esi),%%eax; adcl %%eax,4(%%edi);\n"
"movl 8(%%esi),%%eax; adcl %%eax,8(%%edi);\n"
:"=g" (*dest):"g" (dest), "g" (x2)
:"ax","si","di");
"movl 8(%%esi),%%eax; adcl %%eax,8(%%edi);\n":"=g"
(*dest):"g"(dest), "g"(x2)
:"ax", "si", "di");
}
/* Add the 12 byte Xsig x2 to Xsig dest, adjust exp if overflow occurs. */
/* Note: the constraints in the asm statement didn't always work properly
with gcc 2.5.8. Changing from using edi to using ecx got around the
problem, but keep fingers crossed! */
static inline void add_two_Xsig(Xsig *dest, const Xsig *x2, long int *exp)
static inline void add_two_Xsig(Xsig * dest, const Xsig * x2, long int *exp)
{
asm volatile ("movl %2,%%ecx; movl %3,%%esi;\n"
"movl (%%esi),%%eax; addl %%eax,(%%ecx);\n"
......@@ -98,24 +94,21 @@ static inline void add_two_Xsig(Xsig *dest, const Xsig *x2, long int *exp)
"rcrl 8(%%ecx); rcrl 4(%%ecx); rcrl (%%ecx)\n"
"movl %4,%%ecx; incl (%%ecx)\n"
"movl $1,%%eax; jmp 1f;\n"
"0: xorl %%eax,%%eax;\n"
"1:\n"
:"=g" (*exp), "=g" (*dest)
:"g" (dest), "g" (x2), "g" (exp)
:"cx","si","ax");
"0: xorl %%eax,%%eax;\n" "1:\n":"=g" (*exp), "=g"(*dest)
:"g"(dest), "g"(x2), "g"(exp)
:"cx", "si", "ax");
}
/* Negate (subtract from 1.0) the 12 byte Xsig */
/* This is faster in a loop on my 386 than using the "neg" instruction. */
static inline void negate_Xsig(Xsig *x)
static inline void negate_Xsig(Xsig * x)
{
asm volatile("movl %1,%%esi;\n"
asm volatile ("movl %1,%%esi;\n"
"xorl %%ecx,%%ecx;\n"
"movl %%ecx,%%eax; subl (%%esi),%%eax; movl %%eax,(%%esi);\n"
"movl %%ecx,%%eax; sbbl 4(%%esi),%%eax; movl %%eax,4(%%esi);\n"
"movl %%ecx,%%eax; sbbl 8(%%esi),%%eax; movl %%eax,8(%%esi);\n"
:"=g" (*x):"g" (x):"si","ax","cx");
"movl %%ecx,%%eax; sbbl 8(%%esi),%%eax; movl %%eax,8(%%esi);\n":"=g"
(*x):"g"(x):"si", "ax", "cx");
}
#endif /* _POLY_H */
......@@ -17,10 +17,8 @@
#include "control_w.h"
#include "poly.h"
#define HIPOWER 11
static const unsigned long long lterms[HIPOWER] =
{
static const unsigned long long lterms[HIPOWER] = {
0x0000000000000000LL, /* This term done separately as 12 bytes */
0xf5fdeffc162c7543LL,
0x1c6b08d704a0bfa6LL,
......@@ -45,13 +43,13 @@ static const Xsig shiftterm2 = MK_XSIG(0xb504f333, 0xf9de6484, 0x597d89b3);
static const Xsig shiftterm3 = MK_XSIG(0xd744fcca, 0xd69d6af4, 0x39a68bb9);
static const Xsig *shiftterm[] = { &shiftterm0, &shiftterm1,
&shiftterm2, &shiftterm3 };
&shiftterm2, &shiftterm3
};
/*--- poly_2xm1() -----------------------------------------------------------+
| Requires st(0) which is TAG_Valid and < 1. |
+---------------------------------------------------------------------------*/
int poly_2xm1(u_char sign, FPU_REG *arg, FPU_REG *result)
int poly_2xm1(u_char sign, FPU_REG * arg, FPU_REG * result)
{
long int exponent, shift;
unsigned long long Xll;
......@@ -61,10 +59,9 @@ int poly_2xm1(u_char sign, FPU_REG *arg, FPU_REG *result)
exponent = exponent16(arg);
#ifdef PARANOID
if ( exponent >= 0 ) /* Don't want a |number| >= 1.0 */
{
if (exponent >= 0) { /* Don't want a |number| >= 1.0 */
/* Number negative, too large, or not Valid. */
EXCEPTION(EX_INTERNAL|0x127);
EXCEPTION(EX_INTERNAL | 0x127);
return 1;
}
#endif /* PARANOID */
......@@ -72,66 +69,58 @@ int poly_2xm1(u_char sign, FPU_REG *arg, FPU_REG *result)
argSignif.lsw = 0;
XSIG_LL(argSignif) = Xll = significand(arg);
if ( exponent == -1 )
{
if (exponent == -1) {
shift = (argSignif.msw & 0x40000000) ? 3 : 2;
/* subtract 0.5 or 0.75 */
exponent -= 2;
XSIG_LL(argSignif) <<= 2;
Xll <<= 2;
}
else if ( exponent == -2 )
{
} else if (exponent == -2) {
shift = 1;
/* subtract 0.25 */
exponent--;
XSIG_LL(argSignif) <<= 1;
Xll <<= 1;
}
else
} else
shift = 0;
if ( exponent < -2 )
{
if (exponent < -2) {
/* Shift the argument right by the required places. */
if ( FPU_shrx(&Xll, -2-exponent) >= 0x80000000U )
if (FPU_shrx(&Xll, -2 - exponent) >= 0x80000000U)
Xll++; /* round up */
}
accumulator.lsw = accumulator.midw = accumulator.msw = 0;
polynomial_Xsig(&accumulator, &Xll, lterms, HIPOWER-1);
polynomial_Xsig(&accumulator, &Xll, lterms, HIPOWER - 1);
mul_Xsig_Xsig(&accumulator, &argSignif);
shr_Xsig(&accumulator, 3);
mul_Xsig_Xsig(&argSignif, &hiterm); /* The leading term */
add_two_Xsig(&accumulator, &argSignif, &exponent);
if ( shift )
{
if (shift) {
/* The argument is large, use the identity:
f(x+a) = f(a) * (f(x) + 1) - 1;
*/
shr_Xsig(&accumulator, - exponent);
shr_Xsig(&accumulator, -exponent);
accumulator.msw |= 0x80000000; /* add 1.0 */
mul_Xsig_Xsig(&accumulator, shiftterm[shift]);
accumulator.msw &= 0x3fffffff; /* subtract 1.0 */
exponent = 1;
}
if ( sign != SIGN_POS )
{
if (sign != SIGN_POS) {
/* The argument is negative, use the identity:
f(-x) = -f(x) / (1 + f(x))
*/
Denom.lsw = accumulator.lsw;
XSIG_LL(Denom) = XSIG_LL(accumulator);
if ( exponent < 0 )
shr_Xsig(&Denom, - exponent);
else if ( exponent > 0 )
{
if (exponent < 0)
shr_Xsig(&Denom, -exponent);
else if (exponent > 0) {
/* exponent must be 1 here */
XSIG_LL(Denom) <<= 1;
if ( Denom.lsw & 0x80000000 )
if (Denom.lsw & 0x80000000)
XSIG_LL(Denom) |= 1;
(Denom.lsw) <<= 1;
}
......
......@@ -18,21 +18,18 @@
#include "control_w.h"
#include "poly.h"
#define HIPOWERon 6 /* odd poly, negative terms */
static const unsigned long long oddnegterms[HIPOWERon] =
{
static const unsigned long long oddnegterms[HIPOWERon] = {
0x0000000000000000LL, /* Dummy (not for - 1.0) */
0x015328437f756467LL,
0x0005dda27b73dec6LL,
0x0000226bf2bfb91aLL,
0x000000ccc439c5f7LL,
0x0000000355438407LL
} ;
};
#define HIPOWERop 6 /* odd poly, positive terms */
static const unsigned long long oddplterms[HIPOWERop] =
{
static const unsigned long long oddplterms[HIPOWERop] = {
/* 0xaaaaaaaaaaaaaaabLL, transferred to fixedpterm[] */
0x0db55a71875c9ac2LL,
0x0029fce2d67880b0LL,
......@@ -48,56 +45,44 @@ static const Xsig fixedpterm = MK_XSIG(0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa);
static const Xsig pi_signif = MK_XSIG(0xc90fdaa2, 0x2168c234, 0xc4c6628b);
/*--- poly_atan() -----------------------------------------------------------+
| |
+---------------------------------------------------------------------------*/
void poly_atan(FPU_REG *st0_ptr, u_char st0_tag,
FPU_REG *st1_ptr, u_char st1_tag)
void poly_atan(FPU_REG * st0_ptr, u_char st0_tag,
FPU_REG * st1_ptr, u_char st1_tag)
{
u_char transformed, inverted,
sign1, sign2;
u_char transformed, inverted, sign1, sign2;
int exponent;
long int dummy_exp;
Xsig accumulator, Numer, Denom, accumulatore, argSignif,
argSq, argSqSq;
Xsig accumulator, Numer, Denom, accumulatore, argSignif, argSq, argSqSq;
u_char tag;
sign1 = getsign(st0_ptr);
sign2 = getsign(st1_ptr);
if ( st0_tag == TAG_Valid )
{
if (st0_tag == TAG_Valid) {
exponent = exponent(st0_ptr);
}
else
{
} else {
/* This gives non-compatible stack contents... */
FPU_to_exp16(st0_ptr, st0_ptr);
exponent = exponent16(st0_ptr);
}
if ( st1_tag == TAG_Valid )
{
if (st1_tag == TAG_Valid) {
exponent -= exponent(st1_ptr);
}
else
{
} else {
/* This gives non-compatible stack contents... */
FPU_to_exp16(st1_ptr, st1_ptr);
exponent -= exponent16(st1_ptr);
}
if ( (exponent < 0) || ((exponent == 0) &&
if ((exponent < 0) || ((exponent == 0) &&
((st0_ptr->sigh < st1_ptr->sigh) ||
((st0_ptr->sigh == st1_ptr->sigh) &&
(st0_ptr->sigl < st1_ptr->sigl))) ) )
{
(st0_ptr->sigl < st1_ptr->sigl))))) {
inverted = 1;
Numer.lsw = Denom.lsw = 0;
XSIG_LL(Numer) = significand(st0_ptr);
XSIG_LL(Denom) = significand(st1_ptr);
}
else
{
} else {
inverted = 0;
exponent = -exponent;
Numer.lsw = Denom.lsw = 0;
......@@ -107,33 +92,28 @@ void poly_atan(FPU_REG *st0_ptr, u_char st0_tag,
div_Xsig(&Numer, &Denom, &argSignif);
exponent += norm_Xsig(&argSignif);
if ( (exponent >= -1)
|| ((exponent == -2) && (argSignif.msw > 0xd413ccd0)) )
{
if ((exponent >= -1)
|| ((exponent == -2) && (argSignif.msw > 0xd413ccd0))) {
/* The argument is greater than sqrt(2)-1 (=0.414213562...) */
/* Convert the argument by an identity for atan */
transformed = 1;
if ( exponent >= 0 )
{
if (exponent >= 0) {
#ifdef PARANOID
if ( !( (exponent == 0) &&
if (!((exponent == 0) &&
(argSignif.lsw == 0) && (argSignif.midw == 0) &&
(argSignif.msw == 0x80000000) ) )
{
EXCEPTION(EX_INTERNAL|0x104); /* There must be a logic error */
(argSignif.msw == 0x80000000))) {
EXCEPTION(EX_INTERNAL | 0x104); /* There must be a logic error */
return;
}
#endif /* PARANOID */
argSignif.msw = 0; /* Make the transformed arg -> 0.0 */
}
else
{
} else {
Numer.lsw = Denom.lsw = argSignif.lsw;
XSIG_LL(Numer) = XSIG_LL(Denom) = XSIG_LL(argSignif);
if ( exponent < -1 )
shr_Xsig(&Numer, -1-exponent);
if (exponent < -1)
shr_Xsig(&Numer, -1 - exponent);
negate_Xsig(&Numer);
shr_Xsig(&Denom, -exponent);
......@@ -143,24 +123,25 @@ void poly_atan(FPU_REG *st0_ptr, u_char st0_tag,
exponent = -1 + norm_Xsig(&argSignif);
}
}
else
{
} else {
transformed = 0;
}
argSq.lsw = argSignif.lsw; argSq.midw = argSignif.midw;
argSq.lsw = argSignif.lsw;
argSq.midw = argSignif.midw;
argSq.msw = argSignif.msw;
mul_Xsig_Xsig(&argSq, &argSq);
argSqSq.lsw = argSq.lsw; argSqSq.midw = argSq.midw; argSqSq.msw = argSq.msw;
argSqSq.lsw = argSq.lsw;
argSqSq.midw = argSq.midw;
argSqSq.msw = argSq.msw;
mul_Xsig_Xsig(&argSqSq, &argSqSq);
accumulatore.lsw = argSq.lsw;
XSIG_LL(accumulatore) = XSIG_LL(argSq);
shr_Xsig(&argSq, 2*(-1-exponent-1));
shr_Xsig(&argSqSq, 4*(-1-exponent-1));
shr_Xsig(&argSq, 2 * (-1 - exponent - 1));
shr_Xsig(&argSqSq, 4 * (-1 - exponent - 1));
/* Now have argSq etc with binary point at the left
.1xxxxxxxx */
......@@ -168,15 +149,16 @@ void poly_atan(FPU_REG *st0_ptr, u_char st0_tag,
/* Do the basic fixed point polynomial evaluation */
accumulator.msw = accumulator.midw = accumulator.lsw = 0;
polynomial_Xsig(&accumulator, &XSIG_LL(argSqSq),
oddplterms, HIPOWERop-1);
oddplterms, HIPOWERop - 1);
mul64_Xsig(&accumulator, &XSIG_LL(argSq));
negate_Xsig(&accumulator);
polynomial_Xsig(&accumulator, &XSIG_LL(argSqSq), oddnegterms, HIPOWERon-1);
polynomial_Xsig(&accumulator, &XSIG_LL(argSqSq), oddnegterms,
HIPOWERon - 1);
negate_Xsig(&accumulator);
add_two_Xsig(&accumulator, &fixedpterm, &dummy_exp);
mul64_Xsig(&accumulatore, &denomterm);
shr_Xsig(&accumulatore, 1 + 2*(-1-exponent));
shr_Xsig(&accumulatore, 1 + 2 * (-1 - exponent));
accumulatore.msw |= 0x80000000;
div_Xsig(&accumulator, &accumulatore, &accumulator);
......@@ -188,17 +170,15 @@ void poly_atan(FPU_REG *st0_ptr, u_char st0_tag,
negate_Xsig(&accumulator);
add_Xsig_Xsig(&accumulator, &argSignif);
if ( transformed )
{
if (transformed) {
/* compute pi/4 - accumulator */
shr_Xsig(&accumulator, -1-exponent);
shr_Xsig(&accumulator, -1 - exponent);
negate_Xsig(&accumulator);
add_Xsig_Xsig(&accumulator, &pi_signif);
exponent = -1;
}
if ( inverted )
{
if (inverted) {
/* compute pi/2 - accumulator */
shr_Xsig(&accumulator, -exponent);
negate_Xsig(&accumulator);
......@@ -206,8 +186,7 @@ void poly_atan(FPU_REG *st0_ptr, u_char st0_tag,
exponent = 0;
}
if ( sign1 )
{
if (sign1) {
/* compute pi - accumulator */
shr_Xsig(&accumulator, 1 - exponent);
negate_Xsig(&accumulator);
......
......@@ -10,7 +10,6 @@
| |
+---------------------------------------------------------------------------*/
#include "exception.h"
#include "reg_constant.h"
#include "fpu_emu.h"
......@@ -18,15 +17,13 @@
#include "control_w.h"
#include "poly.h"
static void log2_kernel(FPU_REG const *arg, u_char argsign,
Xsig *accum_result, long int *expon);
Xsig * accum_result, long int *expon);
/*--- poly_l2() -------------------------------------------------------------+
| Base 2 logarithm by a polynomial approximation. |
+---------------------------------------------------------------------------*/
void poly_l2(FPU_REG *st0_ptr, FPU_REG *st1_ptr, u_char st1_sign)
void poly_l2(FPU_REG * st0_ptr, FPU_REG * st1_ptr, u_char st1_sign)
{
long int exponent, expon, expon_expon;
Xsig accumulator, expon_accum, yaccum;
......@@ -37,16 +34,13 @@ void poly_l2(FPU_REG *st0_ptr, FPU_REG *st1_ptr, u_char st1_sign)
exponent = exponent16(st0_ptr);
/* From st0_ptr, make a number > sqrt(2)/2 and < sqrt(2) */
if ( st0_ptr->sigh > (unsigned)0xb504f334 )
{
if (st0_ptr->sigh > (unsigned)0xb504f334) {
/* Treat as sqrt(2)/2 < st0_ptr < 1 */
significand(&x) = - significand(st0_ptr);
significand(&x) = -significand(st0_ptr);
setexponent16(&x, -1);
exponent++;
argsign = SIGN_NEG;
}
else
{
} else {
/* Treat as 1 <= st0_ptr < sqrt(2) */
x.sigh = st0_ptr->sigh - 0x80000000;
x.sigl = st0_ptr->sigl;
......@@ -55,46 +49,39 @@ void poly_l2(FPU_REG *st0_ptr, FPU_REG *st1_ptr, u_char st1_sign)
}
tag = FPU_normalize_nuo(&x);
if ( tag == TAG_Zero )
{
if (tag == TAG_Zero) {
expon = 0;
accumulator.msw = accumulator.midw = accumulator.lsw = 0;
}
else
{
} else {
log2_kernel(&x, argsign, &accumulator, &expon);
}
if ( exponent < 0 )
{
if (exponent < 0) {
sign = SIGN_NEG;
exponent = -exponent;
}
else
} else
sign = SIGN_POS;
expon_accum.msw = exponent; expon_accum.midw = expon_accum.lsw = 0;
if ( exponent )
{
expon_accum.msw = exponent;
expon_accum.midw = expon_accum.lsw = 0;
if (exponent) {
expon_expon = 31 + norm_Xsig(&expon_accum);
shr_Xsig(&accumulator, expon_expon - expon);
if ( sign ^ argsign )
if (sign ^ argsign)
negate_Xsig(&accumulator);
add_Xsig_Xsig(&accumulator, &expon_accum);
}
else
{
} else {
expon_expon = expon;
sign = argsign;
}
yaccum.lsw = 0; XSIG_LL(yaccum) = significand(st1_ptr);
yaccum.lsw = 0;
XSIG_LL(yaccum) = significand(st1_ptr);
mul_Xsig_Xsig(&accumulator, &yaccum);
expon_expon += round_Xsig(&accumulator);
if ( accumulator.msw == 0 )
{
if (accumulator.msw == 0) {
FPU_copy_to_reg1(&CONST_Z, TAG_Zero);
return;
}
......@@ -111,20 +98,18 @@ void poly_l2(FPU_REG *st0_ptr, FPU_REG *st1_ptr, u_char st1_sign)
}
/*--- poly_l2p1() -----------------------------------------------------------+
| Base 2 logarithm by a polynomial approximation. |
| log2(x+1) |
+---------------------------------------------------------------------------*/
int poly_l2p1(u_char sign0, u_char sign1,
FPU_REG *st0_ptr, FPU_REG *st1_ptr, FPU_REG *dest)
FPU_REG * st0_ptr, FPU_REG * st1_ptr, FPU_REG * dest)
{
u_char tag;
long int exponent;
Xsig accumulator, yaccum;
if ( exponent16(st0_ptr) < 0 )
{
if (exponent16(st0_ptr) < 0) {
log2_kernel(st0_ptr, sign0, &accumulator, &exponent);
yaccum.lsw = 0;
......@@ -134,7 +119,8 @@ int poly_l2p1(u_char sign0, u_char sign1,
exponent += round_Xsig(&accumulator);
exponent += exponent16(st1_ptr) + 1;
if ( exponent < EXP_WAY_UNDER ) exponent = EXP_WAY_UNDER;
if (exponent < EXP_WAY_UNDER)
exponent = EXP_WAY_UNDER;
significand(dest) = XSIG_LL(accumulator);
setexponent16(dest, exponent);
......@@ -142,45 +128,38 @@ int poly_l2p1(u_char sign0, u_char sign1,
tag = FPU_round(dest, 1, 0, FULL_PRECISION, sign0 ^ sign1);
FPU_settagi(1, tag);
if ( tag == TAG_Valid )
if (tag == TAG_Valid)
set_precision_flag_up(); /* 80486 appears to always do this */
}
else
{
} else {
/* The magnitude of st0_ptr is far too large. */
if ( sign0 != SIGN_POS )
{
if (sign0 != SIGN_POS) {
/* Trying to get the log of a negative number. */
#ifdef PECULIAR_486 /* Stupid 80486 doesn't worry about log(negative). */
changesign(st1_ptr);
#else
if ( arith_invalid(1) < 0 )
if (arith_invalid(1) < 0)
return 1;
#endif /* PECULIAR_486 */
}
/* 80486 appears to do this */
if ( sign0 == SIGN_NEG )
if (sign0 == SIGN_NEG)
set_precision_flag_down();
else
set_precision_flag_up();
}
if ( exponent(dest) <= EXP_UNDER )
if (exponent(dest) <= EXP_UNDER)
EXCEPTION(EX_Underflow);
return 0;
}
#undef HIPOWER
#define HIPOWER 10
static const unsigned long long logterms[HIPOWER] =
{
static const unsigned long long logterms[HIPOWER] = {
0x2a8eca5705fc2ef0LL,
0xf6384ee1d01febceLL,
0x093bb62877cdf642LL,
......@@ -195,12 +174,11 @@ static const unsigned long long logterms[HIPOWER] =
static const unsigned long leadterm = 0xb8000000;
/*--- log2_kernel() ---------------------------------------------------------+
| Base 2 logarithm by a polynomial approximation. |
| log2(x+1) |
+---------------------------------------------------------------------------*/
static void log2_kernel(FPU_REG const *arg, u_char argsign, Xsig *accum_result,
static void log2_kernel(FPU_REG const *arg, u_char argsign, Xsig * accum_result,
long int *expon)
{
long int exponent, adj;
......@@ -210,53 +188,47 @@ static void log2_kernel(FPU_REG const *arg, u_char argsign, Xsig *accum_result,
exponent = exponent16(arg);
Numer.lsw = Denom.lsw = 0;
XSIG_LL(Numer) = XSIG_LL(Denom) = significand(arg);
if ( argsign == SIGN_POS )
{
if (argsign == SIGN_POS) {
shr_Xsig(&Denom, 2 - (1 + exponent));
Denom.msw |= 0x80000000;
div_Xsig(&Numer, &Denom, &argSignif);
}
else
{
} else {
shr_Xsig(&Denom, 1 - (1 + exponent));
negate_Xsig(&Denom);
if ( Denom.msw & 0x80000000 )
{
if (Denom.msw & 0x80000000) {
div_Xsig(&Numer, &Denom, &argSignif);
exponent ++;
}
else
{
exponent++;
} else {
/* Denom must be 1.0 */
argSignif.lsw = Numer.lsw; argSignif.midw = Numer.midw;
argSignif.lsw = Numer.lsw;
argSignif.midw = Numer.midw;
argSignif.msw = Numer.msw;
}
}
#ifndef PECULIAR_486
/* Should check here that |local_arg| is within the valid range */
if ( exponent >= -2 )
{
if ( (exponent > -2) ||
(argSignif.msw > (unsigned)0xafb0ccc0) )
{
if (exponent >= -2) {
if ((exponent > -2) || (argSignif.msw > (unsigned)0xafb0ccc0)) {
/* The argument is too large */
}
}
#endif /* PECULIAR_486 */
arg_signif.lsw = argSignif.lsw; XSIG_LL(arg_signif) = XSIG_LL(argSignif);
arg_signif.lsw = argSignif.lsw;
XSIG_LL(arg_signif) = XSIG_LL(argSignif);
adj = norm_Xsig(&argSignif);
accumulator.lsw = argSignif.lsw; XSIG_LL(accumulator) = XSIG_LL(argSignif);
accumulator.lsw = argSignif.lsw;
XSIG_LL(accumulator) = XSIG_LL(argSignif);
mul_Xsig_Xsig(&accumulator, &accumulator);
shr_Xsig(&accumulator, 2*(-1 - (1 + exponent + adj)));
shr_Xsig(&accumulator, 2 * (-1 - (1 + exponent + adj)));
Xsq = XSIG_LL(accumulator);
if ( accumulator.lsw & 0x80000000 )
if (accumulator.lsw & 0x80000000)
Xsq++;
accumulator.msw = accumulator.midw = accumulator.lsw = 0;
/* Do the basic fixed point polynomial evaluation */
polynomial_Xsig(&accumulator, &Xsq, logterms, HIPOWER-1);
polynomial_Xsig(&accumulator, &Xsq, logterms, HIPOWER - 1);
mul_Xsig_Xsig(&accumulator, &argSignif);
shr_Xsig(&accumulator, 6 - adj);
......
......@@ -11,7 +11,6 @@
| |
+---------------------------------------------------------------------------*/
#include "exception.h"
#include "reg_constant.h"
#include "fpu_emu.h"
......@@ -19,51 +18,43 @@
#include "control_w.h"
#include "poly.h"
#define N_COEFF_P 4
#define N_COEFF_N 4
static const unsigned long long pos_terms_l[N_COEFF_P] =
{
static const unsigned long long pos_terms_l[N_COEFF_P] = {
0xaaaaaaaaaaaaaaabLL,
0x00d00d00d00cf906LL,
0x000006b99159a8bbLL,
0x000000000d7392e6LL
};
static const unsigned long long neg_terms_l[N_COEFF_N] =
{
static const unsigned long long neg_terms_l[N_COEFF_N] = {
0x2222222222222167LL,
0x0002e3bc74aab624LL,
0x0000000b09229062LL,
0x00000000000c7973LL
};
#define N_COEFF_PH 4
#define N_COEFF_NH 4
static const unsigned long long pos_terms_h[N_COEFF_PH] =
{
static const unsigned long long pos_terms_h[N_COEFF_PH] = {
0x0000000000000000LL,
0x05b05b05b05b0406LL,
0x000049f93edd91a9LL,
0x00000000c9c9ed62LL
};
static const unsigned long long neg_terms_h[N_COEFF_NH] =
{
static const unsigned long long neg_terms_h[N_COEFF_NH] = {
0xaaaaaaaaaaaaaa98LL,
0x001a01a01a019064LL,
0x0000008f76c68a77LL,
0x0000000000d58f5eLL
};
/*--- poly_sine() -----------------------------------------------------------+
| |
+---------------------------------------------------------------------------*/
void poly_sine(FPU_REG *st0_ptr)
void poly_sine(FPU_REG * st0_ptr)
{
int exponent, echange;
Xsig accumulator, argSqrd, argTo4;
......@@ -77,24 +68,27 @@ void poly_sine(FPU_REG *st0_ptr)
/* Split into two ranges, for arguments below and above 1.0 */
/* The boundary between upper and lower is approx 0.88309101259 */
if ( (exponent < -1) || ((exponent == -1) && (st0_ptr->sigh <= 0xe21240aa)) )
{
if ((exponent < -1)
|| ((exponent == -1) && (st0_ptr->sigh <= 0xe21240aa))) {
/* The argument is <= 0.88309101259 */
argSqrd.msw = st0_ptr->sigh; argSqrd.midw = st0_ptr->sigl; argSqrd.lsw = 0;
argSqrd.msw = st0_ptr->sigh;
argSqrd.midw = st0_ptr->sigl;
argSqrd.lsw = 0;
mul64_Xsig(&argSqrd, &significand(st0_ptr));
shr_Xsig(&argSqrd, 2*(-1-exponent));
argTo4.msw = argSqrd.msw; argTo4.midw = argSqrd.midw;
shr_Xsig(&argSqrd, 2 * (-1 - exponent));
argTo4.msw = argSqrd.msw;
argTo4.midw = argSqrd.midw;
argTo4.lsw = argSqrd.lsw;
mul_Xsig_Xsig(&argTo4, &argTo4);
polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_l,
N_COEFF_N-1);
N_COEFF_N - 1);
mul_Xsig_Xsig(&accumulator, &argSqrd);
negate_Xsig(&accumulator);
polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_l,
N_COEFF_P-1);
N_COEFF_P - 1);
shr_Xsig(&accumulator, 2); /* Divide by four */
accumulator.msw |= 0x80000000; /* Add 1.0 */
......@@ -104,7 +98,7 @@ void poly_sine(FPU_REG *st0_ptr)
mul64_Xsig(&accumulator, &significand(st0_ptr));
/* Divide by four, FPU_REG compatible, etc */
exponent = 3*exponent;
exponent = 3 * exponent;
/* The minimum exponent difference is 3 */
shr_Xsig(&accumulator, exponent(st0_ptr) - exponent);
......@@ -115,16 +109,13 @@ void poly_sine(FPU_REG *st0_ptr)
echange = round_Xsig(&accumulator);
setexponentpos(&result, exponent(st0_ptr) + echange);
}
else
{
} else {
/* The argument is > 0.88309101259 */
/* We use sin(st(0)) = cos(pi/2-st(0)) */
fixed_arg = significand(st0_ptr);
if ( exponent == 0 )
{
if (exponent == 0) {
/* The argument is >= 1.0 */
/* Put the binary point at the left. */
......@@ -133,22 +124,24 @@ void poly_sine(FPU_REG *st0_ptr)
/* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */
fixed_arg = 0x921fb54442d18469LL - fixed_arg;
/* There is a special case which arises due to rounding, to fix here. */
if ( fixed_arg == 0xffffffffffffffffLL )
if (fixed_arg == 0xffffffffffffffffLL)
fixed_arg = 0;
XSIG_LL(argSqrd) = fixed_arg; argSqrd.lsw = 0;
XSIG_LL(argSqrd) = fixed_arg;
argSqrd.lsw = 0;
mul64_Xsig(&argSqrd, &fixed_arg);
XSIG_LL(argTo4) = XSIG_LL(argSqrd); argTo4.lsw = argSqrd.lsw;
XSIG_LL(argTo4) = XSIG_LL(argSqrd);
argTo4.lsw = argSqrd.lsw;
mul_Xsig_Xsig(&argTo4, &argTo4);
polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_h,
N_COEFF_NH-1);
N_COEFF_NH - 1);
mul_Xsig_Xsig(&accumulator, &argSqrd);
negate_Xsig(&accumulator);
polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_h,
N_COEFF_PH-1);
N_COEFF_PH - 1);
negate_Xsig(&accumulator);
mul64_Xsig(&accumulator, &fixed_arg);
......@@ -172,8 +165,7 @@ void poly_sine(FPU_REG *st0_ptr)
/* This has an exponent of -65 */
fix_up = 0x898cc517;
/* The fix-up needs to be improved for larger args */
if ( argSqrd.msw & 0xffc00000 )
{
if (argSqrd.msw & 0xffc00000) {
/* Get about 32 bit precision in these: */
fix_up -= mul_32_32(0x898cc517, argSqrd.msw) / 6;
}
......@@ -181,8 +173,8 @@ void poly_sine(FPU_REG *st0_ptr)
adj = accumulator.lsw; /* temp save */
accumulator.lsw -= fix_up;
if ( accumulator.lsw > adj )
XSIG_LL(accumulator) --;
if (accumulator.lsw > adj)
XSIG_LL(accumulator)--;
echange = round_Xsig(&accumulator);
......@@ -194,21 +186,18 @@ void poly_sine(FPU_REG *st0_ptr)
FPU_copy_to_reg0(&result, TAG_Valid);
#ifdef PARANOID
if ( (exponent(&result) >= 0)
&& (significand(&result) > 0x8000000000000000LL) )
{
EXCEPTION(EX_INTERNAL|0x150);
if ((exponent(&result) >= 0)
&& (significand(&result) > 0x8000000000000000LL)) {
EXCEPTION(EX_INTERNAL | 0x150);
}
#endif /* PARANOID */
}
/*--- poly_cos() ------------------------------------------------------------+
| |
+---------------------------------------------------------------------------*/
void poly_cos(FPU_REG *st0_ptr)
void poly_cos(FPU_REG * st0_ptr)
{
FPU_REG result;
long int exponent, exp2, echange;
......@@ -216,10 +205,9 @@ void poly_cos(FPU_REG *st0_ptr)
unsigned long long fixed_arg;
#ifdef PARANOID
if ( (exponent(st0_ptr) > 0)
if ((exponent(st0_ptr) > 0)
|| ((exponent(st0_ptr) == 0)
&& (significand(st0_ptr) > 0xc90fdaa22168c234LL)) )
{
&& (significand(st0_ptr) > 0xc90fdaa22168c234LL))) {
EXCEPTION(EX_Invalid);
FPU_copy_to_reg0(&CONST_QNaN, TAG_Special);
return;
......@@ -230,36 +218,37 @@ void poly_cos(FPU_REG *st0_ptr)
accumulator.lsw = accumulator.midw = accumulator.msw = 0;
if ( (exponent < -1) || ((exponent == -1) && (st0_ptr->sigh <= 0xb00d6f54)) )
{
if ((exponent < -1)
|| ((exponent == -1) && (st0_ptr->sigh <= 0xb00d6f54))) {
/* arg is < 0.687705 */
argSqrd.msw = st0_ptr->sigh; argSqrd.midw = st0_ptr->sigl;
argSqrd.msw = st0_ptr->sigh;
argSqrd.midw = st0_ptr->sigl;
argSqrd.lsw = 0;
mul64_Xsig(&argSqrd, &significand(st0_ptr));
if ( exponent < -1 )
{
if (exponent < -1) {
/* shift the argument right by the required places */
shr_Xsig(&argSqrd, 2*(-1-exponent));
shr_Xsig(&argSqrd, 2 * (-1 - exponent));
}
argTo4.msw = argSqrd.msw; argTo4.midw = argSqrd.midw;
argTo4.msw = argSqrd.msw;
argTo4.midw = argSqrd.midw;
argTo4.lsw = argSqrd.lsw;
mul_Xsig_Xsig(&argTo4, &argTo4);
polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_h,
N_COEFF_NH-1);
N_COEFF_NH - 1);
mul_Xsig_Xsig(&accumulator, &argSqrd);
negate_Xsig(&accumulator);
polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_h,
N_COEFF_PH-1);
N_COEFF_PH - 1);
negate_Xsig(&accumulator);
mul64_Xsig(&accumulator, &significand(st0_ptr));
mul64_Xsig(&accumulator, &significand(st0_ptr));
shr_Xsig(&accumulator, -2*(1+exponent));
shr_Xsig(&accumulator, -2 * (1 + exponent));
shr_Xsig(&accumulator, 3);
negate_Xsig(&accumulator);
......@@ -272,28 +261,22 @@ void poly_cos(FPU_REG *st0_ptr)
following code will work ok */
negate_Xsig(&accumulator);
if ( accumulator.lsw & 0x80000000 )
XSIG_LL(accumulator) ++;
if ( accumulator.msw == 0 )
{
if (accumulator.lsw & 0x80000000)
XSIG_LL(accumulator)++;
if (accumulator.msw == 0) {
/* The result is 1.0 */
FPU_copy_to_reg0(&CONST_1, TAG_Valid);
return;
}
else
{
} else {
significand(&result) = XSIG_LL(accumulator);
/* will be a valid positive nr with expon = -1 */
setexponentpos(&result, -1);
}
}
else
{
} else {
fixed_arg = significand(st0_ptr);
if ( exponent == 0 )
{
if (exponent == 0) {
/* The argument is >= 1.0 */
/* Put the binary point at the left. */
......@@ -302,7 +285,7 @@ void poly_cos(FPU_REG *st0_ptr)
/* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */
fixed_arg = 0x921fb54442d18469LL - fixed_arg;
/* There is a special case which arises due to rounding, to fix here. */
if ( fixed_arg == 0xffffffffffffffffLL )
if (fixed_arg == 0xffffffffffffffffLL)
fixed_arg = 0;
exponent = -1;
......@@ -310,33 +293,33 @@ void poly_cos(FPU_REG *st0_ptr)
/* A shift is needed here only for a narrow range of arguments,
i.e. for fixed_arg approx 2^-32, but we pick up more... */
if ( !(LL_MSW(fixed_arg) & 0xffff0000) )
{
if (!(LL_MSW(fixed_arg) & 0xffff0000)) {
fixed_arg <<= 16;
exponent -= 16;
exp2 -= 16;
}
XSIG_LL(argSqrd) = fixed_arg; argSqrd.lsw = 0;
XSIG_LL(argSqrd) = fixed_arg;
argSqrd.lsw = 0;
mul64_Xsig(&argSqrd, &fixed_arg);
if ( exponent < -1 )
{
if (exponent < -1) {
/* shift the argument right by the required places */
shr_Xsig(&argSqrd, 2*(-1-exponent));
shr_Xsig(&argSqrd, 2 * (-1 - exponent));
}
argTo4.msw = argSqrd.msw; argTo4.midw = argSqrd.midw;
argTo4.msw = argSqrd.msw;
argTo4.midw = argSqrd.midw;
argTo4.lsw = argSqrd.lsw;
mul_Xsig_Xsig(&argTo4, &argTo4);
polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), neg_terms_l,
N_COEFF_N-1);
N_COEFF_N - 1);
mul_Xsig_Xsig(&accumulator, &argSqrd);
negate_Xsig(&accumulator);
polynomial_Xsig(&accumulator, &XSIG_LL(argTo4), pos_terms_l,
N_COEFF_P-1);
N_COEFF_P - 1);
shr_Xsig(&accumulator, 2); /* Divide by four */
accumulator.msw |= 0x80000000; /* Add 1.0 */
......@@ -346,7 +329,7 @@ void poly_cos(FPU_REG *st0_ptr)
mul64_Xsig(&accumulator, &fixed_arg);
/* Divide by four, FPU_REG compatible, etc */
exponent = 3*exponent;
exponent = 3 * exponent;
/* The minimum exponent difference is 3 */
shr_Xsig(&accumulator, exp2 - exponent);
......@@ -364,8 +347,7 @@ void poly_cos(FPU_REG *st0_ptr)
fix_up.lsw = 0;
/* The fix-up needs to be improved for larger args */
if ( argSqrd.msw & 0xffc00000 )
{
if (argSqrd.msw & 0xffc00000) {
/* Get about 32 bit precision in these: */
fix_up.msw -= mul_32_32(0x898cc517, argSqrd.msw) / 2;
fix_up.msw += mul_32_32(0x898cc517, argTo4.msw) / 24;
......@@ -387,10 +369,9 @@ void poly_cos(FPU_REG *st0_ptr)
FPU_copy_to_reg0(&result, TAG_Valid);
#ifdef PARANOID
if ( (exponent(&result) >= 0)
&& (significand(&result) > 0x8000000000000000LL) )
{
EXCEPTION(EX_INTERNAL|0x151);
if ((exponent(&result) >= 0)
&& (significand(&result) > 0x8000000000000000LL)) {
EXCEPTION(EX_INTERNAL | 0x151);
}
#endif /* PARANOID */
......
......@@ -17,43 +17,37 @@
#include "control_w.h"
#include "poly.h"
#define HiPOWERop 3 /* odd poly, positive terms */
static const unsigned long long oddplterm[HiPOWERop] =
{
static const unsigned long long oddplterm[HiPOWERop] = {
0x0000000000000000LL,
0x0051a1cf08fca228LL,
0x0000000071284ff7LL
};
#define HiPOWERon 2 /* odd poly, negative terms */
static const unsigned long long oddnegterm[HiPOWERon] =
{
static const unsigned long long oddnegterm[HiPOWERon] = {
0x1291a9a184244e80LL,
0x0000583245819c21LL
};
#define HiPOWERep 2 /* even poly, positive terms */
static const unsigned long long evenplterm[HiPOWERep] =
{
static const unsigned long long evenplterm[HiPOWERep] = {
0x0e848884b539e888LL,
0x00003c7f18b887daLL
};
#define HiPOWERen 2 /* even poly, negative terms */
static const unsigned long long evennegterm[HiPOWERen] =
{
static const unsigned long long evennegterm[HiPOWERen] = {
0xf1f0200fd51569ccLL,
0x003afb46105c4432LL
};
static const unsigned long long twothirds = 0xaaaaaaaaaaaaaaabLL;
/*--- poly_tan() ------------------------------------------------------------+
| |
+---------------------------------------------------------------------------*/
void poly_tan(FPU_REG *st0_ptr)
void poly_tan(FPU_REG * st0_ptr)
{
long int exponent;
int invert;
......@@ -64,20 +58,21 @@ void poly_tan(FPU_REG *st0_ptr)
exponent = exponent(st0_ptr);
#ifdef PARANOID
if ( signnegative(st0_ptr) ) /* Can't hack a number < 0.0 */
{ arith_invalid(0); return; } /* Need a positive number */
if (signnegative(st0_ptr)) { /* Can't hack a number < 0.0 */
arith_invalid(0);
return;
} /* Need a positive number */
#endif /* PARANOID */
/* Split the problem into two domains, smaller and larger than pi/4 */
if ( (exponent == 0) || ((exponent == -1) && (st0_ptr->sigh > 0xc90fdaa2)) )
{
if ((exponent == 0)
|| ((exponent == -1) && (st0_ptr->sigh > 0xc90fdaa2))) {
/* The argument is greater than (approx) pi/4 */
invert = 1;
accum.lsw = 0;
XSIG_LL(accum) = significand(st0_ptr);
if ( exponent == 0 )
{
if (exponent == 0) {
/* The argument is >= 1.0 */
/* Put the binary point at the left. */
XSIG_LL(accum) <<= 1;
......@@ -85,72 +80,72 @@ void poly_tan(FPU_REG *st0_ptr)
/* pi/2 in hex is: 1.921fb54442d18469 898CC51701B839A2 52049C1 */
XSIG_LL(accum) = 0x921fb54442d18469LL - XSIG_LL(accum);
/* This is a special case which arises due to rounding. */
if ( XSIG_LL(accum) == 0xffffffffffffffffLL )
{
if (XSIG_LL(accum) == 0xffffffffffffffffLL) {
FPU_settag0(TAG_Valid);
significand(st0_ptr) = 0x8a51e04daabda360LL;
setexponent16(st0_ptr, (0x41 + EXTENDED_Ebias) | SIGN_Negative);
setexponent16(st0_ptr,
(0x41 + EXTENDED_Ebias) | SIGN_Negative);
return;
}
argSignif.lsw = accum.lsw;
XSIG_LL(argSignif) = XSIG_LL(accum);
exponent = -1 + norm_Xsig(&argSignif);
}
else
{
} else {
invert = 0;
argSignif.lsw = 0;
XSIG_LL(accum) = XSIG_LL(argSignif) = significand(st0_ptr);
if ( exponent < -1 )
{
if (exponent < -1) {
/* shift the argument right by the required places */
if ( FPU_shrx(&XSIG_LL(accum), -1-exponent) >= 0x80000000U )
XSIG_LL(accum) ++; /* round up */
if (FPU_shrx(&XSIG_LL(accum), -1 - exponent) >=
0x80000000U)
XSIG_LL(accum)++; /* round up */
}
}
XSIG_LL(argSq) = XSIG_LL(accum); argSq.lsw = accum.lsw;
XSIG_LL(argSq) = XSIG_LL(accum);
argSq.lsw = accum.lsw;
mul_Xsig_Xsig(&argSq, &argSq);
XSIG_LL(argSqSq) = XSIG_LL(argSq); argSqSq.lsw = argSq.lsw;
XSIG_LL(argSqSq) = XSIG_LL(argSq);
argSqSq.lsw = argSq.lsw;
mul_Xsig_Xsig(&argSqSq, &argSqSq);
/* Compute the negative terms for the numerator polynomial */
accumulatoro.msw = accumulatoro.midw = accumulatoro.lsw = 0;
polynomial_Xsig(&accumulatoro, &XSIG_LL(argSqSq), oddnegterm, HiPOWERon-1);
polynomial_Xsig(&accumulatoro, &XSIG_LL(argSqSq), oddnegterm,
HiPOWERon - 1);
mul_Xsig_Xsig(&accumulatoro, &argSq);
negate_Xsig(&accumulatoro);
/* Add the positive terms */
polynomial_Xsig(&accumulatoro, &XSIG_LL(argSqSq), oddplterm, HiPOWERop-1);
polynomial_Xsig(&accumulatoro, &XSIG_LL(argSqSq), oddplterm,
HiPOWERop - 1);
/* Compute the positive terms for the denominator polynomial */
accumulatore.msw = accumulatore.midw = accumulatore.lsw = 0;
polynomial_Xsig(&accumulatore, &XSIG_LL(argSqSq), evenplterm, HiPOWERep-1);
polynomial_Xsig(&accumulatore, &XSIG_LL(argSqSq), evenplterm,
HiPOWERep - 1);
mul_Xsig_Xsig(&accumulatore, &argSq);
negate_Xsig(&accumulatore);
/* Add the negative terms */
polynomial_Xsig(&accumulatore, &XSIG_LL(argSqSq), evennegterm, HiPOWERen-1);
polynomial_Xsig(&accumulatore, &XSIG_LL(argSqSq), evennegterm,
HiPOWERen - 1);
/* Multiply by arg^2 */
mul64_Xsig(&accumulatore, &XSIG_LL(argSignif));
mul64_Xsig(&accumulatore, &XSIG_LL(argSignif));
/* de-normalize and divide by 2 */
shr_Xsig(&accumulatore, -2*(1+exponent) + 1);
shr_Xsig(&accumulatore, -2 * (1 + exponent) + 1);
negate_Xsig(&accumulatore); /* This does 1 - accumulator */
/* Now find the ratio. */
if ( accumulatore.msw == 0 )
{
if (accumulatore.msw == 0) {
/* accumulatoro must contain 1.0 here, (actually, 0) but it
really doesn't matter what value we use because it will
have negligible effect in later calculations
*/
XSIG_LL(accum) = 0x8000000000000000LL;
accum.lsw = 0;
}
else
{
} else {
div_Xsig(&accumulatoro, &accumulatore, &accum);
}
......@@ -159,13 +154,12 @@ void poly_tan(FPU_REG *st0_ptr)
mul64_Xsig(&accum, &XSIG_LL(argSignif));
mul64_Xsig(&accum, &XSIG_LL(argSignif));
mul64_Xsig(&accum, &twothirds);
shr_Xsig(&accum, -2*(exponent+1));
shr_Xsig(&accum, -2 * (exponent + 1));
/* tan(arg) = arg + accum */
add_two_Xsig(&accum, &argSignif, &exponent);
if ( invert )
{
if (invert) {
/* We now have the value of tan(pi_2 - arg) where pi_2 is an
approximation for pi/2
*/
......@@ -179,27 +173,23 @@ void poly_tan(FPU_REG *st0_ptr)
XSIG_LL(fix_up) = 0x898cc51701b839a2LL;
fix_up.lsw = 0;
if ( exponent == 0 )
if (exponent == 0)
adj = 0xffffffff; /* We want approx 1.0 here, but
this is close enough. */
else if ( exponent > -30 )
{
adj = accum.msw >> -(exponent+1); /* tan */
else if (exponent > -30) {
adj = accum.msw >> -(exponent + 1); /* tan */
adj = mul_32_32(adj, adj); /* tan^2 */
}
else
} else
adj = 0;
adj = mul_32_32(0x898cc517, adj); /* delta * tan^2 */
fix_up.msw += adj;
if ( !(fix_up.msw & 0x80000000) ) /* did fix_up overflow ? */
{
if (!(fix_up.msw & 0x80000000)) { /* did fix_up overflow ? */
/* Yes, we need to add an msb */
shr_Xsig(&fix_up, 1);
fix_up.msw |= 0x80000000;
shr_Xsig(&fix_up, 64 + exponent);
}
else
} else
shr_Xsig(&fix_up, 65 + exponent);
add_two_Xsig(&accum, &fix_up, &exponent);
......@@ -210,7 +200,7 @@ void poly_tan(FPU_REG *st0_ptr)
accumulatoro.lsw = accumulatoro.midw = 0;
accumulatoro.msw = 0x80000000;
div_Xsig(&accumulatoro, &accum, &accum);
exponent = - exponent - 1;
exponent = -exponent - 1;
}
/* Transfer the result */
......
......@@ -27,7 +27,7 @@
static
int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa,
FPU_REG const *b, u_char tagb, u_char signb,
FPU_REG *dest, int deststnr, int control_w);
FPU_REG * dest, int deststnr, int control_w);
/*
Operates on st(0) and st(n), or on st(0) and temporary data.
......@@ -43,44 +43,38 @@ int FPU_add(FPU_REG const *b, u_char tagb, int deststnr, int control_w)
u_char saved_sign = getsign(dest);
int diff, tag, expa, expb;
if ( !(taga | tagb) )
{
if (!(taga | tagb)) {
expa = exponent(a);
expb = exponent(b);
valid_add:
/* Both registers are valid */
if (!(signa ^ signb))
{
if (!(signa ^ signb)) {
/* signs are the same */
tag = FPU_u_add(a, b, dest, control_w, signa, expa, expb);
}
else
{
tag =
FPU_u_add(a, b, dest, control_w, signa, expa, expb);
} else {
/* The signs are different, so do a subtraction */
diff = expa - expb;
if (!diff)
{
if (!diff) {
diff = a->sigh - b->sigh; /* This works only if the ms bits
are identical. */
if (!diff)
{
if (!diff) {
diff = a->sigl > b->sigl;
if (!diff)
diff = -(a->sigl < b->sigl);
}
}
if (diff > 0)
{
tag = FPU_u_sub(a, b, dest, control_w, signa, expa, expb);
}
else if ( diff < 0 )
{
tag = FPU_u_sub(b, a, dest, control_w, signb, expb, expa);
}
else
{
if (diff > 0) {
tag =
FPU_u_sub(a, b, dest, control_w, signa,
expa, expb);
} else if (diff < 0) {
tag =
FPU_u_sub(b, a, dest, control_w, signb,
expb, expa);
} else {
FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
/* sign depends upon rounding mode */
setsign(dest, ((control_w & CW_RC) != RC_DOWN)
......@@ -89,8 +83,7 @@ int FPU_add(FPU_REG const *b, u_char tagb, int deststnr, int control_w)
}
}
if ( tag < 0 )
{
if (tag < 0) {
setsign(dest, saved_sign);
return tag;
}
......@@ -98,18 +91,17 @@ int FPU_add(FPU_REG const *b, u_char tagb, int deststnr, int control_w)
return tag;
}
if ( taga == TAG_Special )
if (taga == TAG_Special)
taga = FPU_Special(a);
if ( tagb == TAG_Special )
if (tagb == TAG_Special)
tagb = FPU_Special(b);
if ( ((taga == TAG_Valid) && (tagb == TW_Denormal))
if (((taga == TAG_Valid) && (tagb == TW_Denormal))
|| ((taga == TW_Denormal) && (tagb == TAG_Valid))
|| ((taga == TW_Denormal) && (tagb == TW_Denormal)) )
{
|| ((taga == TW_Denormal) && (tagb == TW_Denormal))) {
FPU_REG x, y;
if ( denormal_operand() < 0 )
if (denormal_operand() < 0)
return FPU_Exception;
FPU_to_exp16(a, &x);
......@@ -121,9 +113,8 @@ int FPU_add(FPU_REG const *b, u_char tagb, int deststnr, int control_w)
goto valid_add;
}
if ( (taga == TW_NaN) || (tagb == TW_NaN) )
{
if ( deststnr == 0 )
if ((taga == TW_NaN) || (tagb == TW_NaN)) {
if (deststnr == 0)
return real_2op_NaN(b, tagb, deststnr, a);
else
return real_2op_NaN(a, taga, deststnr, a);
......@@ -133,7 +124,6 @@ int FPU_add(FPU_REG const *b, u_char tagb, int deststnr, int control_w)
dest, deststnr, control_w);
}
/* Subtract b from a. (a-b) -> dest */
int FPU_sub(int flags, int rm, int control_w)
{
......@@ -146,25 +136,21 @@ int FPU_sub(int flags, int rm, int control_w)
taga = FPU_gettag0();
deststnr = 0;
if ( flags & LOADED )
{
b = (FPU_REG *)rm;
if (flags & LOADED) {
b = (FPU_REG *) rm;
tagb = flags & 0x0f;
}
else
{
} else {
b = &st(rm);
tagb = FPU_gettagi(rm);
if ( flags & DEST_RM )
if (flags & DEST_RM)
deststnr = rm;
}
signa = getsign(a);
signb = getsign(b);
if ( flags & REV )
{
if (flags & REV) {
signa ^= SIGN_NEG;
signb ^= SIGN_NEG;
}
......@@ -172,8 +158,7 @@ int FPU_sub(int flags, int rm, int control_w)
dest = &st(deststnr);
saved_sign = getsign(dest);
if ( !(taga | tagb) )
{
if (!(taga | tagb)) {
expa = exponent(a);
expb = exponent(b);
......@@ -182,55 +167,54 @@ int FPU_sub(int flags, int rm, int control_w)
diff = expa - expb;
if (!diff)
{
if (!diff) {
diff = a->sigh - b->sigh; /* Works only if ms bits are identical */
if (!diff)
{
if (!diff) {
diff = a->sigl > b->sigl;
if (!diff)
diff = -(a->sigl < b->sigl);
}
}
switch ( (((int)signa)*2 + signb) / SIGN_NEG )
{
switch ((((int)signa) * 2 + signb) / SIGN_NEG) {
case 0: /* P - P */
case 3: /* N - N */
if (diff > 0)
{
if (diff > 0) {
/* |a| > |b| */
tag = FPU_u_sub(a, b, dest, control_w, signa, expa, expb);
}
else if ( diff == 0 )
{
tag =
FPU_u_sub(a, b, dest, control_w, signa,
expa, expb);
} else if (diff == 0) {
FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
/* sign depends upon rounding mode */
setsign(dest, ((control_w & CW_RC) != RC_DOWN)
? SIGN_POS : SIGN_NEG);
return TAG_Zero;
}
else
{
} else {
sign = signa ^ SIGN_NEG;
tag = FPU_u_sub(b, a, dest, control_w, sign, expb, expa);
tag =
FPU_u_sub(b, a, dest, control_w, sign, expb,
expa);
}
break;
case 1: /* P - N */
tag = FPU_u_add(a, b, dest, control_w, SIGN_POS, expa, expb);
tag =
FPU_u_add(a, b, dest, control_w, SIGN_POS, expa,
expb);
break;
case 2: /* N - P */
tag = FPU_u_add(a, b, dest, control_w, SIGN_NEG, expa, expb);
tag =
FPU_u_add(a, b, dest, control_w, SIGN_NEG, expa,
expb);
break;
#ifdef PARANOID
default:
EXCEPTION(EX_INTERNAL|0x111);
EXCEPTION(EX_INTERNAL | 0x111);
return -1;
#endif
}
if ( tag < 0 )
{
if (tag < 0) {
setsign(dest, saved_sign);
return tag;
}
......@@ -238,18 +222,17 @@ int FPU_sub(int flags, int rm, int control_w)
return tag;
}
if ( taga == TAG_Special )
if (taga == TAG_Special)
taga = FPU_Special(a);
if ( tagb == TAG_Special )
if (tagb == TAG_Special)
tagb = FPU_Special(b);
if ( ((taga == TAG_Valid) && (tagb == TW_Denormal))
if (((taga == TAG_Valid) && (tagb == TW_Denormal))
|| ((taga == TW_Denormal) && (tagb == TAG_Valid))
|| ((taga == TW_Denormal) && (tagb == TW_Denormal)) )
{
|| ((taga == TW_Denormal) && (tagb == TW_Denormal))) {
FPU_REG x, y;
if ( denormal_operand() < 0 )
if (denormal_operand() < 0)
return FPU_Exception;
FPU_to_exp16(a, &x);
......@@ -262,22 +245,18 @@ int FPU_sub(int flags, int rm, int control_w)
goto valid_subtract;
}
if ( (taga == TW_NaN) || (tagb == TW_NaN) )
{
if ((taga == TW_NaN) || (tagb == TW_NaN)) {
FPU_REG const *d1, *d2;
if ( flags & REV )
{
if (flags & REV) {
d1 = b;
d2 = a;
}
else
{
} else {
d1 = a;
d2 = b;
}
if ( flags & LOADED )
if (flags & LOADED)
return real_2op_NaN(b, tagb, deststnr, d1);
if ( flags & DEST_RM )
if (flags & DEST_RM)
return real_2op_NaN(a, taga, deststnr, d2);
else
return real_2op_NaN(b, tagb, deststnr, d2);
......@@ -287,88 +266,68 @@ int FPU_sub(int flags, int rm, int control_w)
dest, deststnr, control_w);
}
static
int add_sub_specials(FPU_REG const *a, u_char taga, u_char signa,
FPU_REG const *b, u_char tagb, u_char signb,
FPU_REG *dest, int deststnr, int control_w)
FPU_REG * dest, int deststnr, int control_w)
{
if ( ((taga == TW_Denormal) || (tagb == TW_Denormal))
&& (denormal_operand() < 0) )
if (((taga == TW_Denormal) || (tagb == TW_Denormal))
&& (denormal_operand() < 0))
return FPU_Exception;
if (taga == TAG_Zero)
{
if (tagb == TAG_Zero)
{
if (taga == TAG_Zero) {
if (tagb == TAG_Zero) {
/* Both are zero, result will be zero. */
u_char different_signs = signa ^ signb;
FPU_copy_to_regi(a, TAG_Zero, deststnr);
if ( different_signs )
{
if (different_signs) {
/* Signs are different. */
/* Sign of answer depends upon rounding mode. */
setsign(dest, ((control_w & CW_RC) != RC_DOWN)
? SIGN_POS : SIGN_NEG);
}
else
} else
setsign(dest, signa); /* signa may differ from the sign of a. */
return TAG_Zero;
}
else
{
} else {
reg_copy(b, dest);
if ( (tagb == TW_Denormal) && (b->sigh & 0x80000000) )
{
if ((tagb == TW_Denormal) && (b->sigh & 0x80000000)) {
/* A pseudoDenormal, convert it. */
addexponent(dest, 1);
tagb = TAG_Valid;
}
else if ( tagb > TAG_Empty )
} else if (tagb > TAG_Empty)
tagb = TAG_Special;
setsign(dest, signb); /* signb may differ from the sign of b. */
FPU_settagi(deststnr, tagb);
return tagb;
}
}
else if (tagb == TAG_Zero)
{
} else if (tagb == TAG_Zero) {
reg_copy(a, dest);
if ( (taga == TW_Denormal) && (a->sigh & 0x80000000) )
{
if ((taga == TW_Denormal) && (a->sigh & 0x80000000)) {
/* A pseudoDenormal */
addexponent(dest, 1);
taga = TAG_Valid;
}
else if ( taga > TAG_Empty )
} else if (taga > TAG_Empty)
taga = TAG_Special;
setsign(dest, signa); /* signa may differ from the sign of a. */
FPU_settagi(deststnr, taga);
return taga;
}
else if (taga == TW_Infinity)
{
if ( (tagb != TW_Infinity) || (signa == signb) )
{
} else if (taga == TW_Infinity) {
if ((tagb != TW_Infinity) || (signa == signb)) {
FPU_copy_to_regi(a, TAG_Special, deststnr);
setsign(dest, signa); /* signa may differ from the sign of a. */
return taga;
}
/* Infinity-Infinity is undefined. */
return arith_invalid(deststnr);
}
else if (tagb == TW_Infinity)
{
} else if (tagb == TW_Infinity) {
FPU_copy_to_regi(b, TAG_Special, deststnr);
setsign(dest, signb); /* signb may differ from the sign of b. */
return tagb;
}
#ifdef PARANOID
EXCEPTION(EX_INTERNAL|0x101);
EXCEPTION(EX_INTERNAL | 0x101);
#endif
return FPU_Exception;
}
......@@ -20,7 +20,6 @@
#include "control_w.h"
#include "status_w.h"
static int compare(FPU_REG const *b, int tagb)
{
int diff, exp0, expb;
......@@ -33,75 +32,77 @@ static int compare(FPU_REG const *b, int tagb)
st0_tag = FPU_gettag0();
st0_sign = getsign(st0_ptr);
if ( tagb == TAG_Special )
if (tagb == TAG_Special)
tagb = FPU_Special(b);
if ( st0_tag == TAG_Special )
if (st0_tag == TAG_Special)
st0_tag = FPU_Special(st0_ptr);
if ( ((st0_tag != TAG_Valid) && (st0_tag != TW_Denormal))
|| ((tagb != TAG_Valid) && (tagb != TW_Denormal)) )
{
if ( st0_tag == TAG_Zero )
{
if ( tagb == TAG_Zero ) return COMP_A_eq_B;
if ( tagb == TAG_Valid )
return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B);
if ( tagb == TW_Denormal )
return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
if (((st0_tag != TAG_Valid) && (st0_tag != TW_Denormal))
|| ((tagb != TAG_Valid) && (tagb != TW_Denormal))) {
if (st0_tag == TAG_Zero) {
if (tagb == TAG_Zero)
return COMP_A_eq_B;
if (tagb == TAG_Valid)
return ((signb ==
SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B);
if (tagb == TW_Denormal)
return ((signb ==
SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
| COMP_Denormal;
}
else if ( tagb == TAG_Zero )
{
if ( st0_tag == TAG_Valid )
return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
if ( st0_tag == TW_Denormal )
return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
} else if (tagb == TAG_Zero) {
if (st0_tag == TAG_Valid)
return ((st0_sign ==
SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
if (st0_tag == TW_Denormal)
return ((st0_sign ==
SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
| COMP_Denormal;
}
if ( st0_tag == TW_Infinity )
{
if ( (tagb == TAG_Valid) || (tagb == TAG_Zero) )
return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
else if ( tagb == TW_Denormal )
return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
if (st0_tag == TW_Infinity) {
if ((tagb == TAG_Valid) || (tagb == TAG_Zero))
return ((st0_sign ==
SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
else if (tagb == TW_Denormal)
return ((st0_sign ==
SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
| COMP_Denormal;
else if ( tagb == TW_Infinity )
{
else if (tagb == TW_Infinity) {
/* The 80486 book says that infinities can be equal! */
return (st0_sign == signb) ? COMP_A_eq_B :
((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
((st0_sign ==
SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
}
/* Fall through to the NaN code */
}
else if ( tagb == TW_Infinity )
{
if ( (st0_tag == TAG_Valid) || (st0_tag == TAG_Zero) )
return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B);
if ( st0_tag == TW_Denormal )
return ((signb == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
} else if (tagb == TW_Infinity) {
if ((st0_tag == TAG_Valid) || (st0_tag == TAG_Zero))
return ((signb ==
SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B);
if (st0_tag == TW_Denormal)
return ((signb ==
SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
| COMP_Denormal;
/* Fall through to the NaN code */
}
/* The only possibility now should be that one of the arguments
is a NaN */
if ( (st0_tag == TW_NaN) || (tagb == TW_NaN) )
{
if ((st0_tag == TW_NaN) || (tagb == TW_NaN)) {
int signalling = 0, unsupported = 0;
if ( st0_tag == TW_NaN )
{
signalling = (st0_ptr->sigh & 0xc0000000) == 0x80000000;
if (st0_tag == TW_NaN) {
signalling =
(st0_ptr->sigh & 0xc0000000) == 0x80000000;
unsupported = !((exponent(st0_ptr) == EXP_OVER)
&& (st0_ptr->sigh & 0x80000000));
&& (st0_ptr->
sigh & 0x80000000));
}
if ( tagb == TW_NaN )
{
signalling |= (b->sigh & 0xc0000000) == 0x80000000;
if (tagb == TW_NaN) {
signalling |=
(b->sigh & 0xc0000000) == 0x80000000;
unsupported |= !((exponent(b) == EXP_OVER)
&& (b->sigh & 0x80000000));
}
if ( signalling || unsupported )
if (signalling || unsupported)
return COMP_No_Comp | COMP_SNaN | COMP_NaN;
else
/* Neither is a signaling NaN */
......@@ -111,66 +112,59 @@ static int compare(FPU_REG const *b, int tagb)
EXCEPTION(EX_Invalid);
}
if (st0_sign != signb)
{
if (st0_sign != signb) {
return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
| ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
| (((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
COMP_Denormal : 0);
}
if ( (st0_tag == TW_Denormal) || (tagb == TW_Denormal) )
{
if ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) {
FPU_to_exp16(st0_ptr, &x);
FPU_to_exp16(b, &y);
st0_ptr = &x;
b = &y;
exp0 = exponent16(st0_ptr);
expb = exponent16(b);
}
else
{
} else {
exp0 = exponent(st0_ptr);
expb = exponent(b);
}
#ifdef PARANOID
if (!(st0_ptr->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
if (!(b->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
if (!(st0_ptr->sigh & 0x80000000))
EXCEPTION(EX_Invalid);
if (!(b->sigh & 0x80000000))
EXCEPTION(EX_Invalid);
#endif /* PARANOID */
diff = exp0 - expb;
if ( diff == 0 )
{
if (diff == 0) {
diff = st0_ptr->sigh - b->sigh; /* Works only if ms bits are
identical */
if ( diff == 0 )
{
if (diff == 0) {
diff = st0_ptr->sigl > b->sigl;
if ( diff == 0 )
if (diff == 0)
diff = -(st0_ptr->sigl < b->sigl);
}
}
if ( diff > 0 )
{
if (diff > 0) {
return ((st0_sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
| ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
| (((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
COMP_Denormal : 0);
}
if ( diff < 0 )
{
if (diff < 0) {
return ((st0_sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
| ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
| (((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
COMP_Denormal : 0);
}
return COMP_A_eq_B
| ( ((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
| (((st0_tag == TW_Denormal) || (tagb == TW_Denormal)) ?
COMP_Denormal : 0);
}
/* This function requires that st(0) is not empty */
int FPU_compare_st_data(FPU_REG const *loaded_data, u_char loaded_tag)
{
......@@ -178,14 +172,11 @@ int FPU_compare_st_data(FPU_REG const *loaded_data, u_char loaded_tag)
c = compare(loaded_data, loaded_tag);
if (c & COMP_NaN)
{
if (c & COMP_NaN) {
EXCEPTION(EX_Invalid);
f = SW_C3 | SW_C2 | SW_C0;
}
else
switch (c & 7)
{
} else
switch (c & 7) {
case COMP_A_lt_B:
f = SW_C0;
break;
......@@ -200,27 +191,24 @@ int FPU_compare_st_data(FPU_REG const *loaded_data, u_char loaded_tag)
break;
#ifdef PARANOID
default:
EXCEPTION(EX_INTERNAL|0x121);
EXCEPTION(EX_INTERNAL | 0x121);
f = SW_C3 | SW_C2 | SW_C0;
break;
#endif /* PARANOID */
}
setcc(f);
if (c & COMP_Denormal)
{
if (c & COMP_Denormal) {
return denormal_operand() < 0;
}
return 0;
}
static int compare_st_st(int nr)
{
int f = 0, c;
FPU_REG *st_ptr;
if ( !NOT_EMPTY(0) || !NOT_EMPTY(nr) )
{
if (!NOT_EMPTY(0) || !NOT_EMPTY(nr)) {
setcc(SW_C3 | SW_C2 | SW_C0);
/* Stack fault */
EXCEPTION(EX_StackUnder);
......@@ -229,15 +217,12 @@ static int compare_st_st(int nr)
st_ptr = &st(nr);
c = compare(st_ptr, FPU_gettagi(nr));
if (c & COMP_NaN)
{
if (c & COMP_NaN) {
setcc(SW_C3 | SW_C2 | SW_C0);
EXCEPTION(EX_Invalid);
return !(control_word & CW_Invalid);
}
else
switch (c & 7)
{
} else
switch (c & 7) {
case COMP_A_lt_B:
f = SW_C0;
break;
......@@ -252,27 +237,24 @@ static int compare_st_st(int nr)
break;
#ifdef PARANOID
default:
EXCEPTION(EX_INTERNAL|0x122);
EXCEPTION(EX_INTERNAL | 0x122);
f = SW_C3 | SW_C2 | SW_C0;
break;
#endif /* PARANOID */
}
setcc(f);
if (c & COMP_Denormal)
{
if (c & COMP_Denormal) {
return denormal_operand() < 0;
}
return 0;
}
static int compare_u_st_st(int nr)
{
int f = 0, c;
FPU_REG *st_ptr;
if ( !NOT_EMPTY(0) || !NOT_EMPTY(nr) )
{
if (!NOT_EMPTY(0) || !NOT_EMPTY(nr)) {
setcc(SW_C3 | SW_C2 | SW_C0);
/* Stack fault */
EXCEPTION(EX_StackUnder);
......@@ -281,20 +263,16 @@ static int compare_u_st_st(int nr)
st_ptr = &st(nr);
c = compare(st_ptr, FPU_gettagi(nr));
if (c & COMP_NaN)
{
if (c & COMP_NaN) {
setcc(SW_C3 | SW_C2 | SW_C0);
if (c & COMP_SNaN) /* This is the only difference between
if (c & COMP_SNaN) { /* This is the only difference between
un-ordered and ordinary comparisons */
{
EXCEPTION(EX_Invalid);
return !(control_word & CW_Invalid);
}
return 0;
}
else
switch (c & 7)
{
} else
switch (c & 7) {
case COMP_A_lt_B:
f = SW_C0;
break;
......@@ -309,14 +287,13 @@ static int compare_u_st_st(int nr)
break;
#ifdef PARANOID
default:
EXCEPTION(EX_INTERNAL|0x123);
EXCEPTION(EX_INTERNAL | 0x123);
f = SW_C3 | SW_C2 | SW_C0;
break;
#endif /* PARANOID */
}
setcc(f);
if (c & COMP_Denormal)
{
if (c & COMP_Denormal) {
return denormal_operand() < 0;
}
return 0;
......@@ -330,28 +307,24 @@ void fcom_st(void)
compare_st_st(FPU_rm);
}
void fcompst(void)
{
/* fcomp st(i) */
if ( !compare_st_st(FPU_rm) )
if (!compare_st_st(FPU_rm))
FPU_pop();
}
void fcompp(void)
{
/* fcompp */
if (FPU_rm != 1)
{
if (FPU_rm != 1) {
FPU_illegal();
return;
}
if ( !compare_st_st(1) )
if (!compare_st_st(1))
poppop();
}
void fucom_(void)
{
/* fucom st(i) */
......@@ -359,23 +332,19 @@ void fucom_(void)
}
void fucomp(void)
{
/* fucomp st(i) */
if ( !compare_u_st_st(FPU_rm) )
if (!compare_u_st_st(FPU_rm))
FPU_pop();
}
void fucompp(void)
{
/* fucompp */
if (FPU_rm == 1)
{
if ( !compare_u_st_st(1) )
if (FPU_rm == 1) {
if (!compare_u_st_st(1))
poppop();
}
else
} else
FPU_illegal();
}
......@@ -16,7 +16,6 @@
#include "reg_constant.h"
#include "control_w.h"
#define MAKE_REG(s,e,l,h) { l, h, \
((EXTENDED_Ebias+(e)) | ((SIGN_##s != 0)*0x8000)) }
......@@ -50,13 +49,11 @@ FPU_REG const CONST_QNaN = MAKE_REG(NEG, EXP_OVER, 0x00000000, 0xC0000000);
/* Only the sign (and tag) is used in internal infinities */
FPU_REG const CONST_INF = MAKE_REG(POS, EXP_OVER, 0x00000000, 0x80000000);
static void fld_const(FPU_REG const *c, int adj, u_char tag)
{
FPU_REG *st_new_ptr;
if ( STACK_OVERFLOW )
{
if (STACK_OVERFLOW) {
FPU_stack_overflow();
return;
}
......@@ -108,13 +105,13 @@ static void fldz(int rc)
fld_const(&CONST_Z, 0, TAG_Zero);
}
typedef void (*FUNC_RC)(int);
typedef void (*FUNC_RC) (int);
static FUNC_RC constants_table[] = {
fld1, fldl2t, fldl2e, fldpi, fldlg2, fldln2, fldz, (FUNC_RC)FPU_illegal
fld1, fldl2t, fldl2e, fldpi, fldlg2, fldln2, fldz, (FUNC_RC) FPU_illegal
};
void fconst(void)
{
(constants_table[FPU_rm])(control_word & CW_RC);
(constants_table[FPU_rm]) (control_word & CW_RC);
}
......@@ -13,8 +13,7 @@
#include "exception.h"
#include "fpu_emu.h"
int FPU_to_exp16(FPU_REG const *a, FPU_REG *x)
int FPU_to_exp16(FPU_REG const *a, FPU_REG * x)
{
int sign = getsign(a);
......@@ -23,31 +22,25 @@ int FPU_to_exp16(FPU_REG const *a, FPU_REG *x)
/* Set up the exponent as a 16 bit quantity. */
setexponent16(x, exponent(a));
if ( exponent16(x) == EXP_UNDER )
{
if (exponent16(x) == EXP_UNDER) {
/* The number is a de-normal or pseudodenormal. */
/* We only deal with the significand and exponent. */
if (x->sigh & 0x80000000)
{
if (x->sigh & 0x80000000) {
/* Is a pseudodenormal. */
/* This is non-80486 behaviour because the number
loses its 'denormal' identity. */
addexponent(x, 1);
}
else
{
} else {
/* Is a denormal. */
addexponent(x, 1);
FPU_normalize_nuo(x);
}
}
if ( !(x->sigh & 0x80000000) )
{
if (!(x->sigh & 0x80000000)) {
EXCEPTION(EX_INTERNAL | 0x180);
}
return sign;
}
......@@ -32,40 +32,31 @@ int FPU_div(int flags, int rm, int control_w)
u_char taga, tagb, signa, signb, sign, saved_sign;
int tag, deststnr;
if ( flags & DEST_RM )
if (flags & DEST_RM)
deststnr = rm;
else
deststnr = 0;
if ( flags & REV )
{
if (flags & REV) {
b = &st(0);
st0_ptr = b;
tagb = FPU_gettag0();
if ( flags & LOADED )
{
a = (FPU_REG *)rm;
if (flags & LOADED) {
a = (FPU_REG *) rm;
taga = flags & 0x0f;
}
else
{
} else {
a = &st(rm);
st_ptr = a;
taga = FPU_gettagi(rm);
}
}
else
{
} else {
a = &st(0);
st0_ptr = a;
taga = FPU_gettag0();
if ( flags & LOADED )
{
b = (FPU_REG *)rm;
if (flags & LOADED) {
b = (FPU_REG *) rm;
tagb = flags & 0x0f;
}
else
{
} else {
b = &st(rm);
st_ptr = b;
tagb = FPU_gettagi(rm);
......@@ -80,8 +71,7 @@ int FPU_div(int flags, int rm, int control_w)
dest = &st(deststnr);
saved_sign = getsign(dest);
if ( !(taga | tagb) )
{
if (!(taga | tagb)) {
/* Both regs Valid, this should be the most common case. */
reg_copy(a, &x);
reg_copy(b, &y);
......@@ -89,42 +79,37 @@ int FPU_div(int flags, int rm, int control_w)
setpositive(&y);
tag = FPU_u_div(&x, &y, dest, control_w, sign);
if ( tag < 0 )
if (tag < 0)
return tag;
FPU_settagi(deststnr, tag);
return tag;
}
if ( taga == TAG_Special )
if (taga == TAG_Special)
taga = FPU_Special(a);
if ( tagb == TAG_Special )
if (tagb == TAG_Special)
tagb = FPU_Special(b);
if ( ((taga == TAG_Valid) && (tagb == TW_Denormal))
if (((taga == TAG_Valid) && (tagb == TW_Denormal))
|| ((taga == TW_Denormal) && (tagb == TAG_Valid))
|| ((taga == TW_Denormal) && (tagb == TW_Denormal)) )
{
if ( denormal_operand() < 0 )
|| ((taga == TW_Denormal) && (tagb == TW_Denormal))) {
if (denormal_operand() < 0)
return FPU_Exception;
FPU_to_exp16(a, &x);
FPU_to_exp16(b, &y);
tag = FPU_u_div(&x, &y, dest, control_w, sign);
if ( tag < 0 )
if (tag < 0)
return tag;
FPU_settagi(deststnr, tag);
return tag;
}
else if ( (taga <= TW_Denormal) && (tagb <= TW_Denormal) )
{
if ( tagb != TAG_Zero )
{
} else if ((taga <= TW_Denormal) && (tagb <= TW_Denormal)) {
if (tagb != TAG_Zero) {
/* Want to find Zero/Valid */
if ( tagb == TW_Denormal )
{
if ( denormal_operand() < 0 )
if (tagb == TW_Denormal) {
if (denormal_operand() < 0)
return FPU_Exception;
}
......@@ -134,8 +119,7 @@ int FPU_div(int flags, int rm, int control_w)
return TAG_Zero;
}
/* We have an exception condition, either 0/0 or Valid/Zero. */
if ( taga == TAG_Zero )
{
if (taga == TAG_Zero) {
/* 0/0 */
return arith_invalid(deststnr);
}
......@@ -143,39 +127,33 @@ int FPU_div(int flags, int rm, int control_w)
return FPU_divide_by_zero(deststnr, sign);
}
/* Must have infinities, NaNs, etc */
else if ( (taga == TW_NaN) || (tagb == TW_NaN) )
{
if ( flags & LOADED )
return real_2op_NaN((FPU_REG *)rm, flags & 0x0f, 0, st0_ptr);
else if ((taga == TW_NaN) || (tagb == TW_NaN)) {
if (flags & LOADED)
return real_2op_NaN((FPU_REG *) rm, flags & 0x0f, 0,
st0_ptr);
if ( flags & DEST_RM )
{
if (flags & DEST_RM) {
int tag;
tag = FPU_gettag0();
if ( tag == TAG_Special )
if (tag == TAG_Special)
tag = FPU_Special(st0_ptr);
return real_2op_NaN(st0_ptr, tag, rm, (flags & REV) ? st0_ptr : &st(rm));
}
else
{
return real_2op_NaN(st0_ptr, tag, rm,
(flags & REV) ? st0_ptr : &st(rm));
} else {
int tag;
tag = FPU_gettagi(rm);
if ( tag == TAG_Special )
if (tag == TAG_Special)
tag = FPU_Special(&st(rm));
return real_2op_NaN(&st(rm), tag, 0, (flags & REV) ? st0_ptr : &st(rm));
return real_2op_NaN(&st(rm), tag, 0,
(flags & REV) ? st0_ptr : &st(rm));
}
}
else if (taga == TW_Infinity)
{
if (tagb == TW_Infinity)
{
} else if (taga == TW_Infinity) {
if (tagb == TW_Infinity) {
/* infinity/infinity */
return arith_invalid(deststnr);
}
else
{
} else {
/* tagb must be Valid or Zero */
if ( (tagb == TW_Denormal) && (denormal_operand() < 0) )
if ((tagb == TW_Denormal) && (denormal_operand() < 0))
return FPU_Exception;
/* Infinity divided by Zero or Valid does
......@@ -184,10 +162,8 @@ int FPU_div(int flags, int rm, int control_w)
setsign(dest, sign);
return taga;
}
}
else if (tagb == TW_Infinity)
{
if ( (taga == TW_Denormal) && (denormal_operand() < 0) )
} else if (tagb == TW_Infinity) {
if ((taga == TW_Denormal) && (denormal_operand() < 0))
return FPU_Exception;
/* The result is zero. */
......@@ -196,9 +172,8 @@ int FPU_div(int flags, int rm, int control_w)
return TAG_Zero;
}
#ifdef PARANOID
else
{
EXCEPTION(EX_INTERNAL|0x102);
else {
EXCEPTION(EX_INTERNAL | 0x102);
return FPU_Exception;
}
#endif /* PARANOID */
......
......@@ -27,7 +27,6 @@
#include "control_w.h"
#include "status_w.h"
#define DOUBLE_Emax 1023 /* largest valid exponent */
#define DOUBLE_Ebias 1023
#define DOUBLE_Emin (-1022) /* smallest valid exponent */
......@@ -36,8 +35,7 @@
#define SINGLE_Ebias 127
#define SINGLE_Emin (-126) /* smallest valid exponent */
static u_char normalize_no_excep(FPU_REG *r, int exp, int sign)
static u_char normalize_no_excep(FPU_REG * r, int exp, int sign)
{
u_char tag;
......@@ -45,36 +43,31 @@ static u_char normalize_no_excep(FPU_REG *r, int exp, int sign)
tag = FPU_normalize_nuo(r);
stdexp(r);
if ( sign )
if (sign)
setnegative(r);
return tag;
}
int FPU_tagof(FPU_REG *ptr)
int FPU_tagof(FPU_REG * ptr)
{
int exp;
exp = exponent16(ptr) & 0x7fff;
if ( exp == 0 )
{
if ( !(ptr->sigh | ptr->sigl) )
{
if (exp == 0) {
if (!(ptr->sigh | ptr->sigl)) {
return TAG_Zero;
}
/* The number is a de-normal or pseudodenormal. */
return TAG_Special;
}
if ( exp == 0x7fff )
{
if (exp == 0x7fff) {
/* Is an Infinity, a NaN, or an unsupported data type. */
return TAG_Special;
}
if ( !(ptr->sigh & 0x80000000) )
{
if (!(ptr->sigh & 0x80000000)) {
/* Unsupported data type. */
/* Valid numbers have the ms bit set to 1. */
/* Unnormal. */
......@@ -84,9 +77,8 @@ int FPU_tagof(FPU_REG *ptr)
return TAG_Valid;
}
/* Get a long double from user memory */
int FPU_load_extended(long double __user *s, int stnr)
int FPU_load_extended(long double __user * s, int stnr)
{
FPU_REG *sti_ptr = &st(stnr);
......@@ -98,35 +90,30 @@ int FPU_load_extended(long double __user *s, int stnr)
return FPU_tagof(sti_ptr);
}
/* Get a double from user memory */
int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data)
int FPU_load_double(double __user * dfloat, FPU_REG * loaded_data)
{
int exp, tag, negative;
unsigned m64, l64;
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_READ, dfloat, 8);
FPU_get_user(m64, 1 + (unsigned long __user *) dfloat);
FPU_get_user(l64, (unsigned long __user *) dfloat);
FPU_get_user(m64, 1 + (unsigned long __user *)dfloat);
FPU_get_user(l64, (unsigned long __user *)dfloat);
RE_ENTRANT_CHECK_ON;
negative = (m64 & 0x80000000) ? SIGN_Negative : SIGN_Positive;
exp = ((m64 & 0x7ff00000) >> 20) - DOUBLE_Ebias + EXTENDED_Ebias;
m64 &= 0xfffff;
if ( exp > DOUBLE_Emax + EXTENDED_Ebias )
{
if (exp > DOUBLE_Emax + EXTENDED_Ebias) {
/* Infinity or NaN */
if ((m64 == 0) && (l64 == 0))
{
if ((m64 == 0) && (l64 == 0)) {
/* +- infinity */
loaded_data->sigh = 0x80000000;
loaded_data->sigl = 0x00000000;
exp = EXP_Infinity + EXTENDED_Ebias;
tag = TAG_Special;
}
else
{
} else {
/* Must be a signaling or quiet NaN */
exp = EXP_NaN + EXTENDED_Ebias;
loaded_data->sigh = (m64 << 11) | 0x80000000;
......@@ -134,30 +121,24 @@ int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data)
loaded_data->sigl = l64 << 11;
tag = TAG_Special; /* The calling function must look for NaNs */
}
}
else if ( exp < DOUBLE_Emin + EXTENDED_Ebias )
{
} else if (exp < DOUBLE_Emin + EXTENDED_Ebias) {
/* Zero or de-normal */
if ((m64 == 0) && (l64 == 0))
{
if ((m64 == 0) && (l64 == 0)) {
/* Zero */
reg_copy(&CONST_Z, loaded_data);
exp = 0;
tag = TAG_Zero;
}
else
{
} else {
/* De-normal */
loaded_data->sigh = m64 << 11;
loaded_data->sigh |= l64 >> 21;
loaded_data->sigl = l64 << 11;
return normalize_no_excep(loaded_data, DOUBLE_Emin, negative)
return normalize_no_excep(loaded_data, DOUBLE_Emin,
negative)
| (denormal_operand() < 0 ? FPU_Exception : 0);
}
}
else
{
} else {
loaded_data->sigh = (m64 << 11) | 0x80000000;
loaded_data->sigh |= l64 >> 21;
loaded_data->sigl = l64 << 11;
......@@ -170,22 +151,20 @@ int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data)
return tag;
}
/* Get a float from user memory */
int FPU_load_single(float __user *single, FPU_REG *loaded_data)
int FPU_load_single(float __user * single, FPU_REG * loaded_data)
{
unsigned m32;
int exp, tag, negative;
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_READ, single, 4);
FPU_get_user(m32, (unsigned long __user *) single);
FPU_get_user(m32, (unsigned long __user *)single);
RE_ENTRANT_CHECK_ON;
negative = (m32 & 0x80000000) ? SIGN_Negative : SIGN_Positive;
if (!(m32 & 0x7fffffff))
{
if (!(m32 & 0x7fffffff)) {
/* Zero */
reg_copy(&CONST_Z, loaded_data);
addexponent(loaded_data, negative);
......@@ -193,37 +172,29 @@ int FPU_load_single(float __user *single, FPU_REG *loaded_data)
}
exp = ((m32 & 0x7f800000) >> 23) - SINGLE_Ebias + EXTENDED_Ebias;
m32 = (m32 & 0x7fffff) << 8;
if ( exp < SINGLE_Emin + EXTENDED_Ebias )
{
if (exp < SINGLE_Emin + EXTENDED_Ebias) {
/* De-normals */
loaded_data->sigh = m32;
loaded_data->sigl = 0;
return normalize_no_excep(loaded_data, SINGLE_Emin, negative)
| (denormal_operand() < 0 ? FPU_Exception : 0);
}
else if ( exp > SINGLE_Emax + EXTENDED_Ebias )
{
} else if (exp > SINGLE_Emax + EXTENDED_Ebias) {
/* Infinity or NaN */
if ( m32 == 0 )
{
if (m32 == 0) {
/* +- infinity */
loaded_data->sigh = 0x80000000;
loaded_data->sigl = 0x00000000;
exp = EXP_Infinity + EXTENDED_Ebias;
tag = TAG_Special;
}
else
{
} else {
/* Must be a signaling or quiet NaN */
exp = EXP_NaN + EXTENDED_Ebias;
loaded_data->sigh = m32 | 0x80000000;
loaded_data->sigl = 0;
tag = TAG_Special; /* The calling function must look for NaNs */
}
}
else
{
} else {
loaded_data->sigh = m32 | 0x80000000;
loaded_data->sigl = 0;
tag = TAG_Valid;
......@@ -234,9 +205,8 @@ int FPU_load_single(float __user *single, FPU_REG *loaded_data)
return tag;
}
/* Get a long long from user memory */
int FPU_load_int64(long long __user *_s)
int FPU_load_int64(long long __user * _s)
{
long long s;
int sign;
......@@ -244,20 +214,18 @@ int FPU_load_int64(long long __user *_s)
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_READ, _s, 8);
if (copy_from_user(&s,_s,8))
if (copy_from_user(&s, _s, 8))
FPU_abort;
RE_ENTRANT_CHECK_ON;
if (s == 0)
{
if (s == 0) {
reg_copy(&CONST_Z, st0_ptr);
return TAG_Zero;
}
if (s > 0)
sign = SIGN_Positive;
else
{
else {
s = -s;
sign = SIGN_Negative;
}
......@@ -267,9 +235,8 @@ int FPU_load_int64(long long __user *_s)
return normalize_no_excep(st0_ptr, 63, sign);
}
/* Get a long from user memory */
int FPU_load_int32(long __user *_s, FPU_REG *loaded_data)
int FPU_load_int32(long __user * _s, FPU_REG * loaded_data)
{
long s;
int negative;
......@@ -279,13 +246,14 @@ int FPU_load_int32(long __user *_s, FPU_REG *loaded_data)
FPU_get_user(s, _s);
RE_ENTRANT_CHECK_ON;
if (s == 0)
{ reg_copy(&CONST_Z, loaded_data); return TAG_Zero; }
if (s == 0) {
reg_copy(&CONST_Z, loaded_data);
return TAG_Zero;
}
if (s > 0)
negative = SIGN_Positive;
else
{
else {
s = -s;
negative = SIGN_Negative;
}
......@@ -296,9 +264,8 @@ int FPU_load_int32(long __user *_s, FPU_REG *loaded_data)
return normalize_no_excep(loaded_data, 31, negative);
}
/* Get a short from user memory */
int FPU_load_int16(short __user *_s, FPU_REG *loaded_data)
int FPU_load_int16(short __user * _s, FPU_REG * loaded_data)
{
int s, negative;
......@@ -308,13 +275,14 @@ int FPU_load_int16(short __user *_s, FPU_REG *loaded_data)
FPU_get_user(s, _s);
RE_ENTRANT_CHECK_ON;
if (s == 0)
{ reg_copy(&CONST_Z, loaded_data); return TAG_Zero; }
if (s == 0) {
reg_copy(&CONST_Z, loaded_data);
return TAG_Zero;
}
if (s > 0)
negative = SIGN_Positive;
else
{
else {
s = -s;
negative = SIGN_Negative;
}
......@@ -325,24 +293,22 @@ int FPU_load_int16(short __user *_s, FPU_REG *loaded_data)
return normalize_no_excep(loaded_data, 15, negative);
}
/* Get a packed bcd array from user memory */
int FPU_load_bcd(u_char __user *s)
int FPU_load_bcd(u_char __user * s)
{
FPU_REG *st0_ptr = &st(0);
int pos;
u_char bcd;
long long l=0;
long long l = 0;
int sign;
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_READ, s, 10);
RE_ENTRANT_CHECK_ON;
for ( pos = 8; pos >= 0; pos--)
{
for (pos = 8; pos >= 0; pos--) {
l *= 10;
RE_ENTRANT_CHECK_OFF;
FPU_get_user(bcd, s+pos);
FPU_get_user(bcd, s + pos);
RE_ENTRANT_CHECK_ON;
l += bcd >> 4;
l *= 10;
......@@ -350,18 +316,15 @@ int FPU_load_bcd(u_char __user *s)
}
RE_ENTRANT_CHECK_OFF;
FPU_get_user(sign, s+9);
FPU_get_user(sign, s + 9);
sign = sign & 0x80 ? SIGN_Negative : SIGN_Positive;
RE_ENTRANT_CHECK_ON;
if ( l == 0 )
{
if (l == 0) {
reg_copy(&CONST_Z, st0_ptr);
addexponent(st0_ptr, sign); /* Set the sign. */
return TAG_Zero;
}
else
{
} else {
significand(st0_ptr) = l;
return normalize_no_excep(st0_ptr, 63, sign);
}
......@@ -370,7 +333,8 @@ int FPU_load_bcd(u_char __user *s)
/*===========================================================================*/
/* Put a long double into user memory */
int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double __user *d)
int FPU_store_extended(FPU_REG * st0_ptr, u_char st0_tag,
long double __user * d)
{
/*
The only exception raised by an attempt to store to an
......@@ -378,14 +342,16 @@ int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double __user *d)
attempting to store from an empty register.
*/
if ( st0_tag != TAG_Empty )
{
if (st0_tag != TAG_Empty) {
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE, d, 10);
FPU_put_user(st0_ptr->sigl, (unsigned long __user *) d);
FPU_put_user(st0_ptr->sigh, (unsigned long __user *) ((u_char __user *)d + 4));
FPU_put_user(exponent16(st0_ptr), (unsigned short __user *) ((u_char __user *)d + 8));
FPU_put_user(st0_ptr->sigl, (unsigned long __user *)d);
FPU_put_user(st0_ptr->sigh,
(unsigned long __user *)((u_char __user *) d + 4));
FPU_put_user(exponent16(st0_ptr),
(unsigned short __user *)((u_char __user *) d +
8));
RE_ENTRANT_CHECK_ON;
return 1;
......@@ -393,26 +359,23 @@ int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double __user *d)
/* Empty register (stack underflow) */
EXCEPTION(EX_StackUnder);
if ( control_word & CW_Invalid )
{
if (control_word & CW_Invalid) {
/* The masked response */
/* Put out the QNaN indefinite */
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE,d,10);
FPU_put_user(0, (unsigned long __user *) d);
FPU_put_user(0xc0000000, 1 + (unsigned long __user *) d);
FPU_put_user(0xffff, 4 + (short __user *) d);
FPU_access_ok(VERIFY_WRITE, d, 10);
FPU_put_user(0, (unsigned long __user *)d);
FPU_put_user(0xc0000000, 1 + (unsigned long __user *)d);
FPU_put_user(0xffff, 4 + (short __user *)d);
RE_ENTRANT_CHECK_ON;
return 1;
}
else
} else
return 0;
}
/* Put a double into user memory */
int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
int FPU_store_double(FPU_REG * st0_ptr, u_char st0_tag, double __user * dfloat)
{
unsigned long l[2];
unsigned long increment = 0; /* avoid gcc warnings */
......@@ -420,58 +383,56 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
int exp;
FPU_REG tmp;
if ( st0_tag == TAG_Valid )
{
if (st0_tag == TAG_Valid) {
reg_copy(st0_ptr, &tmp);
exp = exponent(&tmp);
if ( exp < DOUBLE_Emin ) /* It may be a denormal */
{
if (exp < DOUBLE_Emin) { /* It may be a denormal */
addexponent(&tmp, -DOUBLE_Emin + 52); /* largest exp to be 51 */
denormal_arg:
if ( (precision_loss = FPU_round_to_int(&tmp, st0_tag)) )
{
if ((precision_loss = FPU_round_to_int(&tmp, st0_tag))) {
#ifdef PECULIAR_486
/* Did it round to a non-denormal ? */
/* This behaviour might be regarded as peculiar, it appears
that the 80486 rounds to the dest precision, then
converts to decide underflow. */
if ( !((tmp.sigh == 0x00100000) && (tmp.sigl == 0) &&
(st0_ptr->sigl & 0x000007ff)) )
if (!
((tmp.sigh == 0x00100000) && (tmp.sigl == 0)
&& (st0_ptr->sigl & 0x000007ff)))
#endif /* PECULIAR_486 */
{
EXCEPTION(EX_Underflow);
/* This is a special case: see sec 16.2.5.1 of
the 80486 book */
if ( !(control_word & CW_Underflow) )
if (!(control_word & CW_Underflow))
return 0;
}
EXCEPTION(precision_loss);
if ( !(control_word & CW_Precision) )
if (!(control_word & CW_Precision))
return 0;
}
l[0] = tmp.sigl;
l[1] = tmp.sigh;
}
else
{
if ( tmp.sigl & 0x000007ff )
{
} else {
if (tmp.sigl & 0x000007ff) {
precision_loss = 1;
switch (control_word & CW_RC)
{
switch (control_word & CW_RC) {
case RC_RND:
/* Rounding can get a little messy.. */
increment = ((tmp.sigl & 0x7ff) > 0x400) | /* nearest */
((tmp.sigl & 0xc00) == 0xc00); /* odd -> even */
break;
case RC_DOWN: /* towards -infinity */
increment = signpositive(&tmp) ? 0 : tmp.sigl & 0x7ff;
increment =
signpositive(&tmp) ? 0 : tmp.
sigl & 0x7ff;
break;
case RC_UP: /* towards +infinity */
increment = signpositive(&tmp) ? tmp.sigl & 0x7ff : 0;
increment =
signpositive(&tmp) ? tmp.
sigl & 0x7ff : 0;
break;
case RC_CHOP:
increment = 0;
......@@ -481,147 +442,121 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
/* Truncate the mantissa */
tmp.sigl &= 0xfffff800;
if ( increment )
{
if ( tmp.sigl >= 0xfffff800 )
{
if (increment) {
if (tmp.sigl >= 0xfffff800) {
/* the sigl part overflows */
if ( tmp.sigh == 0xffffffff )
{
if (tmp.sigh == 0xffffffff) {
/* The sigh part overflows */
tmp.sigh = 0x80000000;
exp++;
if (exp >= EXP_OVER)
goto overflow;
}
else
{
tmp.sigh ++;
} else {
tmp.sigh++;
}
tmp.sigl = 0x00000000;
}
else
{
} else {
/* We only need to increment sigl */
tmp.sigl += 0x00000800;
}
}
}
else
} else
precision_loss = 0;
l[0] = (tmp.sigl >> 11) | (tmp.sigh << 21);
l[1] = ((tmp.sigh >> 11) & 0xfffff);
if ( exp > DOUBLE_Emax )
{
if (exp > DOUBLE_Emax) {
overflow:
EXCEPTION(EX_Overflow);
if ( !(control_word & CW_Overflow) )
if (!(control_word & CW_Overflow))
return 0;
set_precision_flag_up();
if ( !(control_word & CW_Precision) )
if (!(control_word & CW_Precision))
return 0;
/* This is a special case: see sec 16.2.5.1 of the 80486 book */
/* Overflow to infinity */
l[0] = 0x00000000; /* Set to */
l[1] = 0x7ff00000; /* + INF */
}
else
{
if ( precision_loss )
{
if ( increment )
} else {
if (precision_loss) {
if (increment)
set_precision_flag_up();
else
set_precision_flag_down();
}
/* Add the exponent */
l[1] |= (((exp+DOUBLE_Ebias) & 0x7ff) << 20);
}
l[1] |= (((exp + DOUBLE_Ebias) & 0x7ff) << 20);
}
}
else if (st0_tag == TAG_Zero)
{
} else if (st0_tag == TAG_Zero) {
/* Number is zero */
l[0] = 0;
l[1] = 0;
}
else if ( st0_tag == TAG_Special )
{
} else if (st0_tag == TAG_Special) {
st0_tag = FPU_Special(st0_ptr);
if ( st0_tag == TW_Denormal )
{
if (st0_tag == TW_Denormal) {
/* A denormal will always underflow. */
#ifndef PECULIAR_486
/* An 80486 is supposed to be able to generate
a denormal exception here, but... */
/* Underflow has priority. */
if ( control_word & CW_Underflow )
if (control_word & CW_Underflow)
denormal_operand();
#endif /* PECULIAR_486 */
reg_copy(st0_ptr, &tmp);
goto denormal_arg;
}
else if (st0_tag == TW_Infinity)
{
} else if (st0_tag == TW_Infinity) {
l[0] = 0;
l[1] = 0x7ff00000;
}
else if (st0_tag == TW_NaN)
{
} else if (st0_tag == TW_NaN) {
/* Is it really a NaN ? */
if ( (exponent(st0_ptr) == EXP_OVER)
&& (st0_ptr->sigh & 0x80000000) )
{
if ((exponent(st0_ptr) == EXP_OVER)
&& (st0_ptr->sigh & 0x80000000)) {
/* See if we can get a valid NaN from the FPU_REG */
l[0] = (st0_ptr->sigl >> 11) | (st0_ptr->sigh << 21);
l[0] =
(st0_ptr->sigl >> 11) | (st0_ptr->
sigh << 21);
l[1] = ((st0_ptr->sigh >> 11) & 0xfffff);
if ( !(st0_ptr->sigh & 0x40000000) )
{
if (!(st0_ptr->sigh & 0x40000000)) {
/* It is a signalling NaN */
EXCEPTION(EX_Invalid);
if ( !(control_word & CW_Invalid) )
if (!(control_word & CW_Invalid))
return 0;
l[1] |= (0x40000000 >> 11);
}
l[1] |= 0x7ff00000;
}
else
{
} else {
/* It is an unsupported data type */
EXCEPTION(EX_Invalid);
if ( !(control_word & CW_Invalid) )
if (!(control_word & CW_Invalid))
return 0;
l[0] = 0;
l[1] = 0xfff80000;
}
}
}
else if ( st0_tag == TAG_Empty )
{
} else if (st0_tag == TAG_Empty) {
/* Empty register (stack underflow) */
EXCEPTION(EX_StackUnder);
if ( control_word & CW_Invalid )
{
if (control_word & CW_Invalid) {
/* The masked response */
/* Put out the QNaN indefinite */
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE,dfloat,8);
FPU_put_user(0, (unsigned long __user *) dfloat);
FPU_put_user(0xfff80000, 1 + (unsigned long __user *) dfloat);
FPU_access_ok(VERIFY_WRITE, dfloat, 8);
FPU_put_user(0, (unsigned long __user *)dfloat);
FPU_put_user(0xfff80000,
1 + (unsigned long __user *)dfloat);
RE_ENTRANT_CHECK_ON;
return 1;
}
else
} else
return 0;
}
if ( getsign(st0_ptr) )
if (getsign(st0_ptr))
l[1] |= 0x80000000;
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE,dfloat,8);
FPU_access_ok(VERIFY_WRITE, dfloat, 8);
FPU_put_user(l[0], (unsigned long __user *)dfloat);
FPU_put_user(l[1], 1 + (unsigned long __user *)dfloat);
RE_ENTRANT_CHECK_ON;
......@@ -629,9 +564,8 @@ int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat)
return 1;
}
/* Put a float into user memory */
int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single)
int FPU_store_single(FPU_REG * st0_ptr, u_char st0_tag, float __user * single)
{
long templ = 0;
unsigned long increment = 0; /* avoid gcc warnings */
......@@ -639,55 +573,49 @@ int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single)
int exp;
FPU_REG tmp;
if ( st0_tag == TAG_Valid )
{
if (st0_tag == TAG_Valid) {
reg_copy(st0_ptr, &tmp);
exp = exponent(&tmp);
if ( exp < SINGLE_Emin )
{
if (exp < SINGLE_Emin) {
addexponent(&tmp, -SINGLE_Emin + 23); /* largest exp to be 22 */
denormal_arg:
if ( (precision_loss = FPU_round_to_int(&tmp, st0_tag)) )
{
if ((precision_loss = FPU_round_to_int(&tmp, st0_tag))) {
#ifdef PECULIAR_486
/* Did it round to a non-denormal ? */
/* This behaviour might be regarded as peculiar, it appears
that the 80486 rounds to the dest precision, then
converts to decide underflow. */
if ( !((tmp.sigl == 0x00800000) &&
((st0_ptr->sigh & 0x000000ff) || st0_ptr->sigl)) )
if (!((tmp.sigl == 0x00800000) &&
((st0_ptr->sigh & 0x000000ff)
|| st0_ptr->sigl)))
#endif /* PECULIAR_486 */
{
EXCEPTION(EX_Underflow);
/* This is a special case: see sec 16.2.5.1 of
the 80486 book */
if ( !(control_word & CW_Underflow) )
if (!(control_word & CW_Underflow))
return 0;
}
EXCEPTION(precision_loss);
if ( !(control_word & CW_Precision) )
if (!(control_word & CW_Precision))
return 0;
}
templ = tmp.sigl;
}
else
{
if ( tmp.sigl | (tmp.sigh & 0x000000ff) )
{
} else {
if (tmp.sigl | (tmp.sigh & 0x000000ff)) {
unsigned long sigh = tmp.sigh;
unsigned long sigl = tmp.sigl;
precision_loss = 1;
switch (control_word & CW_RC)
{
switch (control_word & CW_RC) {
case RC_RND:
increment = ((sigh & 0xff) > 0x80) /* more than half */
|| (((sigh & 0xff) == 0x80) && sigl) /* more than half */
|| ((sigh & 0x180) == 0x180); /* round to even */
||(((sigh & 0xff) == 0x80) && sigl) /* more than half */
||((sigh & 0x180) == 0x180); /* round to even */
break;
case RC_DOWN: /* towards -infinity */
increment = signpositive(&tmp)
......@@ -705,69 +633,53 @@ int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single)
/* Truncate part of the mantissa */
tmp.sigl = 0;
if (increment)
{
if ( sigh >= 0xffffff00 )
{
if (increment) {
if (sigh >= 0xffffff00) {
/* The sigh part overflows */
tmp.sigh = 0x80000000;
exp++;
if ( exp >= EXP_OVER )
if (exp >= EXP_OVER)
goto overflow;
}
else
{
} else {
tmp.sigh &= 0xffffff00;
tmp.sigh += 0x100;
}
}
else
{
} else {
tmp.sigh &= 0xffffff00; /* Finish the truncation */
}
}
else
} else
precision_loss = 0;
templ = (tmp.sigh >> 8) & 0x007fffff;
if ( exp > SINGLE_Emax )
{
if (exp > SINGLE_Emax) {
overflow:
EXCEPTION(EX_Overflow);
if ( !(control_word & CW_Overflow) )
if (!(control_word & CW_Overflow))
return 0;
set_precision_flag_up();
if ( !(control_word & CW_Precision) )
if (!(control_word & CW_Precision))
return 0;
/* This is a special case: see sec 16.2.5.1 of the 80486 book. */
/* Masked response is overflow to infinity. */
templ = 0x7f800000;
}
else
{
if ( precision_loss )
{
if ( increment )
} else {
if (precision_loss) {
if (increment)
set_precision_flag_up();
else
set_precision_flag_down();
}
/* Add the exponent */
templ |= ((exp+SINGLE_Ebias) & 0xff) << 23;
}
templ |= ((exp + SINGLE_Ebias) & 0xff) << 23;
}
}
else if (st0_tag == TAG_Zero)
{
} else if (st0_tag == TAG_Zero) {
templ = 0;
}
else if ( st0_tag == TAG_Special )
{
} else if (st0_tag == TAG_Special) {
st0_tag = FPU_Special(st0_ptr);
if (st0_tag == TW_Denormal)
{
if (st0_tag == TW_Denormal) {
reg_copy(st0_ptr, &tmp);
/* A denormal will always underflow. */
......@@ -775,104 +687,86 @@ int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single)
/* An 80486 is supposed to be able to generate
a denormal exception here, but... */
/* Underflow has priority. */
if ( control_word & CW_Underflow )
if (control_word & CW_Underflow)
denormal_operand();
#endif /* PECULIAR_486 */
goto denormal_arg;
}
else if (st0_tag == TW_Infinity)
{
} else if (st0_tag == TW_Infinity) {
templ = 0x7f800000;
}
else if (st0_tag == TW_NaN)
{
} else if (st0_tag == TW_NaN) {
/* Is it really a NaN ? */
if ( (exponent(st0_ptr) == EXP_OVER) && (st0_ptr->sigh & 0x80000000) )
{
if ((exponent(st0_ptr) == EXP_OVER)
&& (st0_ptr->sigh & 0x80000000)) {
/* See if we can get a valid NaN from the FPU_REG */
templ = st0_ptr->sigh >> 8;
if ( !(st0_ptr->sigh & 0x40000000) )
{
if (!(st0_ptr->sigh & 0x40000000)) {
/* It is a signalling NaN */
EXCEPTION(EX_Invalid);
if ( !(control_word & CW_Invalid) )
if (!(control_word & CW_Invalid))
return 0;
templ |= (0x40000000 >> 8);
}
templ |= 0x7f800000;
}
else
{
} else {
/* It is an unsupported data type */
EXCEPTION(EX_Invalid);
if ( !(control_word & CW_Invalid) )
if (!(control_word & CW_Invalid))
return 0;
templ = 0xffc00000;
}
}
#ifdef PARANOID
else
{
EXCEPTION(EX_INTERNAL|0x164);
else {
EXCEPTION(EX_INTERNAL | 0x164);
return 0;
}
#endif
}
else if ( st0_tag == TAG_Empty )
{
} else if (st0_tag == TAG_Empty) {
/* Empty register (stack underflow) */
EXCEPTION(EX_StackUnder);
if ( control_word & EX_Invalid )
{
if (control_word & EX_Invalid) {
/* The masked response */
/* Put out the QNaN indefinite */
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE,single,4);
FPU_put_user(0xffc00000, (unsigned long __user *) single);
FPU_access_ok(VERIFY_WRITE, single, 4);
FPU_put_user(0xffc00000,
(unsigned long __user *)single);
RE_ENTRANT_CHECK_ON;
return 1;
}
else
} else
return 0;
}
#ifdef PARANOID
else
{
EXCEPTION(EX_INTERNAL|0x163);
else {
EXCEPTION(EX_INTERNAL | 0x163);
return 0;
}
#endif
if ( getsign(st0_ptr) )
if (getsign(st0_ptr))
templ |= 0x80000000;
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE,single,4);
FPU_put_user(templ,(unsigned long __user *) single);
FPU_access_ok(VERIFY_WRITE, single, 4);
FPU_put_user(templ, (unsigned long __user *)single);
RE_ENTRANT_CHECK_ON;
return 1;
}
/* Put a long long into user memory */
int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d)
int FPU_store_int64(FPU_REG * st0_ptr, u_char st0_tag, long long __user * d)
{
FPU_REG t;
long long tll;
int precision_loss;
if ( st0_tag == TAG_Empty )
{
if (st0_tag == TAG_Empty) {
/* Empty register (stack underflow) */
EXCEPTION(EX_StackUnder);
goto invalid_operand;
}
else if ( st0_tag == TAG_Special )
{
} else if (st0_tag == TAG_Special) {
st0_tag = FPU_Special(st0_ptr);
if ( (st0_tag == TW_Infinity) ||
(st0_tag == TW_NaN) )
{
if ((st0_tag == TW_Infinity) || (st0_tag == TW_NaN)) {
EXCEPTION(EX_Invalid);
goto invalid_operand;
}
......@@ -882,32 +776,26 @@ int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d)
precision_loss = FPU_round_to_int(&t, st0_tag);
((long *)&tll)[0] = t.sigl;
((long *)&tll)[1] = t.sigh;
if ( (precision_loss == 1) ||
if ((precision_loss == 1) ||
((t.sigh & 0x80000000) &&
!((t.sigh == 0x80000000) && (t.sigl == 0) &&
signnegative(&t))) )
{
!((t.sigh == 0x80000000) && (t.sigl == 0) && signnegative(&t)))) {
EXCEPTION(EX_Invalid);
/* This is a special case: see sec 16.2.5.1 of the 80486 book */
invalid_operand:
if ( control_word & EX_Invalid )
{
if (control_word & EX_Invalid) {
/* Produce something like QNaN "indefinite" */
tll = 0x8000000000000000LL;
}
else
} else
return 0;
}
else
{
if ( precision_loss )
} else {
if (precision_loss)
set_precision_flag(precision_loss);
if ( signnegative(&t) )
tll = - tll;
if (signnegative(&t))
tll = -tll;
}
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE,d,8);
FPU_access_ok(VERIFY_WRITE, d, 8);
if (copy_to_user(d, &tll, 8))
FPU_abort;
RE_ENTRANT_CHECK_ON;
......@@ -915,25 +803,19 @@ int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d)
return 1;
}
/* Put a long into user memory */
int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long __user *d)
int FPU_store_int32(FPU_REG * st0_ptr, u_char st0_tag, long __user * d)
{
FPU_REG t;
int precision_loss;
if ( st0_tag == TAG_Empty )
{
if (st0_tag == TAG_Empty) {
/* Empty register (stack underflow) */
EXCEPTION(EX_StackUnder);
goto invalid_operand;
}
else if ( st0_tag == TAG_Special )
{
} else if (st0_tag == TAG_Special) {
st0_tag = FPU_Special(st0_ptr);
if ( (st0_tag == TW_Infinity) ||
(st0_tag == TW_NaN) )
{
if ((st0_tag == TW_Infinity) || (st0_tag == TW_NaN)) {
EXCEPTION(EX_Invalid);
goto invalid_operand;
}
......@@ -943,54 +825,43 @@ int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long __user *d)
precision_loss = FPU_round_to_int(&t, st0_tag);
if (t.sigh ||
((t.sigl & 0x80000000) &&
!((t.sigl == 0x80000000) && signnegative(&t))) )
{
!((t.sigl == 0x80000000) && signnegative(&t)))) {
EXCEPTION(EX_Invalid);
/* This is a special case: see sec 16.2.5.1 of the 80486 book */
invalid_operand:
if ( control_word & EX_Invalid )
{
if (control_word & EX_Invalid) {
/* Produce something like QNaN "indefinite" */
t.sigl = 0x80000000;
}
else
} else
return 0;
}
else
{
if ( precision_loss )
} else {
if (precision_loss)
set_precision_flag(precision_loss);
if ( signnegative(&t) )
if (signnegative(&t))
t.sigl = -(long)t.sigl;
}
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE,d,4);
FPU_put_user(t.sigl, (unsigned long __user *) d);
FPU_access_ok(VERIFY_WRITE, d, 4);
FPU_put_user(t.sigl, (unsigned long __user *)d);
RE_ENTRANT_CHECK_ON;
return 1;
}
/* Put a short into user memory */
int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short __user *d)
int FPU_store_int16(FPU_REG * st0_ptr, u_char st0_tag, short __user * d)
{
FPU_REG t;
int precision_loss;
if ( st0_tag == TAG_Empty )
{
if (st0_tag == TAG_Empty) {
/* Empty register (stack underflow) */
EXCEPTION(EX_StackUnder);
goto invalid_operand;
}
else if ( st0_tag == TAG_Special )
{
} else if (st0_tag == TAG_Special) {
st0_tag = FPU_Special(st0_ptr);
if ( (st0_tag == TW_Infinity) ||
(st0_tag == TW_NaN) )
{
if ((st0_tag == TW_Infinity) || (st0_tag == TW_NaN)) {
EXCEPTION(EX_Invalid);
goto invalid_operand;
}
......@@ -1000,38 +871,32 @@ int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short __user *d)
precision_loss = FPU_round_to_int(&t, st0_tag);
if (t.sigh ||
((t.sigl & 0xffff8000) &&
!((t.sigl == 0x8000) && signnegative(&t))) )
{
!((t.sigl == 0x8000) && signnegative(&t)))) {
EXCEPTION(EX_Invalid);
/* This is a special case: see sec 16.2.5.1 of the 80486 book */
invalid_operand:
if ( control_word & EX_Invalid )
{
if (control_word & EX_Invalid) {
/* Produce something like QNaN "indefinite" */
t.sigl = 0x8000;
}
else
} else
return 0;
}
else
{
if ( precision_loss )
} else {
if (precision_loss)
set_precision_flag(precision_loss);
if ( signnegative(&t) )
if (signnegative(&t))
t.sigl = -t.sigl;
}
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE,d,2);
FPU_access_ok(VERIFY_WRITE, d, 2);
FPU_put_user((short)t.sigl, d);
RE_ENTRANT_CHECK_ON;
return 1;
}
/* Put a packed bcd array into user memory */
int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d)
int FPU_store_bcd(FPU_REG * st0_ptr, u_char st0_tag, u_char __user * d)
{
FPU_REG t;
unsigned long long ll;
......@@ -1039,18 +904,13 @@ int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d)
int i, precision_loss;
u_char sign = (getsign(st0_ptr) == SIGN_NEG) ? 0x80 : 0;
if ( st0_tag == TAG_Empty )
{
if (st0_tag == TAG_Empty) {
/* Empty register (stack underflow) */
EXCEPTION(EX_StackUnder);
goto invalid_operand;
}
else if ( st0_tag == TAG_Special )
{
} else if (st0_tag == TAG_Special) {
st0_tag = FPU_Special(st0_ptr);
if ( (st0_tag == TW_Infinity) ||
(st0_tag == TW_NaN) )
{
if ((st0_tag == TW_Infinity) || (st0_tag == TW_NaN)) {
EXCEPTION(EX_Invalid);
goto invalid_operand;
}
......@@ -1061,47 +921,41 @@ int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d)
ll = significand(&t);
/* Check for overflow, by comparing with 999999999999999999 decimal. */
if ( (t.sigh > 0x0de0b6b3) ||
((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff)) )
{
if ((t.sigh > 0x0de0b6b3) ||
((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff))) {
EXCEPTION(EX_Invalid);
/* This is a special case: see sec 16.2.5.1 of the 80486 book */
invalid_operand:
if ( control_word & CW_Invalid )
{
if (control_word & CW_Invalid) {
/* Produce the QNaN "indefinite" */
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE,d,10);
for ( i = 0; i < 7; i++)
FPU_put_user(0, d+i); /* These bytes "undefined" */
FPU_put_user(0xc0, d+7); /* This byte "undefined" */
FPU_put_user(0xff, d+8);
FPU_put_user(0xff, d+9);
FPU_access_ok(VERIFY_WRITE, d, 10);
for (i = 0; i < 7; i++)
FPU_put_user(0, d + i); /* These bytes "undefined" */
FPU_put_user(0xc0, d + 7); /* This byte "undefined" */
FPU_put_user(0xff, d + 8);
FPU_put_user(0xff, d + 9);
RE_ENTRANT_CHECK_ON;
return 1;
}
else
} else
return 0;
}
else if ( precision_loss )
{
} else if (precision_loss) {
/* Precision loss doesn't stop the data transfer */
set_precision_flag(precision_loss);
}
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE,d,10);
FPU_access_ok(VERIFY_WRITE, d, 10);
RE_ENTRANT_CHECK_ON;
for ( i = 0; i < 9; i++)
{
for (i = 0; i < 9; i++) {
b = FPU_div_small(&ll, 10);
b |= (FPU_div_small(&ll, 10)) << 4;
RE_ENTRANT_CHECK_OFF;
FPU_put_user(b, d+i);
FPU_put_user(b, d + i);
RE_ENTRANT_CHECK_ON;
}
RE_ENTRANT_CHECK_OFF;
FPU_put_user(sign, d+9);
FPU_put_user(sign, d + 9);
RE_ENTRANT_CHECK_ON;
return 1;
......@@ -1117,20 +971,18 @@ int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d)
/* Overflow is signalled by a non-zero return value (in eax).
In the case of overflow, the returned significand always has the
largest possible value */
int FPU_round_to_int(FPU_REG *r, u_char tag)
int FPU_round_to_int(FPU_REG * r, u_char tag)
{
u_char very_big;
unsigned eax;
if (tag == TAG_Zero)
{
if (tag == TAG_Zero) {
/* Make sure that zero is returned */
significand(r) = 0;
return 0; /* o.k. */
}
if (exponent(r) > 63)
{
if (exponent(r) > 63) {
r->sigl = r->sigh = ~0; /* The largest representable number */
return 1; /* overflow */
}
......@@ -1140,30 +992,29 @@ int FPU_round_to_int(FPU_REG *r, u_char tag)
#define half_or_more (eax & 0x80000000)
#define frac_part (eax)
#define more_than_half ((eax & 0x80000001) == 0x80000001)
switch (control_word & CW_RC)
{
switch (control_word & CW_RC) {
case RC_RND:
if ( more_than_half /* nearest */
|| (half_or_more && (r->sigl & 1)) ) /* odd -> even */
{
if ( very_big ) return 1; /* overflow */
significand(r) ++;
if (more_than_half /* nearest */
|| (half_or_more && (r->sigl & 1))) { /* odd -> even */
if (very_big)
return 1; /* overflow */
significand(r)++;
return PRECISION_LOST_UP;
}
break;
case RC_DOWN:
if (frac_part && getsign(r))
{
if ( very_big ) return 1; /* overflow */
significand(r) ++;
if (frac_part && getsign(r)) {
if (very_big)
return 1; /* overflow */
significand(r)++;
return PRECISION_LOST_UP;
}
break;
case RC_UP:
if (frac_part && !getsign(r))
{
if ( very_big ) return 1; /* overflow */
significand(r) ++;
if (frac_part && !getsign(r)) {
if (very_big)
return 1; /* overflow */
significand(r)++;
return PRECISION_LOST_UP;
}
break;
......@@ -1177,46 +1028,52 @@ int FPU_round_to_int(FPU_REG *r, u_char tag)
/*===========================================================================*/
u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s)
u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user * s)
{
unsigned short tag_word = 0;
u_char tag;
int i;
if ( (addr_modes.default_mode == VM86) ||
if ((addr_modes.default_mode == VM86) ||
((addr_modes.default_mode == PM16)
^ (addr_modes.override.operand_size == OP_SIZE_PREFIX)) )
{
^ (addr_modes.override.operand_size == OP_SIZE_PREFIX))) {
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_READ, s, 0x0e);
FPU_get_user(control_word, (unsigned short __user *) s);
FPU_get_user(partial_status, (unsigned short __user *) (s+2));
FPU_get_user(tag_word, (unsigned short __user *) (s+4));
FPU_get_user(instruction_address.offset, (unsigned short __user *) (s+6));
FPU_get_user(instruction_address.selector, (unsigned short __user *) (s+8));
FPU_get_user(operand_address.offset, (unsigned short __user *) (s+0x0a));
FPU_get_user(operand_address.selector, (unsigned short __user *) (s+0x0c));
FPU_get_user(control_word, (unsigned short __user *)s);
FPU_get_user(partial_status, (unsigned short __user *)(s + 2));
FPU_get_user(tag_word, (unsigned short __user *)(s + 4));
FPU_get_user(instruction_address.offset,
(unsigned short __user *)(s + 6));
FPU_get_user(instruction_address.selector,
(unsigned short __user *)(s + 8));
FPU_get_user(operand_address.offset,
(unsigned short __user *)(s + 0x0a));
FPU_get_user(operand_address.selector,
(unsigned short __user *)(s + 0x0c));
RE_ENTRANT_CHECK_ON;
s += 0x0e;
if ( addr_modes.default_mode == VM86 )
{
if (addr_modes.default_mode == VM86) {
instruction_address.offset
+= (instruction_address.selector & 0xf000) << 4;
operand_address.offset += (operand_address.selector & 0xf000) << 4;
operand_address.offset +=
(operand_address.selector & 0xf000) << 4;
}
}
else
{
} else {
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_READ, s, 0x1c);
FPU_get_user(control_word, (unsigned short __user *) s);
FPU_get_user(partial_status, (unsigned short __user *) (s+4));
FPU_get_user(tag_word, (unsigned short __user *) (s+8));
FPU_get_user(instruction_address.offset, (unsigned long __user *) (s+0x0c));
FPU_get_user(instruction_address.selector, (unsigned short __user *) (s+0x10));
FPU_get_user(instruction_address.opcode, (unsigned short __user *) (s+0x12));
FPU_get_user(operand_address.offset, (unsigned long __user *) (s+0x14));
FPU_get_user(operand_address.selector, (unsigned long __user *) (s+0x18));
FPU_get_user(control_word, (unsigned short __user *)s);
FPU_get_user(partial_status, (unsigned short __user *)(s + 4));
FPU_get_user(tag_word, (unsigned short __user *)(s + 8));
FPU_get_user(instruction_address.offset,
(unsigned long __user *)(s + 0x0c));
FPU_get_user(instruction_address.selector,
(unsigned short __user *)(s + 0x10));
FPU_get_user(instruction_address.opcode,
(unsigned short __user *)(s + 0x12));
FPU_get_user(operand_address.offset,
(unsigned long __user *)(s + 0x14));
FPU_get_user(operand_address.selector,
(unsigned long __user *)(s + 0x18));
RE_ENTRANT_CHECK_ON;
s += 0x1c;
}
......@@ -1227,35 +1084,32 @@ u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s)
top = (partial_status >> SW_Top_Shift) & 7;
if ( partial_status & ~control_word & CW_Exceptions )
if (partial_status & ~control_word & CW_Exceptions)
partial_status |= (SW_Summary | SW_Backward);
else
partial_status &= ~(SW_Summary | SW_Backward);
for ( i = 0; i < 8; i++ )
{
for (i = 0; i < 8; i++) {
tag = tag_word & 3;
tag_word >>= 2;
if ( tag == TAG_Empty )
if (tag == TAG_Empty)
/* New tag is empty. Accept it */
FPU_settag(i, TAG_Empty);
else if ( FPU_gettag(i) == TAG_Empty )
{
else if (FPU_gettag(i) == TAG_Empty) {
/* Old tag is empty and new tag is not empty. New tag is determined
by old reg contents */
if ( exponent(&fpu_register(i)) == - EXTENDED_Ebias )
{
if ( !(fpu_register(i).sigl | fpu_register(i).sigh) )
if (exponent(&fpu_register(i)) == -EXTENDED_Ebias) {
if (!
(fpu_register(i).sigl | fpu_register(i).
sigh))
FPU_settag(i, TAG_Zero);
else
FPU_settag(i, TAG_Special);
}
else if ( exponent(&fpu_register(i)) == 0x7fff - EXTENDED_Ebias )
{
} else if (exponent(&fpu_register(i)) ==
0x7fff - EXTENDED_Ebias) {
FPU_settag(i, TAG_Special);
}
else if ( fpu_register(i).sigh & 0x80000000 )
} else if (fpu_register(i).sigh & 0x80000000)
FPU_settag(i, TAG_Valid);
else
FPU_settag(i, TAG_Special); /* An Un-normal */
......@@ -1267,8 +1121,7 @@ u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s)
return s;
}
void frstor(fpu_addr_modes addr_modes, u_char __user *data_address)
void frstor(fpu_addr_modes addr_modes, u_char __user * data_address)
{
int i, regnr;
u_char __user *s = fldenv(addr_modes, data_address);
......@@ -1276,59 +1129,56 @@ void frstor(fpu_addr_modes addr_modes, u_char __user *data_address)
/* Copy all registers in stack order. */
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_READ,s,80);
__copy_from_user(register_base+offset, s, other);
if ( offset )
__copy_from_user(register_base, s+other, offset);
FPU_access_ok(VERIFY_READ, s, 80);
__copy_from_user(register_base + offset, s, other);
if (offset)
__copy_from_user(register_base, s + other, offset);
RE_ENTRANT_CHECK_ON;
for ( i = 0; i < 8; i++ )
{
regnr = (i+top) & 7;
if ( FPU_gettag(regnr) != TAG_Empty )
for (i = 0; i < 8; i++) {
regnr = (i + top) & 7;
if (FPU_gettag(regnr) != TAG_Empty)
/* The loaded data over-rides all other cases. */
FPU_settag(regnr, FPU_tagof(&st(i)));
}
}
u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d)
u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user * d)
{
if ( (addr_modes.default_mode == VM86) ||
if ((addr_modes.default_mode == VM86) ||
((addr_modes.default_mode == PM16)
^ (addr_modes.override.operand_size == OP_SIZE_PREFIX)) )
{
^ (addr_modes.override.operand_size == OP_SIZE_PREFIX))) {
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE,d,14);
FPU_access_ok(VERIFY_WRITE, d, 14);
#ifdef PECULIAR_486
FPU_put_user(control_word & ~0xe080, (unsigned long __user *) d);
FPU_put_user(control_word & ~0xe080, (unsigned long __user *)d);
#else
FPU_put_user(control_word, (unsigned short __user *) d);
FPU_put_user(control_word, (unsigned short __user *)d);
#endif /* PECULIAR_486 */
FPU_put_user(status_word(), (unsigned short __user *) (d+2));
FPU_put_user(fpu_tag_word, (unsigned short __user *) (d+4));
FPU_put_user(instruction_address.offset, (unsigned short __user *) (d+6));
FPU_put_user(operand_address.offset, (unsigned short __user *) (d+0x0a));
if ( addr_modes.default_mode == VM86 )
{
FPU_put_user((instruction_address.offset & 0xf0000) >> 4,
(unsigned short __user *) (d+8));
FPU_put_user(status_word(), (unsigned short __user *)(d + 2));
FPU_put_user(fpu_tag_word, (unsigned short __user *)(d + 4));
FPU_put_user(instruction_address.offset,
(unsigned short __user *)(d + 6));
FPU_put_user(operand_address.offset,
(unsigned short __user *)(d + 0x0a));
if (addr_modes.default_mode == VM86) {
FPU_put_user((instruction_address.
offset & 0xf0000) >> 4,
(unsigned short __user *)(d + 8));
FPU_put_user((operand_address.offset & 0xf0000) >> 4,
(unsigned short __user *) (d+0x0c));
}
else
{
FPU_put_user(instruction_address.selector, (unsigned short __user *) (d+8));
FPU_put_user(operand_address.selector, (unsigned short __user *) (d+0x0c));
(unsigned short __user *)(d + 0x0c));
} else {
FPU_put_user(instruction_address.selector,
(unsigned short __user *)(d + 8));
FPU_put_user(operand_address.selector,
(unsigned short __user *)(d + 0x0c));
}
RE_ENTRANT_CHECK_ON;
d += 0x0e;
}
else
{
} else {
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE, d, 7*4);
FPU_access_ok(VERIFY_WRITE, d, 7 * 4);
#ifdef PECULIAR_486
control_word &= ~0xe080;
/* An 80486 sets nearly all of the reserved bits to 1. */
......@@ -1338,7 +1188,7 @@ u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d)
I387.soft.fcs &= ~0xf8000000;
I387.soft.fos |= 0xffff0000;
#endif /* PECULIAR_486 */
if (__copy_to_user(d, &control_word, 7*4))
if (__copy_to_user(d, &control_word, 7 * 4))
FPU_abort;
RE_ENTRANT_CHECK_ON;
d += 0x1c;
......@@ -1350,8 +1200,7 @@ u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d)
return d;
}
void fsave(fpu_addr_modes addr_modes, u_char __user *data_address)
void fsave(fpu_addr_modes addr_modes, u_char __user * data_address)
{
u_char __user *d;
int offset = (top & 7) * 10, other = 80 - offset;
......@@ -1359,13 +1208,13 @@ void fsave(fpu_addr_modes addr_modes, u_char __user *data_address)
d = fstenv(addr_modes, data_address);
RE_ENTRANT_CHECK_OFF;
FPU_access_ok(VERIFY_WRITE,d,80);
FPU_access_ok(VERIFY_WRITE, d, 80);
/* Copy all registers in stack order. */
if (__copy_to_user(d, register_base+offset, other))
if (__copy_to_user(d, register_base + offset, other))
FPU_abort;
if ( offset )
if (__copy_to_user(d+other, register_base, offset))
if (offset)
if (__copy_to_user(d + other, register_base, offset))
FPU_abort;
RE_ENTRANT_CHECK_ON;
......
......@@ -20,7 +20,6 @@
#include "reg_constant.h"
#include "fpu_system.h"
/*
Multiply two registers to give a register result.
The sources are st(deststnr) and (b,tagb,signb).
......@@ -36,14 +35,13 @@ int FPU_mul(FPU_REG const *b, u_char tagb, int deststnr, int control_w)
u_char sign = (getsign(a) ^ getsign(b));
int tag;
if ( !(taga | tagb) )
{
if (!(taga | tagb)) {
/* Both regs Valid, this should be the most common case. */
tag = FPU_u_mul(a, b, dest, control_w, sign, exponent(a) + exponent(b));
if ( tag < 0 )
{
tag =
FPU_u_mul(a, b, dest, control_w, sign,
exponent(a) + exponent(b));
if (tag < 0) {
setsign(dest, saved_sign);
return tag;
}
......@@ -51,35 +49,31 @@ int FPU_mul(FPU_REG const *b, u_char tagb, int deststnr, int control_w)
return tag;
}
if ( taga == TAG_Special )
if (taga == TAG_Special)
taga = FPU_Special(a);
if ( tagb == TAG_Special )
if (tagb == TAG_Special)
tagb = FPU_Special(b);
if ( ((taga == TAG_Valid) && (tagb == TW_Denormal))
if (((taga == TAG_Valid) && (tagb == TW_Denormal))
|| ((taga == TW_Denormal) && (tagb == TAG_Valid))
|| ((taga == TW_Denormal) && (tagb == TW_Denormal)) )
{
|| ((taga == TW_Denormal) && (tagb == TW_Denormal))) {
FPU_REG x, y;
if ( denormal_operand() < 0 )
if (denormal_operand() < 0)
return FPU_Exception;
FPU_to_exp16(a, &x);
FPU_to_exp16(b, &y);
tag = FPU_u_mul(&x, &y, dest, control_w, sign,
exponent16(&x) + exponent16(&y));
if ( tag < 0 )
{
if (tag < 0) {
setsign(dest, saved_sign);
return tag;
}
FPU_settagi(deststnr, tag);
return tag;
}
else if ( (taga <= TW_Denormal) && (tagb <= TW_Denormal) )
{
if ( ((tagb == TW_Denormal) || (taga == TW_Denormal))
&& (denormal_operand() < 0) )
} else if ((taga <= TW_Denormal) && (tagb <= TW_Denormal)) {
if (((tagb == TW_Denormal) || (taga == TW_Denormal))
&& (denormal_operand() < 0))
return FPU_Exception;
/* Must have either both arguments == zero, or
......@@ -93,37 +87,26 @@ int FPU_mul(FPU_REG const *b, u_char tagb, int deststnr, int control_w)
return TAG_Zero;
}
/* Must have infinities, NaNs, etc */
else if ( (taga == TW_NaN) || (tagb == TW_NaN) )
{
else if ((taga == TW_NaN) || (tagb == TW_NaN)) {
return real_2op_NaN(b, tagb, deststnr, &st(0));
}
else if ( ((taga == TW_Infinity) && (tagb == TAG_Zero))
|| ((tagb == TW_Infinity) && (taga == TAG_Zero)) )
{
} else if (((taga == TW_Infinity) && (tagb == TAG_Zero))
|| ((tagb == TW_Infinity) && (taga == TAG_Zero))) {
return arith_invalid(deststnr); /* Zero*Infinity is invalid */
}
else if ( ((taga == TW_Denormal) || (tagb == TW_Denormal))
&& (denormal_operand() < 0) )
{
} else if (((taga == TW_Denormal) || (tagb == TW_Denormal))
&& (denormal_operand() < 0)) {
return FPU_Exception;
}
else if (taga == TW_Infinity)
{
} else if (taga == TW_Infinity) {
FPU_copy_to_regi(a, TAG_Special, deststnr);
setsign(dest, sign);
return TAG_Special;
}
else if (tagb == TW_Infinity)
{
} else if (tagb == TW_Infinity) {
FPU_copy_to_regi(b, TAG_Special, deststnr);
setsign(dest, sign);
return TAG_Special;
}
#ifdef PARANOID
else
{
EXCEPTION(EX_INTERNAL|0x102);
else {
EXCEPTION(EX_INTERNAL | 0x102);
return FPU_Exception;
}
#endif /* PARANOID */
......
......@@ -50,8 +50,8 @@
((partial_status & ~SW_Top & 0xffff) | ((top << SW_Top_Shift) & SW_Top))
static inline void setcc(int cc)
{
partial_status &= ~(SW_C0|SW_C1|SW_C2|SW_C3);
partial_status |= (cc) & (SW_C0|SW_C1|SW_C2|SW_C3);
partial_status &= ~(SW_C0 | SW_C1 | SW_C2 | SW_C3);
partial_status |= (cc) & (SW_C0 | SW_C1 | SW_C2 | SW_C3);
}
#ifdef PECULIAR_486
......
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