Commit 893c4d2f authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.18

parent 9ec7e58c
VERSION = 1 VERSION = 1
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 17 SUBLEVEL = 18
all: Version zImage all: Version zImage
......
...@@ -5,14 +5,13 @@ ...@@ -5,14 +5,13 @@
#DEBUG = -DDEBUGGING #DEBUG = -DDEBUGGING
DEBUG = DEBUG =
PARANOID = -DPARANOID PARANOID = -DPARANOID
REENTRANT = -DREENTRANT_FPU
CFLAGS := $(CFLAGS) $(PARANOID) $(DEBUG) -fno-builtin CFLAGS := $(CFLAGS) $(PARANOID) $(DEBUG) -fno-builtin
.c.o: .c.o:
$(CC) $(CFLAGS) $(MATH_EMULATION) -c $< $(CC) $(CFLAGS) $(MATH_EMULATION) -c $<
.S.o: .S.o:
$(CC) -D__ASSEMBLER__ $(PARANOID) $(REENTRANT) -c $< $(CC) -D__ASSEMBLER__ $(PARANOID) -c $<
.s.o: .s.o:
$(CC) -c $< $(CC) -c $<
......
...@@ -47,7 +47,7 @@ Please report bugs, etc to me at: ...@@ -47,7 +47,7 @@ Please report bugs, etc to me at:
--Bill Metzenthen --Bill Metzenthen
March 1994 June 1994
----------------------- Internals of wm-FPU-emu ----------------------- ----------------------- Internals of wm-FPU-emu -----------------------
...@@ -80,20 +80,24 @@ emulate each FPU instruction to completion without interruption. ...@@ -80,20 +80,24 @@ emulate each FPU instruction to completion without interruption.
However, it may happen that when the emulator is accessing the user However, it may happen that when the emulator is accessing the user
memory space, swapping may be needed. In this case the emulator may be memory space, swapping may be needed. In this case the emulator may be
temporarily suspended while disk i/o takes place. During this time temporarily suspended while disk i/o takes place. During this time
another process may use the emulator, thereby changing some static another process may use the emulator, thereby perhaps changing static
variables (eg FPU_st0_ptr, etc). The code which accesses user memory variables. The code which accesses user memory is confined to five
is confined to five files: files:
fpu_entry.c fpu_entry.c
reg_ld_str.c reg_ld_str.c
load_store.c load_store.c
get_address.c get_address.c
errors.c errors.c
As from version 1.12 of the emulator, no static variables are used
(apart from those in the kernel's per-process tables). The emulator is
therefore now fully re-entrant, rather than having just the restricted
form of re-entrancy which is required by the Linux kernel.
----------------------- Limitations of wm-FPU-emu ----------------------- ----------------------- Limitations of wm-FPU-emu -----------------------
There are a number of differences between the current wm-FPU-emu There are a number of differences between the current wm-FPU-emu
(version beta 1.11) and the 80486 FPU (apart from bugs). Some of the (version 1.12) and the 80486 FPU (apart from bugs). Some of the more
more important differences are listed below: important differences are listed below:
The Roundup flag does not have much meaning for the transcendental The Roundup flag does not have much meaning for the transcendental
functions and its 80486 value with these functions is likely to differ functions and its 80486 value with these functions is likely to differ
...@@ -154,6 +158,11 @@ crashes dosemu under Linux and also brings Windows down with a general ...@@ -154,6 +158,11 @@ crashes dosemu under Linux and also brings Windows down with a general
protection fault message when run under the MS-DOS prompt of Windows protection fault message when run under the MS-DOS prompt of Windows
3.1. (The program simply reads data from a valid address). 3.1. (The program simply reads data from a valid address).
The emulator supports 16-bit protected mode, with one difference from
an 80486DX. A 80486DX will allow some floating point instructions to
write a few bytes below the lowest address of the stack. The emulator
will not allow this in 16-bit protected mode: no instructions are
allowed to write outside the bounds set by the protection.
----------------------- Performance of wm-FPU-emu ----------------------- ----------------------- Performance of wm-FPU-emu -----------------------
...@@ -322,6 +331,7 @@ Hamish Coleman, t933093@minyos.xx.rmit.oz.au ...@@ -322,6 +331,7 @@ Hamish Coleman, t933093@minyos.xx.rmit.oz.au
Bruce Evans, bde@kralizec.zeta.org.au Bruce Evans, bde@kralizec.zeta.org.au
Timo Korvola, Timo.Korvola@hut.fi Timo Korvola, Timo.Korvola@hut.fi
Rick Lyons, rick@razorback.brisnet.org.au Rick Lyons, rick@razorback.brisnet.org.au
Rick, jrs@world.std.com
...and numerous others who responded to my request for help with ...and numerous others who responded to my request for help with
a real 80486. a real 80486.
......
...@@ -42,6 +42,8 @@ void Un_impl(void) ...@@ -42,6 +42,8 @@ void Un_impl(void)
RE_ENTRANT_CHECK_OFF; RE_ENTRANT_CHECK_OFF;
/* No need to verify_area(), we have previously fetched these bytes. */ /* No need to verify_area(), we have previously fetched these bytes. */
printk("Unimplemented FPU Opcode at eip=%p : ", (void *) address); printk("Unimplemented FPU Opcode at eip=%p : ", (void *) address);
if ( FPU_CS == USER_CS )
{
while ( 1 ) while ( 1 )
{ {
byte1 = get_fs_byte((unsigned char *) address); byte1 = get_fs_byte((unsigned char *) address);
...@@ -56,6 +58,12 @@ void Un_impl(void) ...@@ -56,6 +58,12 @@ void Un_impl(void)
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 else
printk("/%d\n", (FPU_modrm >> 3) & 7); printk("/%d\n", (FPU_modrm >> 3) & 7);
}
else
{
printk("cs selector = %04x\n", FPU_CS);
}
RE_ENTRANT_CHECK_ON; RE_ENTRANT_CHECK_ON;
EXCEPTION(EX_Invalid); EXCEPTION(EX_Invalid);
...@@ -85,6 +93,8 @@ void emu_printall() ...@@ -85,6 +93,8 @@ void emu_printall()
RE_ENTRANT_CHECK_OFF; RE_ENTRANT_CHECK_OFF;
/* No need to verify_area(), we have previously fetched these bytes. */ /* No need to verify_area(), we have previously fetched these bytes. */
printk("At %p:", (void *) address); printk("At %p:", (void *) address);
if ( FPU_CS == USER_CS )
{
#define MAX_PRINTED_BYTES 20 #define MAX_PRINTED_BYTES 20
for ( i = 0; i < MAX_PRINTED_BYTES; i++ ) for ( i = 0; i < MAX_PRINTED_BYTES; i++ )
{ {
...@@ -109,6 +119,11 @@ void emu_printall() ...@@ -109,6 +119,11 @@ void emu_printall()
printk(" /%d, mod=%d rm=%d\n", 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
{
printk("%04x\n", FPU_CS);
}
partial_status = status_word(); partial_status = status_word();
...@@ -181,6 +196,7 @@ printk(" CW: ic=%d rc=%ld%ld pc=%ld%ld iem=%d ef=%d%d%d%d%d%d\n", ...@@ -181,6 +196,7 @@ printk(" CW: ic=%d rc=%ld%ld pc=%ld%ld iem=%d ef=%d%d%d%d%d%d\n",
printk("%s\n", tag_desc[(int) (unsigned) r->tag]); printk("%s\n", tag_desc[(int) (unsigned) r->tag]);
} }
#ifdef OBSOLETE
printk("[data] %c .%04lx %04lx %04lx %04lx e%+-6ld ", printk("[data] %c .%04lx %04lx %04lx %04lx e%+-6ld ",
FPU_loaded_data.sign ? '-' : '+', FPU_loaded_data.sign ? '-' : '+',
(long)(FPU_loaded_data.sigh >> 16), (long)(FPU_loaded_data.sigh >> 16),
...@@ -189,6 +205,7 @@ printk(" CW: ic=%d rc=%ld%ld pc=%ld%ld iem=%d ef=%d%d%d%d%d%d\n", ...@@ -189,6 +205,7 @@ printk(" CW: ic=%d rc=%ld%ld pc=%ld%ld iem=%d ef=%d%d%d%d%d%d\n",
(long)(FPU_loaded_data.sigl & 0xFFFF), (long)(FPU_loaded_data.sigl & 0xFFFF),
FPU_loaded_data.exp - EXP_BIAS + 1); FPU_loaded_data.exp - EXP_BIAS + 1);
printk("%s\n", tag_desc[(int) (unsigned) FPU_loaded_data.tag]); printk("%s\n", tag_desc[(int) (unsigned) FPU_loaded_data.tag]);
#endif OBSOLETE
RE_ENTRANT_CHECK_ON; RE_ENTRANT_CHECK_ON;
} }
...@@ -214,7 +231,6 @@ static struct { ...@@ -214,7 +231,6 @@ static struct {
error was detected. error was detected.
Internal error types: Internal error types:
0 in load_store.c
0x14 in fpu_etc.c 0x14 in fpu_etc.c
0x1nn in a *.c file: 0x1nn in a *.c file:
0x101 in reg_add_sub.c 0x101 in reg_add_sub.c
...@@ -244,7 +260,13 @@ static struct { ...@@ -244,7 +260,13 @@ static struct {
0x126 in fpu_entry.c 0x126 in fpu_entry.c
0x127 in poly_2xm1.c 0x127 in poly_2xm1.c
0x128 in fpu_entry.c 0x128 in fpu_entry.c
0x129 in fpu_entry.c
0x130 in get_address.c 0x130 in get_address.c
0x131 in get_address.c
0x132 in get_address.c
0x133 in get_address.c
0x140 in load_store.c
0x141 in load_store.c
0x2nn in an *.S file: 0x2nn in an *.S file:
0x201 in reg_u_add.S 0x201 in reg_u_add.S
0x202 in reg_u_div.S 0x202 in reg_u_div.S
...@@ -583,7 +605,7 @@ void stack_overflow(void) ...@@ -583,7 +605,7 @@ void stack_overflow(void)
{ {
/* The masked response */ /* The masked response */
top--; top--;
reg_move(&CONST_QNaN, FPU_st0_ptr = &st(0)); reg_move(&CONST_QNaN, &st(0));
} }
EXCEPTION(EX_StackOver); EXCEPTION(EX_StackOver);
...@@ -599,7 +621,7 @@ void stack_underflow(void) ...@@ -599,7 +621,7 @@ void stack_underflow(void)
if ( control_word & CW_Invalid ) if ( control_word & CW_Invalid )
{ {
/* The masked response */ /* The masked response */
reg_move(&CONST_QNaN, FPU_st0_ptr); reg_move(&CONST_QNaN, &st(0));
} }
EXCEPTION(EX_StackUnder); EXCEPTION(EX_StackUnder);
......
...@@ -20,7 +20,7 @@ void fadd__() ...@@ -20,7 +20,7 @@ void fadd__()
{ {
/* fadd st,st(i) */ /* fadd st,st(i) */
clear_C1(); clear_C1();
reg_add(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); reg_add(&st(0), &st(FPU_rm), &st(0), control_word);
} }
...@@ -28,7 +28,7 @@ void fmul__() ...@@ -28,7 +28,7 @@ void fmul__()
{ {
/* fmul st,st(i) */ /* fmul st,st(i) */
clear_C1(); clear_C1();
reg_mul(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); reg_mul(&st(0), &st(FPU_rm), &st(0), control_word);
} }
...@@ -37,7 +37,7 @@ void fsub__() ...@@ -37,7 +37,7 @@ void fsub__()
{ {
/* fsub st,st(i) */ /* fsub st,st(i) */
clear_C1(); clear_C1();
reg_sub(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); reg_sub(&st(0), &st(FPU_rm), &st(0), control_word);
} }
...@@ -45,7 +45,7 @@ void fsubr_() ...@@ -45,7 +45,7 @@ void fsubr_()
{ {
/* fsubr st,st(i) */ /* fsubr st,st(i) */
clear_C1(); clear_C1();
reg_sub(&st(FPU_rm), FPU_st0_ptr, FPU_st0_ptr, control_word); reg_sub(&st(FPU_rm), &st(0), &st(0), control_word);
} }
...@@ -53,7 +53,7 @@ void fdiv__() ...@@ -53,7 +53,7 @@ void fdiv__()
{ {
/* fdiv st,st(i) */ /* fdiv st,st(i) */
clear_C1(); clear_C1();
reg_div(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word); reg_div(&st(0), &st(FPU_rm), &st(0), control_word);
} }
...@@ -61,7 +61,7 @@ void fdivr_() ...@@ -61,7 +61,7 @@ void fdivr_()
{ {
/* fdivr st,st(i) */ /* fdivr st,st(i) */
clear_C1(); clear_C1();
reg_div(&st(FPU_rm), FPU_st0_ptr, FPU_st0_ptr, control_word); reg_div(&st(FPU_rm), &st(0), &st(0), control_word);
} }
...@@ -70,7 +70,7 @@ void fadd_i() ...@@ -70,7 +70,7 @@ void fadd_i()
{ {
/* fadd st(i),st */ /* fadd st(i),st */
clear_C1(); clear_C1();
reg_add(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); reg_add(&st(0), &st(FPU_rm), &st(FPU_rm), control_word);
} }
...@@ -78,7 +78,7 @@ void fmul_i() ...@@ -78,7 +78,7 @@ void fmul_i()
{ {
/* fmul st(i),st */ /* fmul st(i),st */
clear_C1(); clear_C1();
reg_mul(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); reg_mul(&st(0), &st(FPU_rm), &st(FPU_rm), control_word);
} }
...@@ -86,9 +86,9 @@ void fsubri() ...@@ -86,9 +86,9 @@ void fsubri()
{ {
/* fsubr st(i),st */ /* fsubr st(i),st */
/* This is the sense of the 80486 manual /* This is the sense of the 80486 manual
reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); */ reg_sub(&st(FPU_rm), &st(0), &st(FPU_rm), control_word); */
clear_C1(); clear_C1();
reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); reg_sub(&st(0), &st(FPU_rm), &st(FPU_rm), control_word);
} }
...@@ -96,9 +96,9 @@ void fsub_i() ...@@ -96,9 +96,9 @@ void fsub_i()
{ {
/* fsub st(i),st */ /* fsub st(i),st */
/* This is the sense of the 80486 manual /* This is the sense of the 80486 manual
reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); */ reg_sub(&st(0), &st(FPU_rm), &st(FPU_rm), control_word); */
clear_C1(); clear_C1();
reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); reg_sub(&st(FPU_rm), &st(0), &st(FPU_rm), control_word);
} }
...@@ -106,7 +106,7 @@ void fdivri() ...@@ -106,7 +106,7 @@ void fdivri()
{ {
/* fdivr st(i),st */ /* fdivr st(i),st */
clear_C1(); clear_C1();
reg_div(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); reg_div(&st(0), &st(FPU_rm), &st(FPU_rm), control_word);
} }
...@@ -114,7 +114,7 @@ void fdiv_i() ...@@ -114,7 +114,7 @@ void fdiv_i()
{ {
/* fdiv st(i),st */ /* fdiv st(i),st */
clear_C1(); clear_C1();
reg_div(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); reg_div(&st(FPU_rm), &st(0), &st(FPU_rm), control_word);
} }
...@@ -123,7 +123,7 @@ void faddp_() ...@@ -123,7 +123,7 @@ void faddp_()
{ {
/* faddp st(i),st */ /* faddp st(i),st */
clear_C1(); clear_C1();
if ( !reg_add(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word) ) if ( !reg_add(&st(0), &st(FPU_rm), &st(FPU_rm), control_word) )
pop(); pop();
} }
...@@ -132,7 +132,7 @@ void fmulp_() ...@@ -132,7 +132,7 @@ void fmulp_()
{ {
/* fmulp st(i),st */ /* fmulp st(i),st */
clear_C1(); clear_C1();
if ( !reg_mul(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word) ) if ( !reg_mul(&st(0), &st(FPU_rm), &st(FPU_rm), control_word) )
pop(); pop();
} }
...@@ -142,9 +142,9 @@ void fsubrp() ...@@ -142,9 +142,9 @@ void fsubrp()
{ {
/* fsubrp st(i),st */ /* fsubrp st(i),st */
/* This is the sense of the 80486 manual /* This is the sense of the 80486 manual
reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); */ reg_sub(&st(FPU_rm), &st(0), &st(FPU_rm), control_word); */
clear_C1(); clear_C1();
if ( !reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word) ) if ( !reg_sub(&st(0), &st(FPU_rm), &st(FPU_rm), control_word) )
pop(); pop();
} }
...@@ -153,9 +153,9 @@ void fsubp_() ...@@ -153,9 +153,9 @@ void fsubp_()
{ {
/* fsubp st(i),st */ /* fsubp st(i),st */
/* This is the sense of the 80486 manual /* This is the sense of the 80486 manual
reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); */ reg_sub(&st(0), &st(FPU_rm), &st(FPU_rm), control_word); */
clear_C1(); clear_C1();
if ( !reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word) ) if ( !reg_sub(&st(FPU_rm), &st(0), &st(FPU_rm), control_word) )
pop(); pop();
} }
...@@ -164,7 +164,7 @@ void fdivrp() ...@@ -164,7 +164,7 @@ void fdivrp()
{ {
/* fdivrp st(i),st */ /* fdivrp st(i),st */
clear_C1(); clear_C1();
if ( !reg_div(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word) ) if ( !reg_div(&st(0), &st(FPU_rm), &st(FPU_rm), control_word) )
pop(); pop();
} }
...@@ -173,7 +173,7 @@ void fdivp_() ...@@ -173,7 +173,7 @@ void fdivp_()
{ {
/* fdivp st(i),st */ /* fdivp st(i),st */
clear_C1(); clear_C1();
if ( !reg_div(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word) ) if ( !reg_div(&st(FPU_rm), &st(0), &st(FPU_rm), control_word) )
pop(); pop();
} }
...@@ -26,8 +26,7 @@ void fclex(void) ...@@ -26,8 +26,7 @@ void fclex(void)
partial_status &= ~(SW_Backward|SW_Summary|SW_Stack_Fault|SW_Precision| partial_status &= ~(SW_Backward|SW_Summary|SW_Stack_Fault|SW_Precision|
SW_Underflow|SW_Overflow|SW_Zero_Div|SW_Denorm_Op| SW_Underflow|SW_Overflow|SW_Zero_Div|SW_Denorm_Op|
SW_Invalid); SW_Invalid);
NO_NET_DATA_EFFECT; no_ip_update = 1;
FPU_entry_eip = ip_offset; /* We want no net effect */
} }
/* Needs to be externally visible */ /* Needs to be externally visible */
...@@ -43,11 +42,12 @@ void finit() ...@@ -43,11 +42,12 @@ void finit()
} }
/* The behaviour is different to that detailed in /* The behaviour is different to that detailed in
Section 15.1.6 of the Intel manual */ Section 15.1.6 of the Intel manual */
data_operand_offset = 0; operand_address.offset = 0;
operand_selector = 0; operand_address.selector = 0;
NO_NET_DATA_EFFECT; instruction_address.offset = 0;
FPU_entry_op_cs = 0; instruction_address.selector = 0;
FPU_entry_eip = ip_offset = 0; instruction_address.opcode = 0;
no_ip_update = 1;
} }
/* /*
...@@ -71,7 +71,7 @@ void finit_() ...@@ -71,7 +71,7 @@ void finit_()
static void fstsw_ax(void) static void fstsw_ax(void)
{ {
*(short *) &FPU_EAX = status_word(); *(short *) &FPU_EAX = status_word();
NO_NET_INSTR_EFFECT; no_ip_update = 1;
} }
static FUNC const fstsw_table[] = { static FUNC const fstsw_table[] = {
...@@ -108,10 +108,9 @@ void fld_i_() ...@@ -108,10 +108,9 @@ void fld_i_()
{ reg_move(&st(FPU_rm), st_new_ptr); push(); } { reg_move(&st(FPU_rm), st_new_ptr); push(); }
else else
{ {
if ( control_word & EX_Invalid ) if ( control_word & CW_Invalid )
{ {
/* The masked response */ /* The masked response */
push();
stack_underflow(); stack_underflow();
} }
else else
...@@ -125,9 +124,9 @@ void fxch_i() ...@@ -125,9 +124,9 @@ void fxch_i()
{ {
/* fxch st(i) */ /* fxch st(i) */
FPU_REG t; FPU_REG t;
register FPU_REG *sti_ptr = &st(FPU_rm); register FPU_REG *sti_ptr = &st(FPU_rm), *st0_ptr = &st(0);
if ( FPU_st0_tag == TW_Empty ) if ( st0_ptr->tag == TW_Empty )
{ {
if ( sti_ptr->tag == TW_Empty ) if ( sti_ptr->tag == TW_Empty )
{ {
...@@ -136,20 +135,20 @@ void fxch_i() ...@@ -136,20 +135,20 @@ void fxch_i()
return; return;
} }
if ( control_word & CW_Invalid ) if ( control_word & CW_Invalid )
reg_move(sti_ptr, FPU_st0_ptr); /* Masked response */ reg_move(sti_ptr, st0_ptr); /* Masked response */
stack_underflow_i(FPU_rm); stack_underflow_i(FPU_rm);
return; return;
} }
if ( sti_ptr->tag == TW_Empty ) if ( sti_ptr->tag == TW_Empty )
{ {
if ( control_word & CW_Invalid ) if ( control_word & CW_Invalid )
reg_move(FPU_st0_ptr, sti_ptr); /* Masked response */ reg_move(st0_ptr, sti_ptr); /* Masked response */
stack_underflow(); stack_underflow();
return; return;
} }
clear_C1(); clear_C1();
reg_move(FPU_st0_ptr, &t); reg_move(st0_ptr, &t);
reg_move(sti_ptr, FPU_st0_ptr); reg_move(sti_ptr, st0_ptr);
reg_move(&t, sti_ptr); reg_move(&t, sti_ptr);
} }
...@@ -172,14 +171,14 @@ void ffreep() ...@@ -172,14 +171,14 @@ void ffreep()
void fst_i_() void fst_i_()
{ {
/* fst st(i) */ /* fst st(i) */
reg_move(FPU_st0_ptr, &st(FPU_rm)); reg_move(&st(0), &st(FPU_rm));
} }
void fstp_i() void fstp_i()
{ {
/* fstp st(i) */ /* fstp st(i) */
reg_move(FPU_st0_ptr, &st(FPU_rm)); reg_move(&st(0), &st(FPU_rm));
pop(); pop();
} }
...@@ -60,14 +60,18 @@ ...@@ -60,14 +60,18 @@
#include <linux/math_emu.h> #include <linux/math_emu.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#ifdef PARANOID /*
#define RE_ENTRANT_CHECKING
*/
#ifdef RE_ENTRANT_CHECKING
extern char emulating; extern char emulating;
# define RE_ENTRANT_CHECK_OFF emulating = 0 # define RE_ENTRANT_CHECK_OFF emulating = 0
# define RE_ENTRANT_CHECK_ON emulating = 1 # define RE_ENTRANT_CHECK_ON emulating = 1
#else #else
# define RE_ENTRANT_CHECK_OFF # define RE_ENTRANT_CHECK_OFF
# define RE_ENTRANT_CHECK_ON # define RE_ENTRANT_CHECK_ON
#endif PARANOID #endif RE_ENTRANT_CHECKING
#define FWAIT_OPCODE 0x9b #define FWAIT_OPCODE 0x9b
#define OP_SIZE_PREFIX 0x66 #define OP_SIZE_PREFIX 0x66
...@@ -89,46 +93,43 @@ extern char emulating; ...@@ -89,46 +93,43 @@ extern char emulating;
#define PREFIX_SS_ 6 #define PREFIX_SS_ 6
#define PREFIX_DEFAULT 7 #define PREFIX_DEFAULT 7
/* These are to defeat the default action, giving the instruction struct address {
no net effect: */ unsigned int offset;
#define NO_NET_DATA_EFFECT \ unsigned int selector:16;
{ FPU_data_address = (void *)data_operand_offset; \ unsigned int opcode:11;
FPU_data_selector = operand_selector; } unsigned int empty:5;
#define NO_NET_INSTR_EFFECT \ };
{ FPU_entry_eip = ip_offset; \
FPU_entry_op_cs = cs_selector; }
typedef void (*FUNC)(void); typedef void (*FUNC)(void);
typedef struct fpu_reg FPU_REG; typedef struct fpu_reg FPU_REG;
typedef void (*FUNC_ST0)(FPU_REG *st0_ptr);
typedef struct { unsigned char address_size, operand_size, segment; } typedef struct { unsigned char address_size, operand_size, segment; }
overrides; overrides;
/* This structure is 48 bits: */ /* This structure is 32 bits: */
typedef struct { overrides override; typedef struct { overrides override;
unsigned char mode16, vm86, p286; } fpu_addr_modes; unsigned 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. */
#define PROTECTED 4
#define SIXTEEN 1 /* We rely upon this being 1 (true) */
#define VM86 SIXTEEN
#define PM16 (SIXTEEN | PROTECTED)
#define SEG32 PROTECTED
extern unsigned char const data_sizes_16[32];
#define st(x) ( regs[((top+x) &7 )] ) #define st(x) ( regs[((top+x) &7 )] )
#define STACK_OVERFLOW (st_new_ptr = &st(-1), st_new_ptr->tag != TW_Empty) #define STACK_OVERFLOW (st_new_ptr = &st(-1), st_new_ptr->tag != TW_Empty)
#define NOT_EMPTY(i) (st(i).tag != TW_Empty) #define NOT_EMPTY(i) (st(i).tag != TW_Empty)
#define NOT_EMPTY_0 (FPU_st0_tag ^ TW_Empty) #define NOT_EMPTY_ST0 (st0_tag ^ TW_Empty)
extern unsigned char FPU_rm;
extern char FPU_st0_tag;
extern FPU_REG *FPU_st0_ptr;
/* ###### These need to be shifted to somewhere safe. */
/* extern void *FPU_data_address; has been shifted */
extern unsigned short FPU_data_selector;
extern unsigned long FPU_entry_op_cs;
extern FPU_REG FPU_loaded_data;
#define pop() { FPU_st0_ptr->tag = TW_Empty; top++; } #define pop() { regs[(top++ & 7 )].tag = TW_Empty; }
#define poppop() { regs[((top + 1) & 7 )].tag \
= regs[(top & 7 )].tag = TW_Empty; \
top += 2; }
/* push() does not affect the tags */ /* push() does not affect the tags */
#define push() { top--; FPU_st0_ptr = st_new_ptr; } #define push() { top--; }
#define reg_move(x, y) { \ #define reg_move(x, y) { \
......
This diff is collapsed.
...@@ -17,22 +17,22 @@ ...@@ -17,22 +17,22 @@
#include "reg_constant.h" #include "reg_constant.h"
static void fchs(void) static void fchs(FPU_REG *st0_ptr)
{ {
if ( NOT_EMPTY_0 ) if ( st0_ptr->tag ^ TW_Empty )
{ {
FPU_st0_ptr->sign ^= SIGN_POS^SIGN_NEG; st0_ptr->sign ^= SIGN_POS^SIGN_NEG;
clear_C1(); clear_C1();
} }
else else
stack_underflow(); stack_underflow();
} }
static void fabs(void) static void fabs(FPU_REG *st0_ptr)
{ {
if ( FPU_st0_tag ^ TW_Empty ) if ( st0_ptr->tag ^ TW_Empty )
{ {
FPU_st0_ptr->sign = SIGN_POS; st0_ptr->sign = SIGN_POS;
clear_C1(); clear_C1();
} }
else else
...@@ -40,25 +40,25 @@ static void fabs(void) ...@@ -40,25 +40,25 @@ static void fabs(void)
} }
static void ftst_(void) static void ftst_(FPU_REG *st0_ptr)
{ {
switch (FPU_st0_tag) switch (st0_ptr->tag)
{ {
case TW_Zero: case TW_Zero:
setcc(SW_C3); setcc(SW_C3);
break; break;
case TW_Valid: case TW_Valid:
if (FPU_st0_ptr->sign == SIGN_POS) if (st0_ptr->sign == SIGN_POS)
setcc(0); setcc(0);
else else
setcc(SW_C0); setcc(SW_C0);
#ifdef DENORM_OPERAND #ifdef DENORM_OPERAND
if ( (FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) ) if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
{ {
#ifdef PECULIAR_486 #ifdef PECULIAR_486
/* This is wierd! */ /* This is wierd! */
if (FPU_st0_ptr->sign == SIGN_POS) if (st0_ptr->sign == SIGN_POS)
setcc(SW_C3); setcc(SW_C3);
#endif PECULIAR_486 #endif PECULIAR_486
return; return;
...@@ -71,7 +71,7 @@ static void ftst_(void) ...@@ -71,7 +71,7 @@ static void ftst_(void)
EXCEPTION(EX_Invalid); EXCEPTION(EX_Invalid);
break; break;
case TW_Infinity: case TW_Infinity:
if (FPU_st0_ptr->sign == SIGN_POS) if (st0_ptr->sign == SIGN_POS)
setcc(0); setcc(0);
else else
setcc(SW_C0); setcc(SW_C0);
...@@ -87,10 +87,10 @@ static void ftst_(void) ...@@ -87,10 +87,10 @@ static void ftst_(void)
} }
} }
static void fxam(void) static void fxam(FPU_REG *st0_ptr)
{ {
int c=0; int c=0;
switch (FPU_st0_tag) switch (st0_ptr->tag)
{ {
case TW_Empty: case TW_Empty:
c = SW_C3|SW_C0; c = SW_C3|SW_C0;
...@@ -100,7 +100,7 @@ static void fxam(void) ...@@ -100,7 +100,7 @@ static void fxam(void)
break; break;
case TW_Valid: case TW_Valid:
/* This will need to be changed if TW_Denormal is ever used. */ /* This will need to be changed if TW_Denormal is ever used. */
if ( FPU_st0_ptr->exp <= EXP_UNDER ) if ( st0_ptr->exp <= EXP_UNDER )
c = SW_C2|SW_C3; /* Denormal */ c = SW_C2|SW_C3; /* Denormal */
else else
c = SW_C2; c = SW_C2;
...@@ -112,16 +112,18 @@ static void fxam(void) ...@@ -112,16 +112,18 @@ static void fxam(void)
c = SW_C2|SW_C0; c = SW_C2|SW_C0;
break; break;
} }
if (FPU_st0_ptr->sign == SIGN_NEG) if (st0_ptr->sign == SIGN_NEG)
c |= SW_C1; c |= SW_C1;
setcc(c); setcc(c);
} }
static FUNC const fp_etc_table[] = {
fchs, fabs, FPU_illegal, FPU_illegal, ftst_, fxam, FPU_illegal, FPU_illegal 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
}; };
void fp_etc() void fp_etc()
{ {
(fp_etc_table[FPU_rm])(); (fp_etc_table[FPU_rm])(&st(0));
} }
...@@ -63,13 +63,16 @@ extern void trig_a(void); ...@@ -63,13 +63,16 @@ extern void trig_a(void);
extern void trig_b(void); extern void trig_b(void);
/* get_address.c */ /* get_address.c */
extern void get_address(unsigned char FPU_modrm, unsigned long *fpu_eip, extern void *get_address(unsigned char FPU_modrm, unsigned long *fpu_eip,
struct address *addr,
fpu_addr_modes); fpu_addr_modes);
extern void get_address_16(unsigned char FPU_modrm, unsigned long *fpu_eip, extern void *get_address_16(unsigned char FPU_modrm, unsigned long *fpu_eip,
struct address *addr,
fpu_addr_modes); fpu_addr_modes);
/* load_store.c */ /* load_store.c */
extern void load_store_instr(char type, fpu_addr_modes addr_modes); extern int load_store_instr(unsigned char type, fpu_addr_modes addr_modes,
void *address);
/* poly_2xm1.c */ /* poly_2xm1.c */
extern int poly_2xm1(FPU_REG const *arg, FPU_REG *result); extern int poly_2xm1(FPU_REG const *arg, FPU_REG *result);
...@@ -96,7 +99,7 @@ extern int reg_sub(FPU_REG const *a, FPU_REG const *b, ...@@ -96,7 +99,7 @@ extern int reg_sub(FPU_REG const *a, FPU_REG const *b,
/* reg_compare.c */ /* reg_compare.c */
extern int compare(FPU_REG const *b); extern int compare(FPU_REG const *b);
extern int compare_st_data(void); extern int compare_st_data(FPU_REG const *b);
extern void fcom_st(void); extern void fcom_st(void);
extern void fcompst(void); extern void fcompst(void);
extern void fcompp(void); extern void fcompp(void);
...@@ -108,26 +111,26 @@ extern void fucompp(void); ...@@ -108,26 +111,26 @@ extern void fucompp(void);
extern void fconst(void); extern void fconst(void);
/* reg_ld_str.c */ /* reg_ld_str.c */
extern int reg_load_extended(void); extern int reg_load_extended(long double *addr, FPU_REG *loaded_data);
extern int reg_load_double(void); extern int reg_load_double(double *dfloat, FPU_REG *loaded_data);
extern int reg_load_single(void); extern int reg_load_single(float *single, FPU_REG *loaded_data);
extern void reg_load_int64(void); extern void reg_load_int64(long long *_s, FPU_REG *loaded_data);
extern void reg_load_int32(void); extern void reg_load_int32(long *_s, FPU_REG *loaded_data);
extern void reg_load_int16(void); extern void reg_load_int16(short *_s, FPU_REG *loaded_data);
extern void reg_load_bcd(void); extern void reg_load_bcd(char *s, FPU_REG *loaded_data);
extern int reg_store_extended(void); extern int reg_store_extended(long double *d, FPU_REG *st0_ptr);
extern int reg_store_double(void); extern int reg_store_double(double *dfloat, FPU_REG *st0_ptr);
extern int reg_store_single(void); extern int reg_store_single(float *single, FPU_REG *st0_ptr);
extern int reg_store_int64(void); extern int reg_store_int64(long long *d, FPU_REG *st0_ptr);
extern int reg_store_int32(void); extern int reg_store_int32(long *d, FPU_REG *st0_ptr);
extern int reg_store_int16(void); extern int reg_store_int16(short *d, FPU_REG *st0_ptr);
extern int reg_store_bcd(void); extern int reg_store_bcd(char *d, FPU_REG *st0_ptr);
extern int round_to_int(FPU_REG *r); extern int round_to_int(FPU_REG *r);
extern char *fldenv(fpu_addr_modes addr_modes); extern char *fldenv(fpu_addr_modes addr_modes, char *address);
extern void frstor(fpu_addr_modes addr_modes); extern void frstor(fpu_addr_modes addr_modes, char *address);
extern unsigned short tag_word(void); extern unsigned short tag_word(void);
extern char *fstenv(fpu_addr_modes addr_modes); extern char *fstenv(fpu_addr_modes addr_modes, char *address);
extern void fsave(fpu_addr_modes addr_modes); extern void fsave(fpu_addr_modes addr_modes, char *address);
/* reg_mul.c */ /* reg_mul.c */
extern int reg_mul(FPU_REG const *a, FPU_REG const *b, extern int reg_mul(FPU_REG const *a, FPU_REG const *b,
......
...@@ -19,6 +19,19 @@ ...@@ -19,6 +19,19 @@
of the stack frame of math_emulate() */ of the stack frame of math_emulate() */
#define SETUP_DATA_AREA(arg) FPU_info = (struct info *) &arg #define SETUP_DATA_AREA(arg) FPU_info = (struct info *) &arg
#define LDT_DESCRIPTOR(s) (current->ldt[(s) >> 3])
#define SEG_D_SIZE(x) ((x).b & (3 << 21))
#define SEG_G_BIT(x) ((x).b & (1 << 23))
#define SEG_GRANULARITY(x) (((x).b & (1 << 23)) ? 4096 : 1)
#define SEG_286_MODE(x) ((x).b & ( 0xff000000 | 0xf0000 | (1 << 23)))
#define SEG_BASE_ADDR(s) (((s).b & 0xff000000) \
| (((s).b & 0xff) << 16) | ((s).a >> 16))
#define SEG_LIMIT(s) (((s).b & 0xff0000) | ((s).a & 0xffff))
#define SEG_EXECUTE_ONLY(s) (((s).b & ((1 << 11) | (1 << 9))) == (1 << 11))
#define SEG_WRITE_PERM(s) (((s).b & ((1 << 11) | (1 << 9))) == (1 << 9))
#define SEG_EXPAND_DOWN(s) (((s).b & ((1 << 11) | (1 << 10))) \
== (1 << 10))
#define I387 (current->tss.i387) #define I387 (current->tss.i387)
#define FPU_info (I387.soft.info) #define FPU_info (I387.soft.info)
...@@ -30,22 +43,24 @@ ...@@ -30,22 +43,24 @@
#define FPU_EIP (FPU_info->___eip) #define FPU_EIP (FPU_info->___eip)
#define FPU_ORIG_EIP (FPU_info->___orig_eip) #define FPU_ORIG_EIP (FPU_info->___orig_eip)
#define LDT_BASE_ADDR(s) ((current->ldt[(s) >> 3].b & 0xff000000) \
| ((current->ldt[(s) >> 3].b & 0xff) << 16) \
| (current->ldt[(s) >> 3].a >> 16))
#define FPU_lookahead (I387.soft.lookahead) #define FPU_lookahead (I387.soft.lookahead)
#define FPU_entry_eip (I387.soft.entry_eip)
/* nz if ip_offset and cs_selector are not to be set for the current
instruction. */
#define no_ip_update (((char *)&(I387.soft.twd))[0])
#define FPU_rm (((unsigned char *)&(I387.soft.twd))[1])
/* Number of bytes of data which can be legally accessed by the current
instruction. This only needs to hold a number <= 108, so a byte will do. */
#define access_limit (((unsigned char *)&(I387.soft.twd))[2])
#define partial_status (I387.soft.swd) #define partial_status (I387.soft.swd)
#define control_word (I387.soft.cwd) #define control_word (I387.soft.cwd)
#define regs (I387.soft.regs) #define regs (I387.soft.regs)
#define top (I387.soft.top) #define top (I387.soft.top)
#define ip_offset (I387.soft.fip) #define instruction_address (*(struct address *)&I387.soft.fip)
#define cs_selector (I387.soft.fcs) #define operand_address (*(struct address *)&I387.soft.foo)
#define data_operand_offset (I387.soft.foo)
#define operand_selector (I387.soft.fos)
#define FPU_verify_area(x,y,z) if ( verify_area(x,y,z) ) \ #define FPU_verify_area(x,y,z) if ( verify_area(x,y,z) ) \
math_abort(FPU_info,SIGSEGV) math_abort(FPU_info,SIGSEGV)
...@@ -64,7 +79,4 @@ ...@@ -64,7 +79,4 @@
#define FPU_code_verify_area(z) FPU_verify_area(VERIFY_READ,(void *)FPU_EIP,z) #define FPU_code_verify_area(z) FPU_verify_area(VERIFY_READ,(void *)FPU_EIP,z)
#endif #endif
/* ######## temporary and ugly ;-) */
#define FPU_data_address ((void *)(I387.soft.twd))
#endif #endif
This diff is collapsed.
This diff is collapsed.
...@@ -27,12 +27,12 @@ ...@@ -27,12 +27,12 @@
#include "control_w.h" #include "control_w.h"
#define _NONE_ 0 /* FPU_st0_ptr etc not needed */ #define _NONE_ 0 /* st0_ptr etc not needed */
#define _REG0_ 1 /* Will be storing st(0) */ #define _REG0_ 1 /* Will be storing st(0) */
#define _PUSH_ 3 /* Need to check for space to push onto stack */ #define _PUSH_ 3 /* Need to check for space to push onto stack */
#define _null_ 4 /* Function illegal or not implemented */ #define _null_ 4 /* Function illegal or not implemented */
#define pop_0() { pop_ptr->tag = TW_Empty; top++; } #define pop_0() { st0_ptr->tag = TW_Empty; top++; }
static unsigned char const type_table[32] = { static unsigned char const type_table[32] = {
...@@ -46,130 +46,162 @@ static unsigned char const type_table[32] = { ...@@ -46,130 +46,162 @@ static unsigned char const type_table[32] = {
_NONE_, _REG0_, _NONE_, _REG0_ _NONE_, _REG0_, _NONE_, _REG0_
}; };
void load_store_instr(char type, fpu_addr_modes addr_modes) unsigned char const data_sizes_16[32] = {
4, 4, 8, 2, 0, 0, 0, 0,
4, 4, 8, 2, 4, 4, 8, 2,
14, 0, 94, 10, 2, 10, 0, 8,
14, 0, 94, 10, 2, 10, 2, 8
};
unsigned 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
};
int load_store_instr(unsigned char type, fpu_addr_modes addr_modes,
void *data_address)
{ {
FPU_REG *pop_ptr; /* We need a version of FPU_st0_ptr which won't FPU_REG loaded_data;
change if the emulator is re-entered. */ FPU_REG *st0_ptr;
st0_ptr = NULL; /* Initialized just to stop compiler warnings. */
pop_ptr = NULL; /* Initialized just to stop compiler warnings. */ if ( addr_modes.default_mode & PROTECTED )
switch ( type_table[(int) (unsigned) type] ) {
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);
#endif PARANOID
}
switch ( type_table[type] )
{ {
case _NONE_: case _NONE_:
break; break;
case _REG0_: case _REG0_:
pop_ptr = &st(0); /* Some of these instructions pop after st0_ptr = &st(0); /* Some of these instructions pop after
storing */ storing */
FPU_st0_ptr = pop_ptr; /* Set the global variables. */
FPU_st0_tag = FPU_st0_ptr->tag;
break; break;
case _PUSH_: case _PUSH_:
{ {
pop_ptr = &st(-1); st0_ptr = &st(-1);
if ( pop_ptr->tag != TW_Empty ) if ( st0_ptr->tag != TW_Empty )
{ stack_overflow(); return; } { stack_overflow(); return 0; }
top--; top--;
} }
break; break;
case _null_: case _null_:
FPU_illegal(); FPU_illegal();
return; return 0;
#ifdef PARANOID #ifdef PARANOID
default: default:
EXCEPTION(EX_INTERNAL); EXCEPTION(EX_INTERNAL|0x141);
return; return 0;
#endif PARANOID #endif PARANOID
} }
switch ( type ) switch ( type )
{ {
case 000: /* fld m32real */ case 000: /* fld m32real */
clear_C1(); clear_C1();
reg_load_single(); reg_load_single((float *)data_address, &loaded_data);
if ( (FPU_loaded_data.tag == TW_NaN) && if ( (loaded_data.tag == TW_NaN) &&
real_2op_NaN(&FPU_loaded_data, &FPU_loaded_data, &FPU_loaded_data) ) real_2op_NaN(&loaded_data, &loaded_data, &loaded_data) )
{ {
top++; top++;
break; break;
} }
reg_move(&FPU_loaded_data, pop_ptr); reg_move(&loaded_data, st0_ptr);
break; break;
case 001: /* fild m32int */ case 001: /* fild m32int */
clear_C1(); clear_C1();
reg_load_int32(); reg_load_int32((long *)data_address, st0_ptr);
reg_move(&FPU_loaded_data, pop_ptr);
break; break;
case 002: /* fld m64real */ case 002: /* fld m64real */
clear_C1(); clear_C1();
reg_load_double(); reg_load_double((double *)data_address, &loaded_data);
if ( (FPU_loaded_data.tag == TW_NaN) && if ( (loaded_data.tag == TW_NaN) &&
real_2op_NaN(&FPU_loaded_data, &FPU_loaded_data, &FPU_loaded_data) ) real_2op_NaN(&loaded_data, &loaded_data, &loaded_data) )
{ {
top++; top++;
break; break;
} }
reg_move(&FPU_loaded_data, pop_ptr); reg_move(&loaded_data, st0_ptr);
break; break;
case 003: /* fild m16int */ case 003: /* fild m16int */
clear_C1(); clear_C1();
reg_load_int16(); reg_load_int16((short *)data_address, st0_ptr);
reg_move(&FPU_loaded_data, pop_ptr);
break; break;
case 010: /* fst m32real */ case 010: /* fst m32real */
clear_C1(); clear_C1();
reg_store_single(); reg_store_single((float *)data_address, st0_ptr);
break; break;
case 011: /* fist m32int */ case 011: /* fist m32int */
clear_C1(); clear_C1();
reg_store_int32(); reg_store_int32((long *)data_address, st0_ptr);
break; break;
case 012: /* fst m64real */ case 012: /* fst m64real */
clear_C1(); clear_C1();
reg_store_double(); reg_store_double((double *)data_address, st0_ptr);
break; break;
case 013: /* fist m16int */ case 013: /* fist m16int */
clear_C1(); clear_C1();
reg_store_int16(); reg_store_int16((short *)data_address, st0_ptr);
break; break;
case 014: /* fstp m32real */ case 014: /* fstp m32real */
clear_C1(); clear_C1();
if ( reg_store_single() ) if ( reg_store_single((float *)data_address, st0_ptr) )
pop_0(); /* pop only if the number was actually stored pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */ (see the 80486 manual p16-28) */
break; break;
case 015: /* fistp m32int */ case 015: /* fistp m32int */
clear_C1(); clear_C1();
if ( reg_store_int32() ) if ( reg_store_int32((long *)data_address, st0_ptr) )
pop_0(); /* pop only if the number was actually stored pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */ (see the 80486 manual p16-28) */
break; break;
case 016: /* fstp m64real */ case 016: /* fstp m64real */
clear_C1(); clear_C1();
if ( reg_store_double() ) if ( reg_store_double((double *)data_address, st0_ptr) )
pop_0(); /* pop only if the number was actually stored pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */ (see the 80486 manual p16-28) */
break; break;
case 017: /* fistp m16int */ case 017: /* fistp m16int */
clear_C1(); clear_C1();
if ( reg_store_int16() ) if ( reg_store_int16((short *)data_address, st0_ptr) )
pop_0(); /* pop only if the number was actually stored pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */ (see the 80486 manual p16-28) */
break; break;
case 020: /* fldenv m14/28byte */ case 020: /* fldenv m14/28byte */
fldenv(addr_modes); fldenv(addr_modes, (char *)data_address);
break; /* Ensure that the values just loaded are not changed by
fix-up operations. */
return 1;
case 022: /* frstor m94/108byte */ case 022: /* frstor m94/108byte */
frstor(addr_modes); frstor(addr_modes, (char *)data_address);
break; /* Ensure that the values just loaded are not changed by
fix-up operations. */
return 1;
case 023: /* fbld m80dec */ case 023: /* fbld m80dec */
clear_C1(); clear_C1();
reg_load_bcd(); reg_load_bcd((char *)data_address, st0_ptr);
reg_move(&FPU_loaded_data, pop_ptr);
break; break;
case 024: /* fldcw */ case 024: /* fldcw */
RE_ENTRANT_CHECK_OFF; RE_ENTRANT_CHECK_OFF;
FPU_verify_area(VERIFY_READ, FPU_data_address, 2); FPU_verify_area(VERIFY_READ, data_address, 2);
control_word = get_fs_word((unsigned short *) FPU_data_address); control_word = get_fs_word((unsigned short *) data_address);
RE_ENTRANT_CHECK_ON; RE_ENTRANT_CHECK_ON;
if ( partial_status & ~control_word & CW_Exceptions ) if ( partial_status & ~control_word & CW_Exceptions )
partial_status |= (SW_Summary | SW_Backward); partial_status |= (SW_Summary | SW_Backward);
...@@ -178,60 +210,51 @@ switch ( type ) ...@@ -178,60 +210,51 @@ switch ( type )
#ifdef PECULIAR_486 #ifdef PECULIAR_486
control_word |= 0x40; /* An 80486 appears to always set this bit */ control_word |= 0x40; /* An 80486 appears to always set this bit */
#endif PECULIAR_486 #endif PECULIAR_486
NO_NET_DATA_EFFECT; return 1;
NO_NET_INSTR_EFFECT;
break;
case 025: /* fld m80real */ case 025: /* fld m80real */
clear_C1(); clear_C1();
reg_load_extended(); reg_load_extended((long double *)data_address, st0_ptr);
reg_move(&FPU_loaded_data, pop_ptr);
break; break;
case 027: /* fild m64int */ case 027: /* fild m64int */
clear_C1(); clear_C1();
reg_load_int64(); reg_load_int64((long long *)data_address, st0_ptr);
reg_move(&FPU_loaded_data, pop_ptr);
break; break;
case 030: /* fstenv m14/28byte */ case 030: /* fstenv m14/28byte */
fstenv(addr_modes); fstenv(addr_modes, (char *)data_address);
NO_NET_DATA_EFFECT; return 1;
break;
case 032: /* fsave */ case 032: /* fsave */
fsave(addr_modes); fsave(addr_modes, (char *)data_address);
NO_NET_DATA_EFFECT; return 1;
break;
case 033: /* fbstp m80dec */ case 033: /* fbstp m80dec */
clear_C1(); clear_C1();
if ( reg_store_bcd() ) if ( reg_store_bcd((char *)data_address, st0_ptr) )
pop_0(); /* pop only if the number was actually stored pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */ (see the 80486 manual p16-28) */
break; break;
case 034: /* fstcw m16int */ case 034: /* fstcw m16int */
RE_ENTRANT_CHECK_OFF; RE_ENTRANT_CHECK_OFF;
FPU_verify_area(VERIFY_WRITE,FPU_data_address,2); FPU_verify_area(VERIFY_WRITE,data_address,2);
put_fs_word(control_word, (short *) FPU_data_address); put_fs_word(control_word, (short *) data_address);
RE_ENTRANT_CHECK_ON; RE_ENTRANT_CHECK_ON;
NO_NET_DATA_EFFECT; return 1;
NO_NET_INSTR_EFFECT;
break;
case 035: /* fstp m80real */ case 035: /* fstp m80real */
clear_C1(); clear_C1();
if ( reg_store_extended() ) if ( reg_store_extended((long double *)data_address, st0_ptr) )
pop_0(); /* pop only if the number was actually stored pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */ (see the 80486 manual p16-28) */
break; break;
case 036: /* fstsw m2byte */ case 036: /* fstsw m2byte */
RE_ENTRANT_CHECK_OFF; RE_ENTRANT_CHECK_OFF;
FPU_verify_area(VERIFY_WRITE,FPU_data_address,2); FPU_verify_area(VERIFY_WRITE,data_address,2);
put_fs_word(status_word(),(short *) FPU_data_address); put_fs_word(status_word(),(short *) data_address);
RE_ENTRANT_CHECK_ON; RE_ENTRANT_CHECK_ON;
NO_NET_DATA_EFFECT; return 1;
NO_NET_INSTR_EFFECT;
break;
case 037: /* fistp m64int */ case 037: /* fistp m64int */
clear_C1(); clear_C1();
if ( reg_store_int64() ) if ( reg_store_int64((long long *)data_address, st0_ptr) )
pop_0(); /* pop only if the number was actually stored pop_0(); /* pop only if the number was actually stored
(see the 80486 manual p16-28) */ (see the 80486 manual p16-28) */
break; break;
} }
return 0;
} }
...@@ -187,16 +187,8 @@ void poly_add_1(FPU_REG *src) ...@@ -187,16 +187,8 @@ void poly_add_1(FPU_REG *src)
for the use of this function in poly_atan. Simple truncation for the use of this function in poly_atan. Simple truncation
is used here instead of round-to-nearest. */ is used here instead of round-to-nearest. */
#ifdef OBSOLETE
char round = (src->sigl & 3) == 3;
#endif OBSOLETE
shrx(&src->sigl, 1); shrx(&src->sigl, 1);
#ifdef OBSOLETE
if ( round ) significand(src)++; /* Round to even */
#endif OBSOLETE
src->sigh |= 0x80000000; src->sigh |= 0x80000000;
src->exp = EXP_BIAS; src->exp = EXP_BIAS;
......
...@@ -24,10 +24,15 @@ ...@@ -24,10 +24,15 @@
int compare(FPU_REG const *b) int compare(FPU_REG const *b)
{ {
int diff; int diff;
char st0_tag;
FPU_REG *st0_ptr;
if ( FPU_st0_ptr->tag | b->tag ) st0_ptr = &st(0);
st0_tag = st0_ptr->tag;
if ( st0_tag | b->tag )
{ {
if ( FPU_st0_ptr->tag == TW_Zero ) if ( st0_tag == TW_Zero )
{ {
if ( b->tag == TW_Zero ) return COMP_A_eq_B; if ( b->tag == TW_Zero ) return COMP_A_eq_B;
if ( b->tag == TW_Valid ) if ( b->tag == TW_Valid )
...@@ -42,23 +47,23 @@ int compare(FPU_REG const *b) ...@@ -42,23 +47,23 @@ int compare(FPU_REG const *b)
} }
else if ( b->tag == TW_Zero ) else if ( b->tag == TW_Zero )
{ {
if ( FPU_st0_ptr->tag == TW_Valid ) if ( st0_tag == TW_Valid )
{ {
return ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B return ((st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B
: COMP_A_lt_B) : COMP_A_lt_B)
#ifdef DENORM_OPERAND #ifdef DENORM_OPERAND
| ((FPU_st0_ptr->exp <= EXP_UNDER ) | ((st0_ptr->exp <= EXP_UNDER )
? COMP_Denormal : 0 ) ? COMP_Denormal : 0 )
#endif DENORM_OPERAND #endif DENORM_OPERAND
; ;
} }
} }
if ( FPU_st0_ptr->tag == TW_Infinity ) if ( st0_tag == TW_Infinity )
{ {
if ( (b->tag == TW_Valid) || (b->tag == TW_Zero) ) if ( (b->tag == TW_Valid) || (b->tag == TW_Zero) )
{ {
return ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B return ((st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B
: COMP_A_lt_B) : COMP_A_lt_B)
#ifdef DENORM_OPERAND #ifdef DENORM_OPERAND
| (((b->tag == TW_Valid) && (b->exp <= EXP_UNDER)) ? | (((b->tag == TW_Valid) && (b->exp <= EXP_UNDER)) ?
...@@ -69,19 +74,19 @@ int compare(FPU_REG const *b) ...@@ -69,19 +74,19 @@ int compare(FPU_REG const *b)
else if ( b->tag == TW_Infinity ) else if ( b->tag == TW_Infinity )
{ {
/* The 80486 book says that infinities can be equal! */ /* The 80486 book says that infinities can be equal! */
return (FPU_st0_ptr->sign == b->sign) ? COMP_A_eq_B : return (st0_ptr->sign == b->sign) ? COMP_A_eq_B :
((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B); ((st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
} }
/* Fall through to the NaN code */ /* Fall through to the NaN code */
} }
else if ( b->tag == TW_Infinity ) else if ( b->tag == TW_Infinity )
{ {
if ( (FPU_st0_ptr->tag == TW_Valid) || (FPU_st0_ptr->tag == TW_Zero) ) if ( (st0_tag == TW_Valid) || (st0_tag == TW_Zero) )
{ {
return ((b->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B) return ((b->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
#ifdef DENORM_OPERAND #ifdef DENORM_OPERAND
| (((FPU_st0_ptr->tag == TW_Valid) | (((st0_tag == TW_Valid)
&& (FPU_st0_ptr->exp <= EXP_UNDER)) ? && (st0_ptr->exp <= EXP_UNDER)) ?
COMP_Denormal : 0) COMP_Denormal : 0)
#endif DENORM_OPERAND #endif DENORM_OPERAND
; ;
...@@ -91,9 +96,9 @@ int compare(FPU_REG const *b) ...@@ -91,9 +96,9 @@ int compare(FPU_REG const *b)
/* The only possibility now should be that one of the arguments /* The only possibility now should be that one of the arguments
is a NaN */ is a NaN */
if ( (FPU_st0_ptr->tag == TW_NaN) || (b->tag == TW_NaN) ) if ( (st0_tag == TW_NaN) || (b->tag == TW_NaN) )
{ {
if ( ((FPU_st0_ptr->tag == TW_NaN) && !(FPU_st0_ptr->sigh & 0x40000000)) if ( ((st0_tag == TW_NaN) && !(st0_ptr->sigh & 0x40000000))
|| ((b->tag == TW_NaN) && !(b->sigh & 0x40000000)) ) || ((b->tag == TW_NaN) && !(b->sigh & 0x40000000)) )
/* At least one arg is a signaling NaN */ /* At least one arg is a signaling NaN */
return COMP_No_Comp | COMP_SNaN | COMP_NaN; return COMP_No_Comp | COMP_SNaN | COMP_NaN;
...@@ -106,51 +111,51 @@ int compare(FPU_REG const *b) ...@@ -106,51 +111,51 @@ int compare(FPU_REG const *b)
} }
#ifdef PARANOID #ifdef PARANOID
if (!(FPU_st0_ptr->sigh & 0x80000000)) EXCEPTION(EX_Invalid); if (!(st0_ptr->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
if (!(b->sigh & 0x80000000)) EXCEPTION(EX_Invalid); if (!(b->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
#endif PARANOID #endif PARANOID
if (FPU_st0_ptr->sign != b->sign) if (st0_ptr->sign != b->sign)
{ {
return ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B) return ((st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
#ifdef DENORM_OPERAND #ifdef DENORM_OPERAND
| |
( ((FPU_st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ? ( ((st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
COMP_Denormal : 0) COMP_Denormal : 0)
#endif DENORM_OPERAND #endif DENORM_OPERAND
; ;
} }
diff = FPU_st0_ptr->exp - b->exp; diff = st0_ptr->exp - b->exp;
if ( diff == 0 ) if ( diff == 0 )
{ {
diff = FPU_st0_ptr->sigh - b->sigh; /* Works only if ms bits are diff = st0_ptr->sigh - b->sigh; /* Works only if ms bits are
identical */ identical */
if ( diff == 0 ) if ( diff == 0 )
{ {
diff = FPU_st0_ptr->sigl > b->sigl; diff = st0_ptr->sigl > b->sigl;
if ( diff == 0 ) if ( diff == 0 )
diff = -(FPU_st0_ptr->sigl < b->sigl); diff = -(st0_ptr->sigl < b->sigl);
} }
} }
if ( diff > 0 ) if ( diff > 0 )
{ {
return ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B) return ((st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B)
#ifdef DENORM_OPERAND #ifdef DENORM_OPERAND
| |
( ((FPU_st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ? ( ((st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
COMP_Denormal : 0) COMP_Denormal : 0)
#endif DENORM_OPERAND #endif DENORM_OPERAND
; ;
} }
if ( diff < 0 ) if ( diff < 0 )
{ {
return ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B) return ((st0_ptr->sign == SIGN_POS) ? COMP_A_lt_B : COMP_A_gt_B)
#ifdef DENORM_OPERAND #ifdef DENORM_OPERAND
| |
( ((FPU_st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ? ( ((st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
COMP_Denormal : 0) COMP_Denormal : 0)
#endif DENORM_OPERAND #endif DENORM_OPERAND
; ;
...@@ -159,7 +164,7 @@ int compare(FPU_REG const *b) ...@@ -159,7 +164,7 @@ int compare(FPU_REG const *b)
return COMP_A_eq_B return COMP_A_eq_B
#ifdef DENORM_OPERAND #ifdef DENORM_OPERAND
| |
( ((FPU_st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ? ( ((st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
COMP_Denormal : 0) COMP_Denormal : 0)
#endif DENORM_OPERAND #endif DENORM_OPERAND
; ;
...@@ -168,11 +173,11 @@ int compare(FPU_REG const *b) ...@@ -168,11 +173,11 @@ int compare(FPU_REG const *b)
/* This function requires that st(0) is not empty */ /* This function requires that st(0) is not empty */
int compare_st_data(void) int compare_st_data(FPU_REG const *loaded_data)
{ {
int f, c; int f, c;
c = compare(&FPU_loaded_data); c = compare(loaded_data);
if (c & COMP_NaN) if (c & COMP_NaN)
{ {
...@@ -214,7 +219,7 @@ static int compare_st_st(int nr) ...@@ -214,7 +219,7 @@ static int compare_st_st(int nr)
{ {
int f, c; int f, c;
if ( !NOT_EMPTY_0 || !NOT_EMPTY(nr) ) if ( !NOT_EMPTY(0) || !NOT_EMPTY(nr) )
{ {
setcc(SW_C3 | SW_C2 | SW_C0); setcc(SW_C3 | SW_C2 | SW_C0);
/* Stack fault */ /* Stack fault */
...@@ -264,7 +269,7 @@ static int compare_u_st_st(int nr) ...@@ -264,7 +269,7 @@ static int compare_u_st_st(int nr)
{ {
int f, c; int f, c;
if ( !NOT_EMPTY_0 || !NOT_EMPTY(nr) ) if ( !NOT_EMPTY(0) || !NOT_EMPTY(nr) )
{ {
setcc(SW_C3 | SW_C2 | SW_C0); setcc(SW_C3 | SW_C2 | SW_C0);
/* Stack fault */ /* Stack fault */
...@@ -340,10 +345,7 @@ void fcompp() ...@@ -340,10 +345,7 @@ void fcompp()
return; return;
} }
if ( !compare_st_st(1) ) if ( !compare_st_st(1) )
{ poppop();
pop(); FPU_st0_ptr = &st(0);
pop();
}
} }
...@@ -369,10 +371,7 @@ void fucompp() ...@@ -369,10 +371,7 @@ void fucompp()
if (FPU_rm == 1) if (FPU_rm == 1)
{ {
if ( !compare_u_st_st(1) ) if ( !compare_u_st_st(1) )
{ poppop();
pop(); FPU_st0_ptr = &st(0);
pop();
}
} }
else else
FPU_illegal(); FPU_illegal();
......
...@@ -66,7 +66,7 @@ static void fld_const(FPU_REG const *c) ...@@ -66,7 +66,7 @@ static void fld_const(FPU_REG const *c)
return; return;
} }
push(); push();
reg_move(c, FPU_st0_ptr); reg_move(c, st_new_ptr);
clear_C1(); clear_C1();
} }
......
...@@ -25,9 +25,9 @@ ...@@ -25,9 +25,9 @@
_reg_div: _reg_div:
pushl %ebp pushl %ebp
movl %esp,%ebp movl %esp,%ebp
#ifdef REENTRANT_FPU #ifndef NON_REENTRANT_FPU
subl $28,%esp /* Needed by divide_kernel */ subl $28,%esp /* Needed by divide_kernel */
#endif REENTRANT_FPU #endif NON_REENTRANT_FPU
pushl %esi pushl %esi
pushl %edi pushl %edi
...@@ -214,11 +214,11 @@ LDiv_negative_result: ...@@ -214,11 +214,11 @@ LDiv_negative_result:
xorl %eax,%eax /* Valid result */ xorl %eax,%eax /* Valid result */
LDiv_exit: LDiv_exit:
#ifdef REENTRANT_FPU #ifndef NON_REENTRANT_FPU
leal -40(%ebp),%esp leal -40(%ebp),%esp
#else #else
leal -12(%ebp),%esp leal -12(%ebp),%esp
#endif REENTRANT_FPU #endif NON_REENTRANT_FPU
popl %ebx popl %ebx
popl %edi popl %edi
......
This diff is collapsed.
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
#define UNMASKED_UNDERFLOW $2 #define UNMASKED_UNDERFLOW $2
#ifdef REENTRANT_FPU #ifndef NON_REENTRANT_FPU
/* Make the code re-entrant by putting /* Make the code re-entrant by putting
local storage on the stack: */ local storage on the stack: */
#define FPU_bits_lost (%esp) #define FPU_bits_lost (%esp)
...@@ -97,7 +97,7 @@ FPU_bits_lost: ...@@ -97,7 +97,7 @@ FPU_bits_lost:
.byte 0 .byte 0
FPU_denormal: FPU_denormal:
.byte 0 .byte 0
#endif REENTRANT_FPU #endif NON_REENTRANT_FPU
.text .text
...@@ -127,9 +127,9 @@ fpu_reg_round: /* Normal entry point */ ...@@ -127,9 +127,9 @@ fpu_reg_round: /* Normal entry point */
fpu_reg_round_sqrt: /* Entry point from wm_sqrt.S */ fpu_reg_round_sqrt: /* Entry point from wm_sqrt.S */
#ifdef REENTRANT_FPU #ifndef NON_REENTRANT_FPU
pushl %ebx /* adjust the stack pointer */ pushl %ebx /* adjust the stack pointer */
#endif REENTRANT_FPU #endif NON_REENTRANT_FPU
#ifdef PARANOID #ifdef PARANOID
/* Cannot use this here yet */ /* Cannot use this here yet */
...@@ -417,9 +417,9 @@ xL_Store_significand: ...@@ -417,9 +417,9 @@ xL_Store_significand:
jge L_overflow jge L_overflow
fpu_reg_round_exit: fpu_reg_round_exit:
#ifdef REENTRANT_FPU #ifndef NON_REENTRANT_FPU
popl %ebx /* adjust the stack pointer */ popl %ebx /* adjust the stack pointer */
#endif REENTRANT_FPU #endif NON_REENTRANT_FPU
fpu_Arith_exit: fpu_Arith_exit:
popl %ebx popl %ebx
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
/* #define dSIGH(x) 4(x) */ /* #define dSIGH(x) 4(x) */
#ifdef REENTRANT_FPU #ifndef NON_REENTRANT_FPU
/* /*
Local storage on the stack: Local storage on the stack:
Result: FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0 Result: FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0
...@@ -65,7 +65,7 @@ FPU_result_2: ...@@ -65,7 +65,7 @@ FPU_result_2:
.long 0 .long 0
FPU_ovfl_flag: FPU_ovfl_flag:
.byte 0 .byte 0
#endif REENTRANT_FPU #endif NON_REENTRANT_FPU
.text .text
...@@ -78,9 +78,9 @@ FPU_ovfl_flag: ...@@ -78,9 +78,9 @@ FPU_ovfl_flag:
_reg_u_div: _reg_u_div:
pushl %ebp pushl %ebp
movl %esp,%ebp movl %esp,%ebp
#ifdef REENTRANT_FPU #ifndef NON_REENTRANT_FPU
subl $28,%esp subl $28,%esp
#endif REENTRANT_FPU #endif NON_REENTRANT_FPU
pushl %esi pushl %esi
pushl %edi pushl %edi
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#ifdef REENTRANT_FPU #ifndef NON_REENTRANT_FPU
/* Local storage on the stack: */ /* Local storage on the stack: */
#define FPU_accum_0 -4(%ebp) /* ms word */ #define FPU_accum_0 -4(%ebp) /* ms word */
#define FPU_accum_1 -8(%ebp) #define FPU_accum_1 -8(%ebp)
...@@ -40,7 +40,7 @@ FPU_accum_0: ...@@ -40,7 +40,7 @@ FPU_accum_0:
.long 0 .long 0
FPU_accum_1: FPU_accum_1:
.long 0 .long 0
#endif REENTRANT_FPU #endif NON_REENTRANT_FPU
.text .text
...@@ -50,9 +50,9 @@ FPU_accum_1: ...@@ -50,9 +50,9 @@ FPU_accum_1:
_reg_u_mul: _reg_u_mul:
pushl %ebp pushl %ebp
movl %esp,%ebp movl %esp,%ebp
#ifdef REENTRANT_FPU #ifndef NON_REENTRANT_FPU
subl $8,%esp subl $8,%esp
#endif REENTRANT_FPU #endif NON_REENTRANT_FPU
pushl %esi pushl %esi
pushl %edi pushl %edi
......
...@@ -9,5 +9,4 @@ ...@@ -9,5 +9,4 @@
| | | |
+---------------------------------------------------------------------------*/ +---------------------------------------------------------------------------*/
#define FPU_VERSION "wm-FPU-emu version Beta 1.11" #define FPU_VERSION "wm-FPU-emu version 1.12"
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include "fpu_asm.h" #include "fpu_asm.h"
#ifdef REENTRANT_FPU #ifndef NON_REENTRANT_FPU
/* Local storage on the stack: */ /* Local storage on the stack: */
#define FPU_accum_3 -4(%ebp) /* ms word */ #define FPU_accum_3 -4(%ebp) /* ms word */
#define FPU_accum_2 -8(%ebp) #define FPU_accum_2 -8(%ebp)
...@@ -70,7 +70,7 @@ FPU_fsqrt_arg_1: ...@@ -70,7 +70,7 @@ FPU_fsqrt_arg_1:
.long 0 .long 0
FPU_fsqrt_arg_0: FPU_fsqrt_arg_0:
.long 0 /* ls word, at most the ms bit is set */ .long 0 /* ls word, at most the ms bit is set */
#endif REENTRANT_FPU #endif NON_REENTRANT_FPU
.text .text
...@@ -80,9 +80,9 @@ FPU_fsqrt_arg_0: ...@@ -80,9 +80,9 @@ FPU_fsqrt_arg_0:
_wm_sqrt: _wm_sqrt:
pushl %ebp pushl %ebp
movl %esp,%ebp movl %esp,%ebp
#ifdef REENTRANT_FPU #ifndef NON_REENTRANT_FPU
subl $28,%esp subl $28,%esp
#endif REENTRANT_FPU #endif NON_REENTRANT_FPU
pushl %esi pushl %esi
pushl %edi pushl %edi
pushl %ebx pushl %ebx
......
This diff is collapsed.
...@@ -82,6 +82,9 @@ extern int * blksize_size[MAX_BLKDEV]; ...@@ -82,6 +82,9 @@ extern int * blksize_size[MAX_BLKDEV];
extern unsigned long hd_init(unsigned long mem_start, unsigned long mem_end); extern unsigned long hd_init(unsigned long mem_start, unsigned long mem_end);
extern unsigned long cdu31a_init(unsigned long mem_start, unsigned long mem_end); extern unsigned long cdu31a_init(unsigned long mem_start, unsigned long mem_end);
extern unsigned long mcd_init(unsigned long mem_start, unsigned long mem_end); extern unsigned long mcd_init(unsigned long mem_start, unsigned long mem_end);
#ifdef CONFIG_SBPCD
extern unsigned long sbpcd_init(unsigned long, unsigned long);
#endif CONFIG_SBPCD
extern int is_read_only(int dev); extern int is_read_only(int dev);
extern void set_device_ro(int dev,int flag); extern void set_device_ro(int dev,int flag);
......
...@@ -19,10 +19,6 @@ ...@@ -19,10 +19,6 @@
#include "blk.h" #include "blk.h"
#ifdef CONFIG_SBPCD
extern u_long sbpcd_init(u_long, u_long);
#endif CONFIG_SBPCD
/* /*
* The request-struct contains all necessary data * The request-struct contains all necessary data
* to load a nr of sectors into memory * to load a nr of sectors into memory
......
This diff is collapsed.
...@@ -281,6 +281,14 @@ static struct device ppp0_dev = { ...@@ -281,6 +281,14 @@ static struct device ppp0_dev = {
#define NEXT_DEV (&ppp0_dev) #define NEXT_DEV (&ppp0_dev)
#endif /* PPP */ #endif /* PPP */
#ifdef CONFIG_DUMMY
extern int dummy_init(struct device *dev);
static struct device dummy_dev = {
"dummy", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, dummy_init, };
# undef NEXT_DEV
# define NEXT_DEV (&dummy_dev)
#endif
#ifdef LOOPBACK #ifdef LOOPBACK
extern int loopback_init(struct device *dev); extern int loopback_init(struct device *dev);
static struct device loopback_dev = { static struct device loopback_dev = {
......
This diff is collapsed.
This diff is collapsed.
...@@ -44,6 +44,9 @@ extern int check_cdu31a_media_change(int, int); ...@@ -44,6 +44,9 @@ extern int check_cdu31a_media_change(int, int);
#ifdef CONFIG_MCD #ifdef CONFIG_MCD
extern int check_mcd_media_change(int, int); extern int check_mcd_media_change(int, int);
#endif #endif
#ifdef CONFIG_SBPCD
extern int check_sbpcd_media_change(int, int);
#endif
#define NR_SIZES 4 #define NR_SIZES 4
static char buffersize_index[9] = {-1, 0, 1, -1, 2, -1, -1, -1, 3}; static char buffersize_index[9] = {-1, 0, 1, -1, 2, -1, -1, -1, 3};
...@@ -334,6 +337,12 @@ void check_disk_change(dev_t dev) ...@@ -334,6 +337,12 @@ void check_disk_change(dev_t dev)
break; break;
#endif #endif
#if defined(CONFIG_SBPCD)
case MATSUSHITA_CDROM_MAJOR:
i = check_sbpcd_media_change(dev, 0);
break;
#endif
default: default:
return; return;
}; };
......
This diff is collapsed.
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
OBJS = sched.o sys_call.o traps.o irq.o dma.o fork.o \ OBJS = sched.o sys_call.o traps.o irq.o dma.o fork.o \
panic.o printk.o vsprintf.o sys.o module.o ksyms.o exit.o \ panic.o printk.o vsprintf.o sys.o module.o ksyms.o exit.o \
signal.o mktime.o ptrace.o ioport.o itimer.o \ signal.o ptrace.o ioport.o itimer.o \
info.o ldt.o time.o tqueue.o vm86.o info.o ldt.o time.o tqueue.o vm86.o
all: kernel.o all: kernel.o
......
...@@ -517,6 +517,8 @@ static void second_overflow(void) ...@@ -517,6 +517,8 @@ static void second_overflow(void)
if (xtime.tv_sec > last_rtc_update + 660) if (xtime.tv_sec > last_rtc_update + 660)
if (set_rtc_mmss(xtime.tv_sec) == 0) if (set_rtc_mmss(xtime.tv_sec) == 0)
last_rtc_update = xtime.tv_sec; last_rtc_update = xtime.tv_sec;
else
last_rtc_update = xtime.tv_sec - 600; /* do it again in one min */
} }
/* /*
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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