diff options
Diffstat (limited to 'arch/x86/math-emu/fpu_emu.h')
-rw-r--r-- | arch/x86/math-emu/fpu_emu.h | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/arch/x86/math-emu/fpu_emu.h b/arch/x86/math-emu/fpu_emu.h new file mode 100644 index 000000000000..65120f523853 --- /dev/null +++ b/arch/x86/math-emu/fpu_emu.h | |||
@@ -0,0 +1,218 @@ | |||
1 | /*---------------------------------------------------------------------------+ | ||
2 | | fpu_emu.h | | ||
3 | | | | ||
4 | | Copyright (C) 1992,1993,1994,1997 | | ||
5 | | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, | | ||
6 | | Australia. E-mail billm@suburbia.net | | ||
7 | | | | ||
8 | +---------------------------------------------------------------------------*/ | ||
9 | |||
10 | |||
11 | #ifndef _FPU_EMU_H_ | ||
12 | #define _FPU_EMU_H_ | ||
13 | |||
14 | /* | ||
15 | * Define PECULIAR_486 to get a closer approximation to 80486 behaviour, | ||
16 | * rather than behaviour which appears to be cleaner. | ||
17 | * This is a matter of opinion: for all I know, the 80486 may simply | ||
18 | * be complying with the IEEE spec. Maybe one day I'll get to see the | ||
19 | * spec... | ||
20 | */ | ||
21 | #define PECULIAR_486 | ||
22 | |||
23 | #ifdef __ASSEMBLY__ | ||
24 | #include "fpu_asm.h" | ||
25 | #define Const(x) $##x | ||
26 | #else | ||
27 | #define Const(x) x | ||
28 | #endif | ||
29 | |||
30 | #define EXP_BIAS Const(0) | ||
31 | #define EXP_OVER Const(0x4000) /* smallest invalid large exponent */ | ||
32 | #define EXP_UNDER Const(-0x3fff) /* largest invalid small exponent */ | ||
33 | #define EXP_WAY_UNDER Const(-0x6000) /* Below the smallest denormal, but | ||
34 | still a 16 bit nr. */ | ||
35 | #define EXP_Infinity EXP_OVER | ||
36 | #define EXP_NaN EXP_OVER | ||
37 | |||
38 | #define EXTENDED_Ebias Const(0x3fff) | ||
39 | #define EXTENDED_Emin (-0x3ffe) /* smallest valid exponent */ | ||
40 | |||
41 | #define SIGN_POS Const(0) | ||
42 | #define SIGN_NEG Const(0x80) | ||
43 | |||
44 | #define SIGN_Positive Const(0) | ||
45 | #define SIGN_Negative Const(0x8000) | ||
46 | |||
47 | |||
48 | /* Keep the order TAG_Valid, TAG_Zero, TW_Denormal */ | ||
49 | /* The following fold to 2 (Special) in the Tag Word */ | ||
50 | #define TW_Denormal Const(4) /* De-normal */ | ||
51 | #define TW_Infinity Const(5) /* + or - infinity */ | ||
52 | #define TW_NaN Const(6) /* Not a Number */ | ||
53 | #define TW_Unsupported Const(7) /* Not supported by an 80486 */ | ||
54 | |||
55 | #define TAG_Valid Const(0) /* valid */ | ||
56 | #define TAG_Zero Const(1) /* zero */ | ||
57 | #define TAG_Special Const(2) /* De-normal, + or - infinity, | ||
58 | or Not a Number */ | ||
59 | #define TAG_Empty Const(3) /* empty */ | ||
60 | #define TAG_Error Const(0x80) /* probably need to abort */ | ||
61 | |||
62 | #define LOADED_DATA Const(10101) /* Special st() number to identify | ||
63 | loaded data (not on stack). */ | ||
64 | |||
65 | /* A few flags (must be >= 0x10). */ | ||
66 | #define REV 0x10 | ||
67 | #define DEST_RM 0x20 | ||
68 | #define LOADED 0x40 | ||
69 | |||
70 | #define FPU_Exception Const(0x80000000) /* Added to tag returns. */ | ||
71 | |||
72 | |||
73 | #ifndef __ASSEMBLY__ | ||
74 | |||
75 | #include "fpu_system.h" | ||
76 | |||
77 | #include <asm/sigcontext.h> /* for struct _fpstate */ | ||
78 | #include <asm/math_emu.h> | ||
79 | #include <linux/linkage.h> | ||
80 | |||
81 | /* | ||
82 | #define RE_ENTRANT_CHECKING | ||
83 | */ | ||
84 | |||
85 | #ifdef RE_ENTRANT_CHECKING | ||
86 | extern u_char emulating; | ||
87 | # define RE_ENTRANT_CHECK_OFF emulating = 0 | ||
88 | # define RE_ENTRANT_CHECK_ON emulating = 1 | ||
89 | #else | ||
90 | # define RE_ENTRANT_CHECK_OFF | ||
91 | # define RE_ENTRANT_CHECK_ON | ||
92 | #endif /* RE_ENTRANT_CHECKING */ | ||
93 | |||
94 | #define FWAIT_OPCODE 0x9b | ||
95 | #define OP_SIZE_PREFIX 0x66 | ||
96 | #define ADDR_SIZE_PREFIX 0x67 | ||
97 | #define PREFIX_CS 0x2e | ||
98 | #define PREFIX_DS 0x3e | ||
99 | #define PREFIX_ES 0x26 | ||
100 | #define PREFIX_SS 0x36 | ||
101 | #define PREFIX_FS 0x64 | ||
102 | #define PREFIX_GS 0x65 | ||
103 | #define PREFIX_REPE 0xf3 | ||
104 | #define PREFIX_REPNE 0xf2 | ||
105 | #define PREFIX_LOCK 0xf0 | ||
106 | #define PREFIX_CS_ 1 | ||
107 | #define PREFIX_DS_ 2 | ||
108 | #define PREFIX_ES_ 3 | ||
109 | #define PREFIX_FS_ 4 | ||
110 | #define PREFIX_GS_ 5 | ||
111 | #define PREFIX_SS_ 6 | ||
112 | #define PREFIX_DEFAULT 7 | ||
113 | |||
114 | struct address { | ||
115 | unsigned int offset; | ||
116 | unsigned int selector:16; | ||
117 | unsigned int opcode:11; | ||
118 | unsigned int empty:5; | ||
119 | }; | ||
120 | struct fpu__reg { | ||
121 | unsigned sigl; | ||
122 | unsigned sigh; | ||
123 | short exp; | ||
124 | }; | ||
125 | |||
126 | typedef void (*FUNC)(void); | ||
127 | typedef struct fpu__reg FPU_REG; | ||
128 | typedef void (*FUNC_ST0)(FPU_REG *st0_ptr, u_char st0_tag); | ||
129 | typedef struct { u_char address_size, operand_size, segment; } | ||
130 | overrides; | ||
131 | /* This structure is 32 bits: */ | ||
132 | typedef struct { overrides override; | ||
133 | u_char default_mode; } fpu_addr_modes; | ||
134 | /* PROTECTED has a restricted meaning in the emulator; it is used | ||
135 | to signal that the emulator needs to do special things to ensure | ||
136 | that protection is respected in a segmented model. */ | ||
137 | #define PROTECTED 4 | ||
138 | #define SIXTEEN 1 /* We rely upon this being 1 (true) */ | ||
139 | #define VM86 SIXTEEN | ||
140 | #define PM16 (SIXTEEN | PROTECTED) | ||
141 | #define SEG32 PROTECTED | ||
142 | extern u_char const data_sizes_16[32]; | ||
143 | |||
144 | #define register_base ((u_char *) registers ) | ||
145 | #define fpu_register(x) ( * ((FPU_REG *)( register_base + 10 * (x & 7) )) ) | ||
146 | #define st(x) ( * ((FPU_REG *)( register_base + 10 * ((top+x) & 7) )) ) | ||
147 | |||
148 | #define STACK_OVERFLOW (FPU_stackoverflow(&st_new_ptr)) | ||
149 | #define NOT_EMPTY(i) (!FPU_empty_i(i)) | ||
150 | |||
151 | #define NOT_EMPTY_ST0 (st0_tag ^ TAG_Empty) | ||
152 | |||
153 | #define poppop() { FPU_pop(); FPU_pop(); } | ||
154 | |||
155 | /* push() does not affect the tags */ | ||
156 | #define push() { top--; } | ||
157 | |||
158 | #define signbyte(a) (((u_char *)(a))[9]) | ||
159 | #define getsign(a) (signbyte(a) & 0x80) | ||
160 | #define setsign(a,b) { if (b) signbyte(a) |= 0x80; else signbyte(a) &= 0x7f; } | ||
161 | #define copysign(a,b) { if (getsign(a)) signbyte(b) |= 0x80; \ | ||
162 | else signbyte(b) &= 0x7f; } | ||
163 | #define changesign(a) { signbyte(a) ^= 0x80; } | ||
164 | #define setpositive(a) { signbyte(a) &= 0x7f; } | ||
165 | #define setnegative(a) { signbyte(a) |= 0x80; } | ||
166 | #define signpositive(a) ( (signbyte(a) & 0x80) == 0 ) | ||
167 | #define signnegative(a) (signbyte(a) & 0x80) | ||
168 | |||
169 | static inline void reg_copy(FPU_REG const *x, FPU_REG *y) | ||
170 | { | ||
171 | *(short *)&(y->exp) = *(const short *)&(x->exp); | ||
172 | *(long long *)&(y->sigl) = *(const long long *)&(x->sigl); | ||
173 | } | ||
174 | |||
175 | #define exponent(x) (((*(short *)&((x)->exp)) & 0x7fff) - EXTENDED_Ebias) | ||
176 | #define setexponentpos(x,y) { (*(short *)&((x)->exp)) = \ | ||
177 | ((y) + EXTENDED_Ebias) & 0x7fff; } | ||
178 | #define exponent16(x) (*(short *)&((x)->exp)) | ||
179 | #define setexponent16(x,y) { (*(short *)&((x)->exp)) = (y); } | ||
180 | #define addexponent(x,y) { (*(short *)&((x)->exp)) += (y); } | ||
181 | #define stdexp(x) { (*(short *)&((x)->exp)) += EXTENDED_Ebias; } | ||
182 | |||
183 | #define isdenormal(ptr) (exponent(ptr) == EXP_BIAS+EXP_UNDER) | ||
184 | |||
185 | #define significand(x) ( ((unsigned long long *)&((x)->sigl))[0] ) | ||
186 | |||
187 | |||
188 | /*----- Prototypes for functions written in assembler -----*/ | ||
189 | /* extern void reg_move(FPU_REG *a, FPU_REG *b); */ | ||
190 | |||
191 | asmlinkage int FPU_normalize(FPU_REG *x); | ||
192 | asmlinkage int FPU_normalize_nuo(FPU_REG *x); | ||
193 | asmlinkage int FPU_u_sub(FPU_REG const *arg1, FPU_REG const *arg2, | ||
194 | FPU_REG *answ, unsigned int control_w, u_char sign, | ||
195 | int expa, int expb); | ||
196 | asmlinkage int FPU_u_mul(FPU_REG const *arg1, FPU_REG const *arg2, | ||
197 | FPU_REG *answ, unsigned int control_w, u_char sign, | ||
198 | int expon); | ||
199 | asmlinkage int FPU_u_div(FPU_REG const *arg1, FPU_REG const *arg2, | ||
200 | FPU_REG *answ, unsigned int control_w, u_char sign); | ||
201 | asmlinkage int FPU_u_add(FPU_REG const *arg1, FPU_REG const *arg2, | ||
202 | FPU_REG *answ, unsigned int control_w, u_char sign, | ||
203 | int expa, int expb); | ||
204 | asmlinkage int wm_sqrt(FPU_REG *n, int dummy1, int dummy2, | ||
205 | unsigned int control_w, u_char sign); | ||
206 | asmlinkage unsigned FPU_shrx(void *l, unsigned x); | ||
207 | asmlinkage unsigned FPU_shrxs(void *v, unsigned x); | ||
208 | asmlinkage unsigned long FPU_div_small(unsigned long long *x, unsigned long y); | ||
209 | asmlinkage int FPU_round(FPU_REG *arg, unsigned int extent, int dummy, | ||
210 | unsigned int control_w, u_char sign); | ||
211 | |||
212 | #ifndef MAKING_PROTO | ||
213 | #include "fpu_proto.h" | ||
214 | #endif | ||
215 | |||
216 | #endif /* __ASSEMBLY__ */ | ||
217 | |||
218 | #endif /* _FPU_EMU_H_ */ | ||