[SOFTX86]
[reactos.git] / include / reactos / libs / softx86 / softx87.h
1
2 #ifndef SOFTX87_H
3 #define SOFTX87_H
4
5 /* get the Softx86 configuration defines and Softx86 headers */
6 #include "softx86.h"
7 #include <softx86cfg.h>
8
9 #ifdef __cplusplus
10 extern "C" {
11 #endif //__cplusplus
12
13 /// version composed as follows: H.LL.SSSS
14 // where: H = major version number (any length)
15 // L = minor version number (2 digits)
16 // S = sub-minor version number (4 digits)
17 //
18 // This is v0.00.0033
19 #define SOFTX87_VERSION_HI 0
20 #define SOFTX87_VERSION_LO 0
21 #define SOFTX87_VERSION_SUBLO 33
22
23 #ifdef __MINGW32__ // MINGW
24
25 typedef unsigned char sx87_ubyte;
26 typedef signed char sx87_sbyte;
27 typedef unsigned short int sx87_uword;
28 typedef signed short int sx87_sword;
29 typedef unsigned int sx87_udword;
30 typedef signed int sx87_sdword;
31 typedef unsigned long long int sx87_uldword;
32 typedef signed long long int sx87_sldword;
33
34 #elif WIN32 // MSVC
35
36 typedef unsigned char sx87_ubyte;
37 typedef signed char sx87_sbyte;
38 typedef unsigned short int sx87_uword;
39 typedef signed short int sx87_sword;
40 typedef unsigned int sx87_udword;
41 typedef signed int sx87_sdword;
42 typedef unsigned __int64 sx87_uldword;
43 typedef signed __int64 sx87_sldword;
44
45 #else // GCC 3.xx.xx
46
47 typedef unsigned char sx87_ubyte;
48 typedef signed char sx87_sbyte;
49 typedef unsigned short int sx87_uword;
50 typedef signed short int sx87_sword;
51 typedef unsigned int sx87_udword;
52 typedef signed int sx87_sdword;
53 typedef unsigned long long int sx87_uldword;
54 typedef signed long long int sx87_sldword;
55
56 #endif
57
58 /* NOTE: Each FPU register is maintained in a format similar but not
59 quite the same as the 80-bit format documented by Intel to
60 be the "internal" format used by the FPU.
61
62 We store the sign, mantissa, and exponent differently.
63
64 Intel documents the 80-bit register to be stored like this:
65
66 bit 79: sign
67 bits 64-78: exponent
68 bit 0-63: mantissa.
69
70 This is referred to in their documentation as "double extended precision F.P"
71 */
72 typedef struct {
73 sx86_uldword mantissa;
74 sx86_uword exponent;
75 sx86_ubyte sign_bit;
76 } softx87_reg80;
77
78 /*============================================================================
79 FPU state variables.
80
81 WARNING: This structure is likely to change constantly over time, do not
82 rely on this structure staying the same from version to version.
83 */
84
85 typedef struct {
86 sx86_udword offset;
87 sx86_uword segment;
88 } softx87_ptr;
89
90 typedef struct {
91 sx86_uword status_word; /* status word */
92 sx86_uword control_word; /* control word */
93 sx86_uword tag_word; /* "TAG" word */
94 softx87_ptr data_pointer; /* ? */
95 softx87_ptr last_instruction; /* last instruction address */
96 softx87_ptr last_instruction_memptr; /* last instruction memory reference */
97 sx87_uword last_opcode; /* last FPU opcode */
98 softx87_reg80 st[8]; /* registers ST(0) thru ST(7) */
99 } softx87_fpustate;
100
101 typedef struct {
102 /* I/O */
103 void (*on_read_memory) (/* softx87_ctx */ void* _ctx,sx87_udword address,sx87_ubyte *buf,int size); /* called to fetch from memory <size> bytes from address <address> */
104 void (*on_write_memory) (/* softx87_ctx */ void* _ctx,sx87_udword address,sx87_ubyte *buf,int size); /* called to write to memory <size> bytes from address <address> */
105 /* callbacks to softx86 for fetching more opcodes */
106 sx86_ubyte (*on_softx86_fetch_exec_byte) (softx86_ctx *ctx);
107 sx86_ubyte (*on_softx86_fetch_dec_byte) (softx86_ctx *ctx);
108 void (*on_sx86_exec_full_modrmonly_memx) (softx86_ctx *ctx,sx86_ubyte mod,sx86_ubyte rm,int sz,void (*op64)(softx86_ctx* ctx,char *datz,int sz));
109 void (*on_sx86_exec_full_modrw_memx) (softx86_ctx* ctx,sx86_ubyte mod,sx86_ubyte rm,int sz,void (*op64)(softx86_ctx* ctx,char *datz,int sz));
110 void (*on_sx86_dec_full_modrmonly) (softx86_ctx *ctx,sx86_ubyte is_word,sx86_ubyte dat32,sx86_ubyte mod,sx86_ubyte rm,char* op1);
111 } softx87_callbacks;
112
113 /*=====================================================================================
114 Softx87 bug structure
115
116 This structure is used to contain variables related to the emulation of various
117 flaws and bugs in the FPU.
118
119 Please do not modify these directly.
120 */
121 typedef struct {
122 sx87_ubyte ip_ignores_prefix; // 1=8087 FPU behavior where FPU last instruction pointer ignores the 8086 prefixes
123 } softx87_bugs;
124
125 /*=====================================================================================
126 Softx87 context structure
127
128 This structure is used to interact with the host application.
129 */
130 typedef struct {
131 // version
132 sx87_ubyte version_hi;
133 sx87_ubyte version_lo;
134 sx87_uword version_sublo;
135 // other
136 softx87_fpustate state;
137 softx87_callbacks callbacks;
138 softx87_bugs bugs;
139 void* opcode_table;
140 int level;
141 softx86_ctx* ref_softx86;
142 } softx87_ctx;
143
144 /* FPU emulation levels */
145 #define SX87_FPULEVEL_8087 0 // 8088
146 #define SX87_FPULEVEL_80287 1 // 80287
147 #define SX87_FPULEVEL_80387 2 // 80387
148 #define SX87_FPULEVEL_80487 3 // 80487
149
150 /* Types as returned by softx87_get_fpu_register_double() */
151 #define SX87_FPU_NUMTYPE_NUMBER 0 // a number
152 #define SX87_FPU_NUMTYPE_NEGINF 1 // -infinity
153 #define SX87_FPU_NUMTYPE_POSINF 2 // +infinity
154 #define SX87_FPU_NUMTYPE_NAN 3 // NaN
155
156 /* API */
157 int softx87_getversion(int *major,int *minor,int *subminor);
158 int softx87_init(softx87_ctx* ctx,int level);
159 int softx87_reset(softx87_ctx* ctx);
160 int softx87_free(softx87_ctx* ctx);
161 double softx87_get_fpu_double(softx87_ctx* ctx,softx87_reg80 *reg,int *numtype);
162 void softx87_set_fpu_double(softx87_ctx* ctx,softx87_reg80 *reg,double val);
163 double softx87_get_fpu_register_double(softx87_ctx* ctx,int i,int *numtype);
164 void softx87_set_fpu_register_double(softx87_ctx* ctx,int i,double val);
165 void softx87_finit_setup(softx87_ctx* ctx);
166 /* callbacks intended for reference to softx86 */
167 int softx87_on_fpu_opcode_exec(/* softx86_ctx */ void* _ctx86,/* softx87_ctx */ void* _ctx87,sx86_ubyte opcode);
168 int softx87_on_fpu_opcode_dec(/* softx86_ctx */ void* _ctx86,/* softx87_ctx */ void* _ctx87,sx86_ubyte opcode,char buf[128]);
169
170 /* mask constants for FPU status */
171 /*-----------exception flags----------*/
172 #define SX87_FPUSTAT_INVALID_OP 0x0001
173 #define SX87_FPUSTAT_DENORMAL 0x0002
174 #define SX87_FPUSTAT_ZERO_DIVIDE 0x0004
175 #define SX87_FPUSTAT_OVERFLOW 0x0008
176 #define SX87_FPUSTAT_UNDERFLOW 0x0010
177 #define SX87_FPUSTAT_PRECISION 0x0020
178 /*-----------more flags---------------*/
179 #define SX87_FPUSTAT_STACK_FAULT 0x0040
180 #define SX87_FPUSTAT_ERROR_SUMMARY 0x0080
181 /*-----------condition codes----------*/
182 #define SX87_FPUSTAT_C0 0x0100
183 #define SX87_FPUSTAT_C1 0x0200
184 #define SX87_FPUSTAT_C2 0x0400
185 #define SX87_FPUSTAT_TOP_MASK 0x3800
186 #define SX87_FPUSTAT_TOP(x) (((x)>>11)&7)
187 #define SX87_FPUSTAT_TOP_SET(x,y) (x = (((x)&(~SX87_FPUSTAT_TOP_MASK)) | (((y)&7)<<11)))
188 #define SX87_FPUSTAT_C3 0x4000
189 #define SX87_FPUSTAT_BUSY 0x8000
190
191 /* mask constants for FPU control word */
192 /*-----------exception flags----------*/
193 #define SX87_FPUCTRLW_INVALID_OP 0x0001
194 #define SX87_FPUCTRLW_DENORMAL 0x0002
195 #define SX87_FPUCTRLW_ZERO_DIVIDE 0x0004
196 #define SX87_FPUCTRLW_OVERFLOW 0x0008
197 #define SX87_FPUCTRLW_UNDERFLOW 0x0010
198 #define SX87_FPUCTRLW_PRECISION 0x0020
199 /*-----------precision control flag---*/
200 #define SX87_FPUCTRLW_PCTL_MASK 0x0300
201 #define SX87_FPUCTRLW_PCTL(x) (((x)>>8)&3)
202 #define SX87_FPUCTRLW_PCTL_SET(x,y) (x = (((x)&(~SX87_FPUCTRLW_PCTL_MASK)) | (((y)&3)<<8)))
203 /*-----------rounding control flag----*/
204 #define SX87_FPUCTRLW_RNDCTL_MASK 0x0C00
205 #define SX87_FPUCTRLW_RNDCTL(x) (((x)>>10)&3)
206 #define SX87_FPUCTRLW_RNDCTL_SET(x,y) (x = (((x)&(~SX87_FPUCTRLW_RNDCTL_MASK)) | (((y)&3)<<10)))
207 /*-----------infinity control flag----*/
208 #define SX87_FPUCTRLW_INFCTL 0x1000
209
210 /* precision control flag values */
211 #define SX87_FPUCTRLW_PCTL_24_BIT 0
212 #define SX87_FPUCTRLW_PCTL_RESERVED_1 1
213 #define SX87_FPUCTRLW_PCTL_53_BIT 2
214 #define SX87_FPUCTRLW_PCTL_64_BIT 3
215
216 /* rounding control flag values */
217 #define SX87_FPUCTRLW_RNDCTL_NEAREST 0 /* nearest */
218 #define SX87_FPUCTRLW_RNDCTL_DOWNINF 1 /* down towards -inf */
219 #define SX87_FPUCTRLW_RNDCTL_UPINF 2 /* down towards +inf */
220 #define SX87_FPUCTRLW_RNDCTL_ZERO 3 /* towards zero (truncate) */
221
222 /* mask constants for FPU tag word */
223 #define SX87_FPUTAGW_TAG(x,i) (((x)>>(i*2))&3)
224 #define SX87_FPUTAGW_TAG_SET(x,i,y) (x = (((x) & (~(3<<(i*2)))) | (((y)&3)<<(i*2))))
225 #define SX87_FPUTAGVAL_VALID 0
226 #define SX87_FPUTAGVAL_ZERO 1
227 #define SX87_FPUTAGVAL_SPECIAL 2
228 #define SX87_FPUTAGVAL_EMPTY 3
229
230 /* takes a ST(i) index and converts it to the true register index */
231 #define SX87_FPU_ST(TOP,i) ((TOP+i)&7)
232
233 /* default callback functions within the library */
234 void softx87_step_def_on_read_memory(void* _ctx,sx87_udword address,sx87_ubyte *buf,int size);
235 void softx87_step_def_on_write_memory(void* _ctx,sx87_udword address,sx87_ubyte *buf,int size);
236 sx86_ubyte softx87_def_on_softx86_fetch_exec_byte(softx86_ctx* ctx);
237 sx86_ubyte softx87_def_on_softx86_fetch_dec_byte(softx86_ctx* ctx);
238 void softx87_on_sx86_exec_full_modrmonly_memx(softx86_ctx *ctx,sx86_ubyte mod,sx86_ubyte rm,int sz,void (*op64)(softx86_ctx* ctx,char *datz,int sz));
239 void softx87_on_sx86_dec_full_modrmonly(softx86_ctx* ctx,sx86_ubyte is_word,sx86_ubyte dat32,sx86_ubyte mod,sx86_ubyte rm,char* op1);
240
241 /* bug emulation constants. each is meant to be unique. */
242 #define SX87_BUG_IP_IGNORES_PREFIX 0x56780100
243
244 /* use this to change values in the bug emulation structure */
245 int softx87_setbug(softx87_ctx* ctx,sx87_udword bug_id,sx87_ubyte on_off);
246
247 /* utility */
248 void softx87_normalize(softx87_ctx* ctx,softx87_reg80 *val);
249
250 /* loading/saving */
251 void softx87_unpack_raw_int16(softx87_ctx* ctx,sx87_ubyte *data,softx87_reg80 *v);
252 void softx87_unpack_raw_int32(softx87_ctx* ctx,sx87_ubyte *data,softx87_reg80 *v);
253 void softx87_unpack_raw_fp32(softx87_ctx* ctx,sx87_ubyte *data,softx87_reg80 *v);
254 void softx87_unpack_raw_fp64(softx87_ctx* ctx,sx87_ubyte *data,softx87_reg80 *v);
255
256 #ifdef __cplusplus
257 }
258 #endif //__cplusplus
259
260 /* softx87_connect_to_CPU(context)
261 Connects Softx86 CPU to a Softx87 FPU.
262 This function assumes that you want the CPU and FPU to
263 share the same memory. Provided as a service for those
264 who don't want to manually link pointers together and such. */
265 static int softx87_connect_to_CPU(softx86_ctx* cpu,softx87_ctx* fpu)
266 {
267 if (!cpu || !fpu) return 0;
268
269 cpu->ref_softx87_ctx = fpu;
270 fpu->ref_softx86 = cpu;
271 cpu->callbacks->on_fpu_opcode_exec = softx87_on_fpu_opcode_exec;
272 cpu->callbacks->on_fpu_opcode_dec = softx87_on_fpu_opcode_dec;
273 fpu->callbacks.on_read_memory = cpu->callbacks->on_read_memory;
274 fpu->callbacks.on_write_memory = cpu->callbacks->on_write_memory;
275 fpu->callbacks.on_softx86_fetch_dec_byte = softx86_fetch_dec_byte;
276 fpu->callbacks.on_softx86_fetch_exec_byte = softx86_fetch_exec_byte;
277 fpu->callbacks.on_sx86_dec_full_modrmonly = sx86_dec_full_modrmonly;
278 fpu->callbacks.on_sx86_exec_full_modrmonly_memx = sx86_exec_full_modrmonly_memx;
279 fpu->callbacks.on_sx86_exec_full_modrw_memx = sx86_exec_full_modrw_memx;
280
281 return 1;
282 }
283
284 #endif //SOFTX87_H
285