4 * Copyright (C) 2003, 2004 Jonathan Campbell <jcampbell@mdjk.com>
8 * Initialization, de-initialization, register modification, and default
9 * routines for callbacks (in case they weren't set by the host app).
11 * Internal to this library, there are also functions to take care of
12 * fetching the current opcode (as referred to by CS:IP), fetching
13 * the current opcode for the decompiler (as referred to by a separate
14 * pair CS:IP), and pushing/popping data to/from the stack (SS:SP).
16 ***********************************************************************************
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 ************************************************************************************/
39 /* utility function to normalize a floating point value */
40 void softx87_normalize(softx87_ctx
* ctx
,softx87_reg80
*val
)
48 /* how many leading 0 bits in the mantissa */
51 while (!((val
->mantissa
>>(63-sh
))&1)) {
56 /* if none, don't do anything */
66 /* API for converting an FPU register to a type "double" value.
67 Yes, it is an approximation. Don't take it as the exact value. */
68 double softx87_get_fpu_double(softx87_ctx
* ctx
,softx87_reg80
*reg
,int *numtype
)
73 /* all special cases seem to revolve around exp == 0x7FFF */
74 if (reg
->exponent
== 0x7FFF) {
75 if (reg
->mantissa
== 0) {
78 *numtype
= SX87_FPU_NUMTYPE_NEGINF
;
84 *numtype
= SX87_FPU_NUMTYPE_POSINF
;
91 *numtype
= SX87_FPU_NUMTYPE_NAN
;
97 /* 16383 is the IEEE-754 bias for double extended precision numbers */
98 exp
= reg
->exponent
- (16383+63);
99 #ifdef MSVC_CANT_CONVERT_UI64_TO_DOUBLE
100 if ((reg
->mantissa
>> ((sx87_uldword
)63))&1)
101 /* +2^64 to encourage positive value */
102 val
= ((double)((sx87_sldword
)reg
->mantissa
)) + 18446744073709551616.00;
104 val
= (double)((sx87_sldword
)reg
->mantissa
);
106 val
= (double)(reg
->mantissa
);
108 val
*= pow(2,(double)exp
);
111 *numtype
= SX87_FPU_NUMTYPE_NUMBER
;
119 double softx87_get_fpu_register_double(softx87_ctx
* ctx
,int i
,int *numtype
)
121 if (i
< 0 || i
> 7) {
123 *numtype
= SX87_FPU_NUMTYPE_NAN
;
128 return softx87_get_fpu_double(ctx
,&ctx
->state
.st
[i
],numtype
);
131 /* API for converting a type "double" value to an FPU register.
132 Yes, it is an approximation. Don't take it as the exact value. */
133 void softx87_set_fpu_double(softx87_ctx
* ctx
,softx87_reg80
*reg
,double val
)
135 /* log2 x = ln x / ln 2 */
155 l2b
= (int)ceil(log(val
)/log(2.0));
156 /* calculate just so to produce a normalized value */
157 sal
= val
* pow(2,(double)(63-l2b
));
162 reg
->mantissa
= (sx87_uldword
)sal
;
165 void softx87_set_fpu_register_double(softx87_ctx
* ctx
,int i
,double val
)
170 softx87_set_fpu_double(ctx
,&ctx
->state
.st
[i
],val
);
173 /* callbacks intended to be called by softx86 */
174 int softx87_on_fpu_opcode_exec(/* softx86_ctx */ void* _ctx86
,/* softx87_ctx */ void* _ctx87
,sx86_ubyte opcode
)
176 Sfx87OpcodeTable
*sop
;
182 ctx86
= (softx86_ctx
*)_ctx86
;
183 ctx87
= (softx87_ctx
*)_ctx87
;
184 if (!_ctx86
|| !_ctx87
) return 0;
185 if (opcode
< 0xD8 || opcode
> 0xDF) return 0;
186 sop
= (Sfx87OpcodeTable
*)ctx87
->opcode_table
;
188 op2
= ctx87
->callbacks
.on_softx86_fetch_exec_byte(ctx86
);
189 return sop
->table
[opcode
-0xD8].exec(op2
,ctx87
);
192 int softx87_on_fpu_opcode_dec(/* softx86_ctx */ void* _ctx86
,/* softx87_ctx */ void* _ctx87
,sx86_ubyte opcode
,char buf
[128])
194 Sfx87OpcodeTable
*sop
;
200 ctx86
= (softx86_ctx
*)_ctx86
;
201 ctx87
= (softx87_ctx
*)_ctx87
;
202 if (!_ctx86
|| !_ctx87
) return 0;
203 if (opcode
< 0xD8 || opcode
> 0xDF) return 0;
204 sop
= (Sfx87OpcodeTable
*)ctx87
->opcode_table
;
206 op2
= ctx87
->callbacks
.on_softx86_fetch_dec_byte(ctx86
);
207 return sop
->table
[opcode
-0xD8].dec(op2
,ctx87
,buf
);
210 void softx87_finit_setup(softx87_ctx
* ctx
)
212 softx87_set_fpu_register_double(ctx
,0,0.00);
213 softx87_set_fpu_register_double(ctx
,1,0.00);
214 softx87_set_fpu_register_double(ctx
,2,0.00);
215 softx87_set_fpu_register_double(ctx
,3,0.00);
216 softx87_set_fpu_register_double(ctx
,4,0.00);
217 softx87_set_fpu_register_double(ctx
,5,0.00);
218 softx87_set_fpu_register_double(ctx
,6,0.00);
219 softx87_set_fpu_register_double(ctx
,7,0.00);
220 ctx
->state
.control_word
= 0x037F;
221 ctx
->state
.status_word
= 0x0000;
222 ctx
->state
.tag_word
= 0xFFFF; // all empty
223 ctx
->state
.last_instruction_memptr
.offset
= 0;
224 ctx
->state
.last_instruction_memptr
.segment
= 0;
225 ctx
->state
.data_pointer
.offset
= 0;
226 ctx
->state
.data_pointer
.segment
= 0;
227 ctx
->state
.last_opcode
= 0;
230 /* softx87_reset(context)
236 int softx87_reset(softx87_ctx
* ctx
)
240 /* switch on/off bugs */
241 ctx
->bugs
.ip_ignores_prefix
=
242 (ctx
->level
<= SX87_FPULEVEL_8087
)?1:0;
245 ctx
->opcode_table
= (void*)(&optab8087
);
247 /* set up as if FINIT */
248 softx87_finit_setup(ctx
);
250 return 1; /* success */
253 int softx87_getversion(int *major
,int *minor
,int *subminor
)
255 if (!minor
|| !major
|| !subminor
) return 0;
257 *major
= SOFTX87_VERSION_HI
;
258 *minor
= SOFTX87_VERSION_LO
;
259 *subminor
= SOFTX87_VERSION_SUBLO
;
263 /* softx87_init(context)
264 Initialize a FPU context structure.
269 2 = beta development advisory (FPU level emulation not quite stable) */
270 int softx87_init(softx87_ctx
* ctx
,int level
)
276 if (level
> SX87_FPULEVEL_8087
) return 0; /* we currently support up to the 8087 */
277 if (level
< 0) return 0; /* apparently the host wants an 80(-1)87? :) */
278 // if (level > SX87_FPULEVEL_8087) ret=2; /* 80287 or higher emulation is not stable yet */
281 if (!softx87_reset(ctx
)) return 0;
283 /* store version in the structure */
284 ctx
->version_hi
= SOFTX87_VERSION_HI
;
285 ctx
->version_lo
= SOFTX87_VERSION_LO
;
286 ctx
->version_sublo
= SOFTX87_VERSION_SUBLO
;
288 /* default callbacks */
289 ctx
->callbacks
.on_read_memory
= softx87_step_def_on_read_memory
;
290 ctx
->callbacks
.on_write_memory
= softx87_step_def_on_write_memory
;
291 ctx
->callbacks
.on_softx86_fetch_exec_byte
= softx87_def_on_softx86_fetch_exec_byte
;
292 ctx
->callbacks
.on_softx86_fetch_dec_byte
= softx87_def_on_softx86_fetch_dec_byte
;
293 ctx
->callbacks
.on_sx86_exec_full_modrmonly_memx
= softx87_on_sx86_exec_full_modrmonly_memx
;
294 ctx
->callbacks
.on_sx86_dec_full_modrmonly
= softx87_on_sx86_dec_full_modrmonly
;
296 return ret
; /* success */
299 /* softx86_free(context)
300 Free a FPU context structure */
301 int softx87_free(softx87_ctx
* ctx
)
305 return 1; /* success */
308 /* enable/disable emulation of specific bugs. */
309 int softx87_setbug(softx87_ctx
* ctx
,sx86_udword bug_id
,sx86_ubyte on_off
)
311 if (bug_id
== SX87_BUG_IP_IGNORES_PREFIX
) {
312 ctx
->bugs
.ip_ignores_prefix
= on_off
;
319 /*--------------------------------------------------------------------------------
321 --------------------------------------------------------------------------------*/
323 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
))
327 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
)
331 sx86_ubyte
softx87_def_on_softx86_fetch_exec_byte(softx86_ctx
* ctx
)
336 sx86_ubyte
softx87_def_on_softx86_fetch_dec_byte(softx86_ctx
* ctx
)
341 void softx87_step_def_on_read_memory(void* _ctx
,sx86_udword address
,sx86_ubyte
*buf
,int size
)
343 softx87_ctx
*ctx
= ((softx87_ctx
*)_ctx
);
344 if (!ctx
|| !buf
|| size
< 1) return;
345 memset(buf
,0xFF,size
);
348 void softx87_step_def_on_write_memory(void* _ctx
,sx86_udword address
,sx86_ubyte
*buf
,int size
)
350 softx87_ctx
*ctx
= ((softx87_ctx
*)_ctx
);
351 if (!ctx
|| !buf
|| size
< 1) return;
354 /* loading/storing and conversion code */
356 /* loads 16-bit integer from data[] */
357 void softx87_unpack_raw_int16(softx87_ctx
* ctx
,char *data
,softx87_reg80
*v
)
359 #if SX86_BYTE_ORDER == LE
360 v
->mantissa
= (sx87_uldword
)(*((sx87_uword
*)data
));
362 v
->mantissa
= (sx87_uldword
)data
[0];
363 v
->mantissa
|= ((sx87_uldword
)data
[1])<<((sx87_uldword
)8);
366 /* there. we have all 16 bits. spread them around. */
367 v
->sign_bit
= (v
->mantissa
>> ((sx87_uldword
)15));
369 if (v
->sign_bit
) v
->mantissa
= ((v
->mantissa
^ 0xFFFF)+1);
370 v
->mantissa
<<= (sx87_uldword
)49;
372 /* convert the exponent */
373 v
->exponent
= v
->exponent
+ 16383;
376 /* loads 32-bit integer from data[] */
377 void softx87_unpack_raw_int32(softx87_ctx
* ctx
,char *data
,softx87_reg80
*v
)
379 #if SX86_BYTE_ORDER == LE
380 v
->mantissa
= (sx87_uldword
)(*((sx87_udword
*)data
));
382 v
->mantissa
= (sx87_uldword
)data
[3];
383 v
->mantissa
|= ((sx87_uldword
)data
[2])<<((sx87_uldword
)8);
384 v
->mantissa
|= ((sx87_uldword
)data
[1])<<((sx87_uldword
)16);
385 v
->mantissa
|= ((sx87_uldword
)data
[0])<<((sx87_uldword
)24);
388 /* there. we have all 32 bits. spread them around. */
389 v
->sign_bit
= (v
->mantissa
>> ((sx87_uldword
)31));
391 if (v
->sign_bit
) v
->mantissa
= ((v
->mantissa
^ 0xFFFFFFFF)+1);
392 v
->mantissa
<<= (sx87_uldword
)33;
394 /* convert the exponent */
395 v
->exponent
= v
->exponent
+ 16383;
398 /* loads 32-bit double precision floating point from data[] */
399 void softx87_unpack_raw_fp32(softx87_ctx
* ctx
,char *data
,softx87_reg80
*v
)
401 #if SX86_BYTE_ORDER == LE
402 v
->mantissa
= (sx87_uldword
)(*((sx87_udword
*)data
));
404 v
->mantissa
= (sx87_uldword
)data
[3];
405 v
->mantissa
|= ((sx87_uldword
)data
[2])<<((sx87_uldword
)8);
406 v
->mantissa
|= ((sx87_uldword
)data
[1])<<((sx87_uldword
)16);
407 v
->mantissa
|= ((sx87_uldword
)data
[0])<<((sx87_uldword
)24);
410 /* there. we have all 32 bits. spread them around. */
411 v
->sign_bit
= (v
->mantissa
>> ((sx87_uldword
)31));
412 v
->exponent
= (v
->mantissa
>> ((sx87_uldword
)23))&0xFF;
413 v
->mantissa
&= (sx87_uldword
)(0x7FFFFF);
414 v
->mantissa
|= (sx87_uldword
)(0x800000); /* implied "1"? */
415 v
->mantissa
<<= (sx87_uldword
)40;
417 /* convert the exponent */
418 v
->exponent
= (v
->exponent
- 127) + 16383;
421 /* loads 64-bit double precision floating point from data[] */
422 void softx87_unpack_raw_fp64(softx87_ctx
* ctx
,char *data
,softx87_reg80
*v
)
424 #if SX86_BYTE_ORDER == LE
425 v
->mantissa
= *((sx87_uldword
*)data
);
427 v
->mantissa
= (sx87_uldword
)data
[7];
428 v
->mantissa
|= ((sx87_uldword
)data
[6])<<((sx87_uldword
)8);
429 v
->mantissa
|= ((sx87_uldword
)data
[5])<<((sx87_uldword
)16);
430 v
->mantissa
|= ((sx87_uldword
)data
[4])<<((sx87_uldword
)24);
431 v
->mantissa
|= ((sx87_uldword
)data
[3])<<((sx87_uldword
)32);
432 v
->mantissa
|= ((sx87_uldword
)data
[2])<<((sx87_uldword
)40);
433 v
->mantissa
|= ((sx87_uldword
)data
[1])<<((sx87_uldword
)48);
434 v
->mantissa
|= ((sx87_uldword
)data
[0])<<((sx87_uldword
)56);
437 /* there. we have all 64 bits. spread them around. */
438 v
->sign_bit
= (v
->mantissa
>> ((sx87_uldword
)63));
439 v
->exponent
= (v
->mantissa
>> ((sx87_uldword
)52))&0x7FF;
440 v
->mantissa
&= (sx87_uldword
)(0x0FFFFFFFFFFFFF);
441 v
->mantissa
|= (sx87_uldword
)(0x10000000000000); /* implied "1"? */
442 v
->mantissa
<<= (sx87_uldword
)11;
444 /* convert the exponent */
445 v
->exponent
= (v
->exponent
- 1023) + 16383;