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

Import 1.1.18

parent 9ec7e58c
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 17
SUBLEVEL = 18
all: Version zImage
......
......@@ -5,14 +5,13 @@
#DEBUG = -DDEBUGGING
DEBUG =
PARANOID = -DPARANOID
REENTRANT = -DREENTRANT_FPU
CFLAGS := $(CFLAGS) $(PARANOID) $(DEBUG) -fno-builtin
.c.o:
$(CC) $(CFLAGS) $(MATH_EMULATION) -c $<
.S.o:
$(CC) -D__ASSEMBLER__ $(PARANOID) $(REENTRANT) -c $<
$(CC) -D__ASSEMBLER__ $(PARANOID) -c $<
.s.o:
$(CC) -c $<
......
......@@ -47,7 +47,7 @@ Please report bugs, etc to me at:
--Bill Metzenthen
March 1994
June 1994
----------------------- Internals of wm-FPU-emu -----------------------
......@@ -80,20 +80,24 @@ emulate each FPU instruction to completion without interruption.
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
temporarily suspended while disk i/o takes place. During this time
another process may use the emulator, thereby changing some static
variables (eg FPU_st0_ptr, etc). The code which accesses user memory
is confined to five files:
another process may use the emulator, thereby perhaps changing static
variables. The code which accesses user memory is confined to five
files:
fpu_entry.c
reg_ld_str.c
load_store.c
get_address.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 -----------------------
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
more important differences are listed below:
(version 1.12) and the 80486 FPU (apart from bugs). Some of the more
important differences are listed below:
The Roundup flag does not have much meaning for the transcendental
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
protection fault message when run under the MS-DOS prompt of Windows
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 -----------------------
......@@ -322,6 +331,7 @@ Hamish Coleman, t933093@minyos.xx.rmit.oz.au
Bruce Evans, bde@kralizec.zeta.org.au
Timo Korvola, Timo.Korvola@hut.fi
Rick Lyons, rick@razorback.brisnet.org.au
Rick, jrs@world.std.com
...and numerous others who responded to my request for help with
a real 80486.
......
......@@ -42,6 +42,8 @@ void Un_impl(void)
RE_ENTRANT_CHECK_OFF;
/* No need to verify_area(), we have previously fetched these bytes. */
printk("Unimplemented FPU Opcode at eip=%p : ", (void *) address);
if ( FPU_CS == USER_CS )
{
while ( 1 )
{
byte1 = get_fs_byte((unsigned char *) address);
......@@ -56,6 +58,12 @@ void Un_impl(void)
printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
else
printk("/%d\n", (FPU_modrm >> 3) & 7);
}
else
{
printk("cs selector = %04x\n", FPU_CS);
}
RE_ENTRANT_CHECK_ON;
EXCEPTION(EX_Invalid);
......@@ -85,6 +93,8 @@ void emu_printall()
RE_ENTRANT_CHECK_OFF;
/* No need to verify_area(), we have previously fetched these bytes. */
printk("At %p:", (void *) address);
if ( FPU_CS == USER_CS )
{
#define MAX_PRINTED_BYTES 20
for ( i = 0; i < MAX_PRINTED_BYTES; i++ )
{
......@@ -109,6 +119,11 @@ void emu_printall()
printk(" /%d, mod=%d rm=%d\n",
(FPU_modrm >> 3) & 7, (FPU_modrm >> 6) & 3, FPU_modrm & 7);
}
}
else
{
printk("%04x\n", FPU_CS);
}
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",
printk("%s\n", tag_desc[(int) (unsigned) r->tag]);
}
#ifdef OBSOLETE
printk("[data] %c .%04lx %04lx %04lx %04lx e%+-6ld ",
FPU_loaded_data.sign ? '-' : '+',
(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",
(long)(FPU_loaded_data.sigl & 0xFFFF),
FPU_loaded_data.exp - EXP_BIAS + 1);
printk("%s\n", tag_desc[(int) (unsigned) FPU_loaded_data.tag]);
#endif OBSOLETE
RE_ENTRANT_CHECK_ON;
}
......@@ -214,7 +231,6 @@ static struct {
error was detected.
Internal error types:
0 in load_store.c
0x14 in fpu_etc.c
0x1nn in a *.c file:
0x101 in reg_add_sub.c
......@@ -244,7 +260,13 @@ static struct {
0x126 in fpu_entry.c
0x127 in poly_2xm1.c
0x128 in fpu_entry.c
0x129 in fpu_entry.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:
0x201 in reg_u_add.S
0x202 in reg_u_div.S
......@@ -583,7 +605,7 @@ void stack_overflow(void)
{
/* The masked response */
top--;
reg_move(&CONST_QNaN, FPU_st0_ptr = &st(0));
reg_move(&CONST_QNaN, &st(0));
}
EXCEPTION(EX_StackOver);
......@@ -599,7 +621,7 @@ void stack_underflow(void)
if ( control_word & CW_Invalid )
{
/* The masked response */
reg_move(&CONST_QNaN, FPU_st0_ptr);
reg_move(&CONST_QNaN, &st(0));
}
EXCEPTION(EX_StackUnder);
......
......@@ -20,7 +20,7 @@ void fadd__()
{
/* fadd st,st(i) */
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__()
{
/* fmul st,st(i) */
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__()
{
/* fsub st,st(i) */
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_()
{
/* fsubr st,st(i) */
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__()
{
/* fdiv st,st(i) */
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_()
{
/* fdivr st,st(i) */
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()
{
/* fadd st(i),st */
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()
{
/* fmul st(i),st */
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()
{
/* fsubr st(i),st */
/* 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();
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()
{
/* fsub st(i),st */
/* 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();
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()
{
/* fdivr st(i),st */
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()
{
/* fdiv st(i),st */
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_()
{
/* faddp st(i),st */
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();
}
......@@ -132,7 +132,7 @@ void fmulp_()
{
/* fmulp st(i),st */
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();
}
......@@ -142,9 +142,9 @@ void fsubrp()
{
/* fsubrp st(i),st */
/* 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();
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();
}
......@@ -153,9 +153,9 @@ void fsubp_()
{
/* fsubp st(i),st */
/* 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();
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();
}
......@@ -164,7 +164,7 @@ void fdivrp()
{
/* fdivrp st(i),st */
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();
}
......@@ -173,7 +173,7 @@ void fdivp_()
{
/* fdivp st(i),st */
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();
}
......@@ -26,8 +26,7 @@ void fclex(void)
partial_status &= ~(SW_Backward|SW_Summary|SW_Stack_Fault|SW_Precision|
SW_Underflow|SW_Overflow|SW_Zero_Div|SW_Denorm_Op|
SW_Invalid);
NO_NET_DATA_EFFECT;
FPU_entry_eip = ip_offset; /* We want no net effect */
no_ip_update = 1;
}
/* Needs to be externally visible */
......@@ -43,11 +42,12 @@ void finit()
}
/* The behaviour is different to that detailed in
Section 15.1.6 of the Intel manual */
data_operand_offset = 0;
operand_selector = 0;
NO_NET_DATA_EFFECT;
FPU_entry_op_cs = 0;
FPU_entry_eip = ip_offset = 0;
operand_address.offset = 0;
operand_address.selector = 0;
instruction_address.offset = 0;
instruction_address.selector = 0;
instruction_address.opcode = 0;
no_ip_update = 1;
}
/*
......@@ -71,7 +71,7 @@ void finit_()
static void fstsw_ax(void)
{
*(short *) &FPU_EAX = status_word();
NO_NET_INSTR_EFFECT;
no_ip_update = 1;
}
static FUNC const fstsw_table[] = {
......@@ -108,10 +108,9 @@ void fld_i_()
{ reg_move(&st(FPU_rm), st_new_ptr); push(); }
else
{
if ( control_word & EX_Invalid )
if ( control_word & CW_Invalid )
{
/* The masked response */
push();
stack_underflow();
}
else
......@@ -125,9 +124,9 @@ void fxch_i()
{
/* fxch st(i) */
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 )
{
......@@ -136,20 +135,20 @@ void fxch_i()
return;
}
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);
return;
}
if ( sti_ptr->tag == TW_Empty )
{
if ( control_word & CW_Invalid )
reg_move(FPU_st0_ptr, sti_ptr); /* Masked response */
reg_move(st0_ptr, sti_ptr); /* Masked response */
stack_underflow();
return;
}
clear_C1();
reg_move(FPU_st0_ptr, &t);
reg_move(sti_ptr, FPU_st0_ptr);
reg_move(st0_ptr, &t);
reg_move(sti_ptr, st0_ptr);
reg_move(&t, sti_ptr);
}
......@@ -172,14 +171,14 @@ void ffreep()
void fst_i_()
{
/* fst st(i) */
reg_move(FPU_st0_ptr, &st(FPU_rm));
reg_move(&st(0), &st(FPU_rm));
}
void fstp_i()
{
/* fstp st(i) */
reg_move(FPU_st0_ptr, &st(FPU_rm));
reg_move(&st(0), &st(FPU_rm));
pop();
}
......@@ -60,14 +60,18 @@
#include <linux/math_emu.h>
#include <linux/linkage.h>
#ifdef PARANOID
/*
#define RE_ENTRANT_CHECKING
*/
#ifdef RE_ENTRANT_CHECKING
extern char emulating;
# define RE_ENTRANT_CHECK_OFF emulating = 0
# define RE_ENTRANT_CHECK_ON emulating = 1
#else
# define RE_ENTRANT_CHECK_OFF
# define RE_ENTRANT_CHECK_ON
#endif PARANOID
#endif RE_ENTRANT_CHECKING
#define FWAIT_OPCODE 0x9b
#define OP_SIZE_PREFIX 0x66
......@@ -89,46 +93,43 @@ extern char emulating;
#define PREFIX_SS_ 6
#define PREFIX_DEFAULT 7
/* These are to defeat the default action, giving the instruction
no net effect: */
#define NO_NET_DATA_EFFECT \
{ FPU_data_address = (void *)data_operand_offset; \
FPU_data_selector = operand_selector; }
#define NO_NET_INSTR_EFFECT \
{ FPU_entry_eip = ip_offset; \
FPU_entry_op_cs = cs_selector; }
struct address {
unsigned int offset;
unsigned int selector:16;
unsigned int opcode:11;
unsigned int empty:5;
};
typedef void (*FUNC)(void);
typedef struct fpu_reg FPU_REG;
typedef void (*FUNC_ST0)(FPU_REG *st0_ptr);
typedef struct { unsigned char address_size, operand_size, segment; }
overrides;
/* This structure is 48 bits: */
/* This structure is 32 bits: */
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 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_0 (FPU_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 NOT_EMPTY_ST0 (st0_tag ^ TW_Empty)
#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 */
#define push() { top--; FPU_st0_ptr = st_new_ptr; }
#define push() { top--; }
#define reg_move(x, y) { \
......
This diff is collapsed.
......@@ -17,22 +17,22 @@
#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();
}
else
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();
}
else
......@@ -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:
setcc(SW_C3);
break;
case TW_Valid:
if (FPU_st0_ptr->sign == SIGN_POS)
if (st0_ptr->sign == SIGN_POS)
setcc(0);
else
setcc(SW_C0);
#ifdef DENORM_OPERAND
if ( (FPU_st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
if ( (st0_ptr->exp <= EXP_UNDER) && (denormal_operand()) )
{
#ifdef PECULIAR_486
/* This is wierd! */
if (FPU_st0_ptr->sign == SIGN_POS)
if (st0_ptr->sign == SIGN_POS)
setcc(SW_C3);
#endif PECULIAR_486
return;
......@@ -71,7 +71,7 @@ static void ftst_(void)
EXCEPTION(EX_Invalid);
break;
case TW_Infinity:
if (FPU_st0_ptr->sign == SIGN_POS)
if (st0_ptr->sign == SIGN_POS)
setcc(0);
else
setcc(SW_C0);
......@@ -87,10 +87,10 @@ static void ftst_(void)
}
}
static void fxam(void)
static void fxam(FPU_REG *st0_ptr)
{
int c=0;
switch (FPU_st0_tag)
switch (st0_ptr->tag)
{
case TW_Empty:
c = SW_C3|SW_C0;
......@@ -100,7 +100,7 @@ static void fxam(void)
break;
case TW_Valid:
/* 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 */
else
c = SW_C2;
......@@ -112,16 +112,18 @@ static void fxam(void)
c = SW_C2|SW_C0;
break;
}
if (FPU_st0_ptr->sign == SIGN_NEG)
if (st0_ptr->sign == SIGN_NEG)
c |= SW_C1;
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()
{
(fp_etc_table[FPU_rm])();
(fp_etc_table[FPU_rm])(&st(0));
}
......@@ -63,13 +63,16 @@ extern void trig_a(void);
extern void trig_b(void);
/* 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);
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);
/* 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 */
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,
/* reg_compare.c */
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 fcompst(void);
extern void fcompp(void);
......@@ -108,26 +111,26 @@ extern void fucompp(void);
extern void fconst(void);
/* reg_ld_str.c */
extern int reg_load_extended(void);
extern int reg_load_double(void);
extern int reg_load_single(void);
extern void reg_load_int64(void);
extern void reg_load_int32(void);
extern void reg_load_int16(void);
extern void reg_load_bcd(void);
extern int reg_store_extended(void);
extern int reg_store_double(void);
extern int reg_store_single(void);
extern int reg_store_int64(void);
extern int reg_store_int32(void);
extern int reg_store_int16(void);
extern int reg_store_bcd(void);
extern int reg_load_extended(long double *addr, FPU_REG *loaded_data);
extern int reg_load_double(double *dfloat, FPU_REG *loaded_data);
extern int reg_load_single(float *single, FPU_REG *loaded_data);
extern void reg_load_int64(long long *_s, FPU_REG *loaded_data);
extern void reg_load_int32(long *_s, FPU_REG *loaded_data);
extern void reg_load_int16(short *_s, FPU_REG *loaded_data);
extern void reg_load_bcd(char *s, FPU_REG *loaded_data);
extern int reg_store_extended(long double *d, FPU_REG *st0_ptr);
extern int reg_store_double(double *dfloat, FPU_REG *st0_ptr);
extern int reg_store_single(float *single, FPU_REG *st0_ptr);
extern int reg_store_int64(long long *d, FPU_REG *st0_ptr);
extern int reg_store_int32(long *d, FPU_REG *st0_ptr);
extern int reg_store_int16(short *d, FPU_REG *st0_ptr);
extern int reg_store_bcd(char *d, FPU_REG *st0_ptr);
extern int round_to_int(FPU_REG *r);
extern char *fldenv(fpu_addr_modes addr_modes);
extern void frstor(fpu_addr_modes addr_modes);
extern char *fldenv(fpu_addr_modes addr_modes, char *address);
extern void frstor(fpu_addr_modes addr_modes, char *address);
extern unsigned short tag_word(void);
extern char *fstenv(fpu_addr_modes addr_modes);
extern void fsave(fpu_addr_modes addr_modes);
extern char *fstenv(fpu_addr_modes addr_modes, char *address);
extern void fsave(fpu_addr_modes addr_modes, char *address);
/* reg_mul.c */
extern int reg_mul(FPU_REG const *a, FPU_REG const *b,
......
......@@ -19,6 +19,19 @@
of the stack frame of math_emulate() */
#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 FPU_info (I387.soft.info)
......@@ -30,22 +43,24 @@
#define FPU_EIP (FPU_info->___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_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 control_word (I387.soft.cwd)
#define regs (I387.soft.regs)
#define top (I387.soft.top)
#define ip_offset (I387.soft.fip)
#define cs_selector (I387.soft.fcs)
#define data_operand_offset (I387.soft.foo)
#define operand_selector (I387.soft.fos)
#define instruction_address (*(struct address *)&I387.soft.fip)
#define operand_address (*(struct address *)&I387.soft.foo)
#define FPU_verify_area(x,y,z) if ( verify_area(x,y,z) ) \
math_abort(FPU_info,SIGSEGV)
......@@ -64,7 +79,4 @@
#define FPU_code_verify_area(z) FPU_verify_area(VERIFY_READ,(void *)FPU_EIP,z)
#endif
/* ######## temporary and ugly ;-) */
#define FPU_data_address ((void *)(I387.soft.twd))
#endif
This diff is collapsed.
This diff is collapsed.
......@@ -27,12 +27,12 @@
#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 _PUSH_ 3 /* Need to check for space to push onto stack */
#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] = {
......@@ -46,130 +46,162 @@ static unsigned char const type_table[32] = {
_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
change if the emulator is re-entered. */
FPU_REG loaded_data;
FPU_REG *st0_ptr;
st0_ptr = NULL; /* Initialized just to stop compiler warnings. */
pop_ptr = NULL; /* Initialized just to stop compiler warnings. */
switch ( type_table[(int) (unsigned) type] )
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);
#endif PARANOID
}
switch ( type_table[type] )
{
case _NONE_:
break;
case _REG0_:
pop_ptr = &st(0); /* Some of these instructions pop after
st0_ptr = &st(0); /* Some of these instructions pop after
storing */
FPU_st0_ptr = pop_ptr; /* Set the global variables. */
FPU_st0_tag = FPU_st0_ptr->tag;
break;
case _PUSH_:
{
pop_ptr = &st(-1);
if ( pop_ptr->tag != TW_Empty )
{ stack_overflow(); return; }
st0_ptr = &st(-1);
if ( st0_ptr->tag != TW_Empty )
{ stack_overflow(); return 0; }
top--;
}
break;
case _null_:
FPU_illegal();
return;
return 0;
#ifdef PARANOID
default:
EXCEPTION(EX_INTERNAL);
return;
EXCEPTION(EX_INTERNAL|0x141);
return 0;
#endif PARANOID
}
switch ( type )
switch ( type )
{
case 000: /* fld m32real */
clear_C1();
reg_load_single();
if ( (FPU_loaded_data.tag == TW_NaN) &&
real_2op_NaN(&FPU_loaded_data, &FPU_loaded_data, &FPU_loaded_data) )
reg_load_single((float *)data_address, &loaded_data);
if ( (loaded_data.tag == TW_NaN) &&
real_2op_NaN(&loaded_data, &loaded_data, &loaded_data) )
{
top++;
break;
}
reg_move(&FPU_loaded_data, pop_ptr);
reg_move(&loaded_data, st0_ptr);
break;
case 001: /* fild m32int */
clear_C1();
reg_load_int32();
reg_move(&FPU_loaded_data, pop_ptr);
reg_load_int32((long *)data_address, st0_ptr);
break;
case 002: /* fld m64real */
clear_C1();
reg_load_double();
if ( (FPU_loaded_data.tag == TW_NaN) &&
real_2op_NaN(&FPU_loaded_data, &FPU_loaded_data, &FPU_loaded_data) )
reg_load_double((double *)data_address, &loaded_data);
if ( (loaded_data.tag == TW_NaN) &&
real_2op_NaN(&loaded_data, &loaded_data, &loaded_data) )
{
top++;
break;
}
reg_move(&FPU_loaded_data, pop_ptr);
reg_move(&loaded_data, st0_ptr);
break;
case 003: /* fild m16int */
clear_C1();
reg_load_int16();
reg_move(&FPU_loaded_data, pop_ptr);
reg_load_int16((short *)data_address, st0_ptr);
break;
case 010: /* fst m32real */
clear_C1();
reg_store_single();
reg_store_single((float *)data_address, st0_ptr);
break;
case 011: /* fist m32int */
clear_C1();
reg_store_int32();
reg_store_int32((long *)data_address, st0_ptr);
break;
case 012: /* fst m64real */
clear_C1();
reg_store_double();
reg_store_double((double *)data_address, st0_ptr);
break;
case 013: /* fist m16int */
clear_C1();
reg_store_int16();
reg_store_int16((short *)data_address, st0_ptr);
break;
case 014: /* fstp m32real */
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
(see the 80486 manual p16-28) */
break;
case 015: /* fistp m32int */
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
(see the 80486 manual p16-28) */
break;
case 016: /* fstp m64real */
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
(see the 80486 manual p16-28) */
break;
case 017: /* fistp m16int */
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
(see the 80486 manual p16-28) */
break;
case 020: /* fldenv m14/28byte */
fldenv(addr_modes);
break;
fldenv(addr_modes, (char *)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);
break;
frstor(addr_modes, (char *)data_address);
/* Ensure that the values just loaded are not changed by
fix-up operations. */
return 1;
case 023: /* fbld m80dec */
clear_C1();
reg_load_bcd();
reg_move(&FPU_loaded_data, pop_ptr);
reg_load_bcd((char *)data_address, st0_ptr);
break;
case 024: /* fldcw */
RE_ENTRANT_CHECK_OFF;
FPU_verify_area(VERIFY_READ, FPU_data_address, 2);
control_word = get_fs_word((unsigned short *) FPU_data_address);
FPU_verify_area(VERIFY_READ, data_address, 2);
control_word = get_fs_word((unsigned short *) data_address);
RE_ENTRANT_CHECK_ON;
if ( partial_status & ~control_word & CW_Exceptions )
partial_status |= (SW_Summary | SW_Backward);
......@@ -178,60 +210,51 @@ switch ( type )
#ifdef PECULIAR_486
control_word |= 0x40; /* An 80486 appears to always set this bit */
#endif PECULIAR_486
NO_NET_DATA_EFFECT;
NO_NET_INSTR_EFFECT;
break;
return 1;
case 025: /* fld m80real */
clear_C1();
reg_load_extended();
reg_move(&FPU_loaded_data, pop_ptr);
reg_load_extended((long double *)data_address, st0_ptr);
break;
case 027: /* fild m64int */
clear_C1();
reg_load_int64();
reg_move(&FPU_loaded_data, pop_ptr);
reg_load_int64((long long *)data_address, st0_ptr);
break;
case 030: /* fstenv m14/28byte */
fstenv(addr_modes);
NO_NET_DATA_EFFECT;
break;
fstenv(addr_modes, (char *)data_address);
return 1;
case 032: /* fsave */
fsave(addr_modes);
NO_NET_DATA_EFFECT;
break;
fsave(addr_modes, (char *)data_address);
return 1;
case 033: /* fbstp m80dec */
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
(see the 80486 manual p16-28) */
break;
case 034: /* fstcw m16int */
RE_ENTRANT_CHECK_OFF;
FPU_verify_area(VERIFY_WRITE,FPU_data_address,2);
put_fs_word(control_word, (short *) FPU_data_address);
FPU_verify_area(VERIFY_WRITE,data_address,2);
put_fs_word(control_word, (short *) data_address);
RE_ENTRANT_CHECK_ON;
NO_NET_DATA_EFFECT;
NO_NET_INSTR_EFFECT;
break;
return 1;
case 035: /* fstp m80real */
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
(see the 80486 manual p16-28) */
break;
case 036: /* fstsw m2byte */
RE_ENTRANT_CHECK_OFF;
FPU_verify_area(VERIFY_WRITE,FPU_data_address,2);
put_fs_word(status_word(),(short *) FPU_data_address);
FPU_verify_area(VERIFY_WRITE,data_address,2);
put_fs_word(status_word(),(short *) data_address);
RE_ENTRANT_CHECK_ON;
NO_NET_DATA_EFFECT;
NO_NET_INSTR_EFFECT;
break;
return 1;
case 037: /* fistp m64int */
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
(see the 80486 manual p16-28) */
break;
}
return 0;
}
......@@ -187,16 +187,8 @@ void poly_add_1(FPU_REG *src)
for the use of this function in poly_atan. Simple truncation
is used here instead of round-to-nearest. */
#ifdef OBSOLETE
char round = (src->sigl & 3) == 3;
#endif OBSOLETE
shrx(&src->sigl, 1);
#ifdef OBSOLETE
if ( round ) significand(src)++; /* Round to even */
#endif OBSOLETE
src->sigh |= 0x80000000;
src->exp = EXP_BIAS;
......
......@@ -24,10 +24,15 @@
int compare(FPU_REG const *b)
{
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_Valid )
......@@ -42,23 +47,23 @@ int compare(FPU_REG const *b)
}
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)
#ifdef DENORM_OPERAND
| ((FPU_st0_ptr->exp <= EXP_UNDER )
| ((st0_ptr->exp <= EXP_UNDER )
? COMP_Denormal : 0 )
#endif DENORM_OPERAND
;
}
}
if ( FPU_st0_ptr->tag == TW_Infinity )
if ( st0_tag == TW_Infinity )
{
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)
#ifdef DENORM_OPERAND
| (((b->tag == TW_Valid) && (b->exp <= EXP_UNDER)) ?
......@@ -69,19 +74,19 @@ int compare(FPU_REG const *b)
else if ( b->tag == TW_Infinity )
{
/* The 80486 book says that infinities can be equal! */
return (FPU_st0_ptr->sign == b->sign) ? COMP_A_eq_B :
((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
return (st0_ptr->sign == b->sign) ? COMP_A_eq_B :
((st0_ptr->sign == SIGN_POS) ? COMP_A_gt_B : COMP_A_lt_B);
}
/* Fall through to the NaN code */
}
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)
#ifdef DENORM_OPERAND
| (((FPU_st0_ptr->tag == TW_Valid)
&& (FPU_st0_ptr->exp <= EXP_UNDER)) ?
| (((st0_tag == TW_Valid)
&& (st0_ptr->exp <= EXP_UNDER)) ?
COMP_Denormal : 0)
#endif DENORM_OPERAND
;
......@@ -91,9 +96,9 @@ int compare(FPU_REG const *b)
/* The only possibility now should be that one of the arguments
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)) )
/* At least one arg is a signaling NaN */
return COMP_No_Comp | COMP_SNaN | COMP_NaN;
......@@ -106,51 +111,51 @@ int compare(FPU_REG const *b)
}
#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);
#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
|
( ((FPU_st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
( ((st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
COMP_Denormal : 0)
#endif DENORM_OPERAND
;
}
diff = FPU_st0_ptr->exp - b->exp;
diff = st0_ptr->exp - b->exp;
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 */
if ( diff == 0 )
{
diff = FPU_st0_ptr->sigl > b->sigl;
diff = st0_ptr->sigl > b->sigl;
if ( diff == 0 )
diff = -(FPU_st0_ptr->sigl < b->sigl);
diff = -(st0_ptr->sigl < b->sigl);
}
}
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
|
( ((FPU_st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
( ((st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
COMP_Denormal : 0)
#endif DENORM_OPERAND
;
}
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
|
( ((FPU_st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
( ((st0_ptr->exp <= EXP_UNDER) || (b->exp <= EXP_UNDER)) ?
COMP_Denormal : 0)
#endif DENORM_OPERAND
;
......@@ -159,7 +164,7 @@ int compare(FPU_REG const *b)
return COMP_A_eq_B
#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)
#endif DENORM_OPERAND
;
......@@ -168,11 +173,11 @@ int compare(FPU_REG const *b)
/* 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;
c = compare(&FPU_loaded_data);
c = compare(loaded_data);
if (c & COMP_NaN)
{
......@@ -214,7 +219,7 @@ static int compare_st_st(int nr)
{
int f, c;
if ( !NOT_EMPTY_0 || !NOT_EMPTY(nr) )
if ( !NOT_EMPTY(0) || !NOT_EMPTY(nr) )
{
setcc(SW_C3 | SW_C2 | SW_C0);
/* Stack fault */
......@@ -264,7 +269,7 @@ static int compare_u_st_st(int nr)
{
int f, c;
if ( !NOT_EMPTY_0 || !NOT_EMPTY(nr) )
if ( !NOT_EMPTY(0) || !NOT_EMPTY(nr) )
{
setcc(SW_C3 | SW_C2 | SW_C0);
/* Stack fault */
......@@ -340,10 +345,7 @@ void fcompp()
return;
}
if ( !compare_st_st(1) )
{
pop(); FPU_st0_ptr = &st(0);
pop();
}
poppop();
}
......@@ -369,10 +371,7 @@ void fucompp()
if (FPU_rm == 1)
{
if ( !compare_u_st_st(1) )
{
pop(); FPU_st0_ptr = &st(0);
pop();
}
poppop();
}
else
FPU_illegal();
......
......@@ -66,7 +66,7 @@ static void fld_const(FPU_REG const *c)
return;
}
push();
reg_move(c, FPU_st0_ptr);
reg_move(c, st_new_ptr);
clear_C1();
}
......
......@@ -25,9 +25,9 @@
_reg_div:
pushl %ebp
movl %esp,%ebp
#ifdef REENTRANT_FPU
#ifndef NON_REENTRANT_FPU
subl $28,%esp /* Needed by divide_kernel */
#endif REENTRANT_FPU
#endif NON_REENTRANT_FPU
pushl %esi
pushl %edi
......@@ -214,11 +214,11 @@ LDiv_negative_result:
xorl %eax,%eax /* Valid result */
LDiv_exit:
#ifdef REENTRANT_FPU
#ifndef NON_REENTRANT_FPU
leal -40(%ebp),%esp
#else
leal -12(%ebp),%esp
#endif REENTRANT_FPU
#endif NON_REENTRANT_FPU
popl %ebx
popl %edi
......
This diff is collapsed.
......@@ -82,7 +82,7 @@
#define UNMASKED_UNDERFLOW $2
#ifdef REENTRANT_FPU
#ifndef NON_REENTRANT_FPU
/* Make the code re-entrant by putting
local storage on the stack: */
#define FPU_bits_lost (%esp)
......@@ -97,7 +97,7 @@ FPU_bits_lost:
.byte 0
FPU_denormal:
.byte 0
#endif REENTRANT_FPU
#endif NON_REENTRANT_FPU
.text
......@@ -127,9 +127,9 @@ fpu_reg_round: /* Normal entry point */
fpu_reg_round_sqrt: /* Entry point from wm_sqrt.S */
#ifdef REENTRANT_FPU
#ifndef NON_REENTRANT_FPU
pushl %ebx /* adjust the stack pointer */
#endif REENTRANT_FPU
#endif NON_REENTRANT_FPU
#ifdef PARANOID
/* Cannot use this here yet */
......@@ -417,9 +417,9 @@ xL_Store_significand:
jge L_overflow
fpu_reg_round_exit:
#ifdef REENTRANT_FPU
#ifndef NON_REENTRANT_FPU
popl %ebx /* adjust the stack pointer */
#endif REENTRANT_FPU
#endif NON_REENTRANT_FPU
fpu_Arith_exit:
popl %ebx
......
......@@ -29,7 +29,7 @@
/* #define dSIGH(x) 4(x) */
#ifdef REENTRANT_FPU
#ifndef NON_REENTRANT_FPU
/*
Local storage on the stack:
Result: FPU_accum_3:FPU_accum_2:FPU_accum_1:FPU_accum_0
......@@ -65,7 +65,7 @@ FPU_result_2:
.long 0
FPU_ovfl_flag:
.byte 0
#endif REENTRANT_FPU
#endif NON_REENTRANT_FPU
.text
......@@ -78,9 +78,9 @@ FPU_ovfl_flag:
_reg_u_div:
pushl %ebp
movl %esp,%ebp
#ifdef REENTRANT_FPU
#ifndef NON_REENTRANT_FPU
subl $28,%esp
#endif REENTRANT_FPU
#endif NON_REENTRANT_FPU
pushl %esi
pushl %edi
......
......@@ -27,7 +27,7 @@
#ifdef REENTRANT_FPU
#ifndef NON_REENTRANT_FPU
/* Local storage on the stack: */
#define FPU_accum_0 -4(%ebp) /* ms word */
#define FPU_accum_1 -8(%ebp)
......@@ -40,7 +40,7 @@ FPU_accum_0:
.long 0
FPU_accum_1:
.long 0
#endif REENTRANT_FPU
#endif NON_REENTRANT_FPU
.text
......@@ -50,9 +50,9 @@ FPU_accum_1:
_reg_u_mul:
pushl %ebp
movl %esp,%ebp
#ifdef REENTRANT_FPU
#ifndef NON_REENTRANT_FPU
subl $8,%esp
#endif REENTRANT_FPU
#endif NON_REENTRANT_FPU
pushl %esi
pushl %edi
......
......@@ -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 @@
#include "fpu_asm.h"
#ifdef REENTRANT_FPU
#ifndef NON_REENTRANT_FPU
/* Local storage on the stack: */
#define FPU_accum_3 -4(%ebp) /* ms word */
#define FPU_accum_2 -8(%ebp)
......@@ -70,7 +70,7 @@ FPU_fsqrt_arg_1:
.long 0
FPU_fsqrt_arg_0:
.long 0 /* ls word, at most the ms bit is set */
#endif REENTRANT_FPU
#endif NON_REENTRANT_FPU
.text
......@@ -80,9 +80,9 @@ FPU_fsqrt_arg_0:
_wm_sqrt:
pushl %ebp
movl %esp,%ebp
#ifdef REENTRANT_FPU
#ifndef NON_REENTRANT_FPU
subl $28,%esp
#endif REENTRANT_FPU
#endif NON_REENTRANT_FPU
pushl %esi
pushl %edi
pushl %ebx
......
This diff is collapsed.
......@@ -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 cdu31a_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 void set_device_ro(int dev,int flag);
......
......@@ -19,10 +19,6 @@
#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
* to load a nr of sectors into memory
......
This diff is collapsed.
......@@ -281,6 +281,14 @@ static struct device ppp0_dev = {
#define NEXT_DEV (&ppp0_dev)
#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
extern int loopback_init(struct device *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);
#ifdef CONFIG_MCD
extern int check_mcd_media_change(int, int);
#endif
#ifdef CONFIG_SBPCD
extern int check_sbpcd_media_change(int, int);
#endif
#define NR_SIZES 4
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)
break;
#endif
#if defined(CONFIG_SBPCD)
case MATSUSHITA_CDROM_MAJOR:
i = check_sbpcd_media_change(dev, 0);
break;
#endif
default:
return;
};
......
This diff is collapsed.
......@@ -18,7 +18,7 @@
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 \
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
all: kernel.o
......
......@@ -517,6 +517,8 @@ static void second_overflow(void)
if (xtime.tv_sec > last_rtc_update + 660)
if (set_rtc_mmss(xtime.tv_sec) == 0)
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