blob: 250d8cee7be30a2d4ec0ac00933df33e57194817 (
plain) (
blame)
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
112
113
114
115
116
117
|
#ifndef __X86EMU_PRIVATE_H_
#define __X86EMU_PRIVATE_H_
#include "regs.h"
typedef struct box64context_s box64context_t;
typedef struct x64_ucontext_s x64_ucontext_t;
#define ERR_UNIMPL 1
#define ERR_DIVBY0 2
#define ERR_ILLEGAL 4
typedef struct forkpty_s {
void* amaster;
void* name;
void* termp;
void* winp;
void* f; // forkpty function
} forkpty_t;
typedef union multiuint_s {
uint8_t u8;
uint16_t u16;
uint32_t u32;
uint64_t u64;
} multiuint_t;
typedef struct x64emu_s x64emu_t;
typedef struct x64test_s {
x64emu_t* emu;
uintptr_t memaddr;
int memsize;
int test;
int clean;
uint8_t mem[16];
} x64test_t;
typedef struct x64emu_s {
// cpu
reg64_t regs[16];
x64flags_t eflags;
reg64_t ip;
// sse
sse_regs_t xmm[16];
// fpu / mmx
mmx87_regs_t x87[8];
mmx87_regs_t mmx[8];
x87control_t cw;
x87flags_t sw;
uint32_t top; // top is part of sw, but it's faster to have it separatly
int fpu_stack;
mmxcontrol_t mxcsr;
fpu_ld_t fpu_ld[8]; // for long double emulation / 80bits fld fst
fpu_ll_t fpu_ll[8]; // for 64bits fild / fist sequence
fpu_p_reg_t p_regs[8];
// old ip
uintptr_t old_ip;
// deferred flags
int dummy1; // to align on 64bits with df
deferred_flags_t df;
multiuint_t op1;
multiuint_t op2;
multiuint_t res;
multiuint_t op1_sav; // for dec/inc deferred flags, to be able to compute CF
multiuint_t res_sav;
deferred_flags_t df_sav;
uint32_t *x64emu_parity_tab; // helper
#ifdef HAVE_TRACE
reg64_t oldregs[16];
uintptr_t prev2_ip;
#endif
// segments
uint32_t segs[6]; // only 32bits value?
uintptr_t segs_offs[6]; // computed offset associate with segment
uint32_t segs_serial[6]; // are seg offset clean (not 0) or does they need to be re-computed (0)? For GS, serial need to be the same as context->sel_serial
// parent context
box64context_t *context;
// cpu helpers
reg64_t zero;
reg64_t *sbiidx[16];
// emu control
int quit;
int error;
int fork; // quit because need to fork
forkpty_t* forkpty_info;
int exit;
int quitonlongjmp; // quit if longjmp is called
int quitonexit; // quit if exit/_exit is called
int longjmp; // if quit because of longjmp
x64test_t test; // used for dynarec testing
#ifdef HAVE_TRACE
sse_regs_t old_xmm[16];
#endif
// scratch stack, used for alignement of double and 64bits ints on arm. 200 elements should be enough
uint64_t scratch[200];
// local stack, do be deleted when emu is freed
void* stack2free; // this is the stack to free (can be NULL)
void* init_stack; // initial stack (owned or not)
uint32_t size_stack; // stack size (owned or not)
struct __jmp_buf_tag *jmpbuf;
x64_ucontext_t *uc_link; // to handle setcontext
int type; // EMUTYPE_xxx define
} x64emu_t;
#define EMUTYPE_NONE 0
#define EMUTYPE_MAIN 1
#define EMUTYPE_SIGNAL 2
//#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0; emu->quit=1;}
#define INTR_RAISE_DIV0(emu) {emu->error |= ERR_DIVBY0;} // should rise a SIGFPE and not quit
void applyFlushTo0(x64emu_t* emu);
#endif //__X86EMU_PRIVATE_H_
|