fpu_emu.h 7.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/*---------------------------------------------------------------------------+
 |  fpu_emu.h                                                                |
 |                                                                           |
 | Copyright (C) 1992,1993,1994,1997                                         |
 |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
 |                       Australia.  E-mail   billm@suburbia.net             |
 |                                                                           |
 +---------------------------------------------------------------------------*/

#ifndef _FPU_EMU_H_
#define _FPU_EMU_H_

/*
 * Define PECULIAR_486 to get a closer approximation to 80486 behaviour,
 * rather than behaviour which appears to be cleaner.
 * This is a matter of opinion: for all I know, the 80486 may simply
 * be complying with the IEEE spec. Maybe one day I'll get to see the
 * spec...
 */
#define PECULIAR_486

#ifdef __ASSEMBLY__
#include "fpu_asm.h"
#define	Const(x)	$##x
#else
#define	Const(x)	x
#endif

#define EXP_BIAS	Const(0)
I
Ingo Molnar 已提交
30 31 32 33
#define EXP_OVER	Const(0x4000)	/* smallest invalid large exponent */
#define	EXP_UNDER	Const(-0x3fff)	/* largest invalid small exponent */
#define EXP_WAY_UNDER   Const(-0x6000)	/* Below the smallest denormal, but
					   still a 16 bit nr. */
L
Linus Torvalds 已提交
34 35 36 37
#define EXP_Infinity    EXP_OVER
#define EXP_NaN         EXP_OVER

#define EXTENDED_Ebias Const(0x3fff)
I
Ingo Molnar 已提交
38
#define EXTENDED_Emin (-0x3ffe)	/* smallest valid exponent */
L
Linus Torvalds 已提交
39 40 41 42 43 44 45 46 47

#define SIGN_POS	Const(0)
#define SIGN_NEG	Const(0x80)

#define SIGN_Positive	Const(0)
#define SIGN_Negative	Const(0x8000)

/* Keep the order TAG_Valid, TAG_Zero, TW_Denormal */
/* The following fold to 2 (Special) in the Tag Word */
I
Ingo Molnar 已提交
48
#define TW_Denormal     Const(4)	/* De-normal */
L
Linus Torvalds 已提交
49 50 51 52 53 54 55 56 57
#define TW_Infinity	Const(5)	/* + or - infinity */
#define	TW_NaN		Const(6)	/* Not a Number */
#define	TW_Unsupported	Const(7)	/* Not supported by an 80486 */

#define TAG_Valid	Const(0)	/* valid */
#define TAG_Zero	Const(1)	/* zero */
#define TAG_Special	Const(2)	/* De-normal, + or - infinity,
					   or Not a Number */
#define TAG_Empty	Const(3)	/* empty */
R
Randy Dunlap 已提交
58
#define TAG_Error	Const(0x80)	/* probably need to abort */
L
Linus Torvalds 已提交
59 60 61 62 63 64 65 66 67

#define LOADED_DATA	Const(10101)	/* Special st() number to identify
					   loaded data (not on stack). */

/* A few flags (must be >= 0x10). */
#define REV             0x10
#define DEST_RM         0x20
#define LOADED          0x40

I
Ingo Molnar 已提交
68
#define FPU_Exception   Const(0x80000000)	/* Added to tag returns. */
L
Linus Torvalds 已提交
69 70 71 72 73

#ifndef __ASSEMBLY__

#include "fpu_system.h"

I
Ingo Molnar 已提交
74
#include <asm/sigcontext.h>	/* for struct _fpstate */
L
Linus Torvalds 已提交
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
#include <asm/math_emu.h>
#include <linux/linkage.h>

/*
#define RE_ENTRANT_CHECKING
 */

#ifdef RE_ENTRANT_CHECKING
extern u_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 /* RE_ENTRANT_CHECKING */

#define FWAIT_OPCODE 0x9b
#define OP_SIZE_PREFIX 0x66
#define ADDR_SIZE_PREFIX 0x67
#define PREFIX_CS 0x2e
#define PREFIX_DS 0x3e
#define PREFIX_ES 0x26
#define PREFIX_SS 0x36
#define PREFIX_FS 0x64
#define PREFIX_GS 0x65
#define PREFIX_REPE 0xf3
#define PREFIX_REPNE 0xf2
#define PREFIX_LOCK 0xf0
#define PREFIX_CS_ 1
#define PREFIX_DS_ 2
#define PREFIX_ES_ 3
#define PREFIX_FS_ 4
#define PREFIX_GS_ 5
#define PREFIX_SS_ 6
#define PREFIX_DEFAULT 7

struct address {
I
Ingo Molnar 已提交
112 113 114 115
	unsigned int offset;
	unsigned int selector:16;
	unsigned int opcode:11;
	unsigned int empty:5;
L
Linus Torvalds 已提交
116 117
};
struct fpu__reg {
I
Ingo Molnar 已提交
118 119 120
	unsigned sigl;
	unsigned sigh;
	short exp;
L
Linus Torvalds 已提交
121 122
};

I
Ingo Molnar 已提交
123
typedef void (*FUNC) (void);
L
Linus Torvalds 已提交
124
typedef struct fpu__reg FPU_REG;
125
typedef void (*FUNC_ST0) (FPU_REG *st0_ptr, u_char st0_tag);
I
Ingo Molnar 已提交
126 127 128
typedef struct {
	u_char address_size, operand_size, segment;
} overrides;
L
Linus Torvalds 已提交
129
/* This structure is 32 bits: */
I
Ingo Molnar 已提交
130 131 132 133
typedef struct {
	overrides override;
	u_char default_mode;
} fpu_addr_modes;
L
Linus Torvalds 已提交
134 135 136 137
/* 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
I
Ingo Molnar 已提交
138
#define SIXTEEN   1		/* We rely upon this being 1 (true) */
L
Linus Torvalds 已提交
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
#define VM86      SIXTEEN
#define PM16      (SIXTEEN | PROTECTED)
#define SEG32     PROTECTED
extern u_char const data_sizes_16[32];

#define register_base ((u_char *) registers )
#define fpu_register(x)  ( * ((FPU_REG *)( register_base + 10 * (x & 7) )) )
#define	st(x)      ( * ((FPU_REG *)( register_base + 10 * ((top+x) & 7) )) )

#define	STACK_OVERFLOW	(FPU_stackoverflow(&st_new_ptr))
#define	NOT_EMPTY(i)	(!FPU_empty_i(i))

#define	NOT_EMPTY_ST0	(st0_tag ^ TAG_Empty)

#define poppop() { FPU_pop(); FPU_pop(); }

/* push() does not affect the tags */
#define push()	{ top--; }

#define signbyte(a) (((u_char *)(a))[9])
#define getsign(a) (signbyte(a) & 0x80)
#define setsign(a,b) { if (b) signbyte(a) |= 0x80; else signbyte(a) &= 0x7f; }
#define copysign(a,b) { if (getsign(a)) signbyte(b) |= 0x80; \
                        else signbyte(b) &= 0x7f; }
#define changesign(a) { signbyte(a) ^= 0x80; }
#define setpositive(a) { signbyte(a) &= 0x7f; }
#define setnegative(a) { signbyte(a) |= 0x80; }
#define signpositive(a) ( (signbyte(a) & 0x80) == 0 )
#define signnegative(a) (signbyte(a) & 0x80)

169
static inline void reg_copy(FPU_REG const *x, FPU_REG *y)
L
Linus Torvalds 已提交
170
{
I
Ingo Molnar 已提交
171 172
	*(short *)&(y->exp) = *(const short *)&(x->exp);
	*(long long *)&(y->sigl) = *(const long long *)&(x->sigl);
L
Linus Torvalds 已提交
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
}

#define exponent(x)  (((*(short *)&((x)->exp)) & 0x7fff) - EXTENDED_Ebias)
#define setexponentpos(x,y) { (*(short *)&((x)->exp)) = \
  ((y) + EXTENDED_Ebias) & 0x7fff; }
#define exponent16(x)         (*(short *)&((x)->exp))
#define setexponent16(x,y)  { (*(short *)&((x)->exp)) = (y); }
#define addexponent(x,y)    { (*(short *)&((x)->exp)) += (y); }
#define stdexp(x)           { (*(short *)&((x)->exp)) += EXTENDED_Ebias; }

#define isdenormal(ptr)   (exponent(ptr) == EXP_BIAS+EXP_UNDER)

#define significand(x) ( ((unsigned long long *)&((x)->sigl))[0] )

/*----- Prototypes for functions written in assembler -----*/
/* extern void reg_move(FPU_REG *a, FPU_REG *b); */

190 191
asmlinkage int FPU_normalize(FPU_REG *x);
asmlinkage int FPU_normalize_nuo(FPU_REG *x);
L
Linus Torvalds 已提交
192
asmlinkage int FPU_u_sub(FPU_REG const *arg1, FPU_REG const *arg2,
I
Ingo Molnar 已提交
193
			 FPU_REG * answ, unsigned int control_w, u_char sign,
L
Linus Torvalds 已提交
194 195
			 int expa, int expb);
asmlinkage int FPU_u_mul(FPU_REG const *arg1, FPU_REG const *arg2,
I
Ingo Molnar 已提交
196
			 FPU_REG * answ, unsigned int control_w, u_char sign,
L
Linus Torvalds 已提交
197 198
			 int expon);
asmlinkage int FPU_u_div(FPU_REG const *arg1, FPU_REG const *arg2,
I
Ingo Molnar 已提交
199
			 FPU_REG * answ, unsigned int control_w, u_char sign);
L
Linus Torvalds 已提交
200
asmlinkage int FPU_u_add(FPU_REG const *arg1, FPU_REG const *arg2,
I
Ingo Molnar 已提交
201
			 FPU_REG * answ, unsigned int control_w, u_char sign,
L
Linus Torvalds 已提交
202
			 int expa, int expb);
203
asmlinkage int wm_sqrt(FPU_REG *n, int dummy1, int dummy2,
L
Linus Torvalds 已提交
204
		       unsigned int control_w, u_char sign);
I
Ingo Molnar 已提交
205 206
asmlinkage unsigned FPU_shrx(void *l, unsigned x);
asmlinkage unsigned FPU_shrxs(void *v, unsigned x);
L
Linus Torvalds 已提交
207
asmlinkage unsigned long FPU_div_small(unsigned long long *x, unsigned long y);
208
asmlinkage int FPU_round(FPU_REG *arg, unsigned int extent, int dummy,
L
Linus Torvalds 已提交
209 210 211 212 213 214 215 216 217
			 unsigned int control_w, u_char sign);

#ifndef MAKING_PROTO
#include "fpu_proto.h"
#endif

#endif /* __ASSEMBLY__ */

#endif /* _FPU_EMU_H_ */