1 /* NOTE: this header is included in op-i386.c where global register
2 variable are used. Care must be used when including glibc headers.
42 #define TRAP_FLAG 0x0100
43 #define INTERRUPT_FLAG 0x0200
44 #define DIRECTION_FLAG 0x0400
45 #define IOPL_FLAG_MASK 0x3000
46 #define NESTED_FLAG 0x4000
47 #define BYTE_FL 0x8000 /* Intel reserved! */
48 #define RF_FLAG 0x10000
49 #define VM_FLAG 0x20000
57 #define EXCP05_BOUND 6
58 #define EXCP06_ILLOP 7
61 #define EXCP09_XERR 10
63 #define EXCP0B_NOSEG 12
64 #define EXCP0C_STACK 13
66 #define EXCP0E_PAGE 15
67 #define EXCP10_COPR 17
68 #define EXCP11_ALGN 18
69 #define EXCP12_MCHK 19
71 #define EXCP_INTERRUPT 256 /* async interruption */
74 CC_OP_DYNAMIC
, /* must use dynamic code to get cc_op */
75 CC_OP_EFLAGS
, /* all cc are explicitely computed, CC_SRC = flags */
76 CC_OP_MUL
, /* modify all flags, C, O = (CC_SRC != 0) */
78 CC_OP_ADDB
, /* modify all flags, CC_DST = res, CC_SRC = src1 */
82 CC_OP_ADCB
, /* modify all flags, CC_DST = res, CC_SRC = src1 */
86 CC_OP_SUBB
, /* modify all flags, CC_DST = res, CC_SRC = src1 */
90 CC_OP_SBBB
, /* modify all flags, CC_DST = res, CC_SRC = src1 */
94 CC_OP_LOGICB
, /* modify all flags, CC_DST = res */
98 CC_OP_INCB
, /* modify all flags except, CC_DST = res, CC_SRC = C */
102 CC_OP_DECB
, /* modify all flags except, CC_DST = res, CC_SRC = C */
106 CC_OP_SHLB
, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
110 CC_OP_SARB
, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
118 #define USE_X86LDOUBLE
121 #ifdef USE_X86LDOUBLE
122 typedef long double CPU86_LDouble
;
124 typedef double CPU86_LDouble
;
127 typedef struct SegmentCache
{
133 typedef struct SegmentDescriptorTable
{
136 /* this is the returned base when reading the register, just to
137 avoid that the emulated program modifies it */
138 unsigned long emu_base
;
139 } SegmentDescriptorTable
;
141 typedef struct CPUX86State
{
142 /* standard registers */
147 /* emulator internal eflags handling */
151 int32_t df
; /* D flag : 1 if D = 0, -1 if D = 1 */
154 unsigned int fpstt
; /* top of stack index */
157 uint8_t fptags
[8]; /* 0 = valid, 1 = empty */
158 CPU86_LDouble fpregs
[8];
160 /* emulator internal variables */
164 uint32_t segs
[6]; /* selector values */
165 SegmentCache seg_cache
[6]; /* info taken from LDT/GDT */
166 SegmentDescriptorTable gdt
;
167 SegmentDescriptorTable ldt
;
168 SegmentDescriptorTable idt
;
170 /* various CPU modes */
173 /* exception/interrupt handling */
176 int interrupt_request
;
179 /* all CPU memory access use these macros */
180 static inline int ldub(void *ptr
)
182 return *(uint8_t *)ptr
;
185 static inline int ldsb(void *ptr
)
187 return *(int8_t *)ptr
;
190 static inline void stb(void *ptr
, int v
)
195 #ifdef WORDS_BIGENDIAN
197 /* conservative code for little endian unaligned accesses */
198 static inline int lduw(void *ptr
)
202 __asm__
__volatile__ ("lhbrx %0,0,%1" : "=r" (val
) : "r" (ptr
));
206 return p
[0] | (p
[1] << 8);
210 static inline int ldsw(void *ptr
)
214 __asm__
__volatile__ ("lhbrx %0,0,%1" : "=r" (val
) : "r" (ptr
));
218 return (int16_t)(p
[0] | (p
[1] << 8));
222 static inline int ldl(void *ptr
)
226 __asm__
__volatile__ ("lwbrx %0,0,%1" : "=r" (val
) : "r" (ptr
));
230 return p
[0] | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
234 static inline uint64_t ldq(void *ptr
)
240 return v1
| ((uint64_t)v2
<< 32);
243 static inline void stw(void *ptr
, int v
)
246 __asm__
__volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr
) : "r" (v
), "r" (ptr
));
254 static inline void stl(void *ptr
, int v
)
257 __asm__
__volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr
) : "r" (v
), "r" (ptr
));
267 static inline void stq(void *ptr
, uint64_t v
)
276 static inline float ldfl(void *ptr
)
286 static inline double ldfq(void *ptr
)
296 static inline void stfl(void *ptr
, float v
)
306 static inline void stfq(void *ptr
, double v
)
318 static inline int lduw(void *ptr
)
320 return *(uint16_t *)ptr
;
323 static inline int ldsw(void *ptr
)
325 return *(int16_t *)ptr
;
328 static inline int ldl(void *ptr
)
330 return *(uint32_t *)ptr
;
333 static inline uint64_t ldq(void *ptr
)
335 return *(uint64_t *)ptr
;
338 static inline void stw(void *ptr
, int v
)
340 *(uint16_t *)ptr
= v
;
343 static inline void stl(void *ptr
, int v
)
345 *(uint32_t *)ptr
= v
;
348 static inline void stq(void *ptr
, uint64_t v
)
350 *(uint64_t *)ptr
= v
;
355 static inline float ldfl(void *ptr
)
357 return *(float *)ptr
;
360 static inline double ldfq(void *ptr
)
362 return *(double *)ptr
;
365 static inline void stfl(void *ptr
, float v
)
370 static inline void stfq(void *ptr
, double v
)
377 void cpu_x86_outb(int addr
, int val
);
378 void cpu_x86_outw(int addr
, int val
);
379 void cpu_x86_outl(int addr
, int val
);
380 int cpu_x86_inb(int addr
);
381 int cpu_x86_inw(int addr
);
382 int cpu_x86_inl(int addr
);
385 CPUX86State
*cpu_x86_init(void);
386 int cpu_x86_exec(CPUX86State
*s
);
387 void cpu_x86_interrupt(CPUX86State
*s
);
388 void cpu_x86_close(CPUX86State
*s
);
390 /* needed to load some predefinied segment registers */
391 void cpu_x86_load_seg(CPUX86State
*s
, int seg_reg
, int selector
);
393 /* you can call these signal handler from you SIGBUS and SIGSEGV
394 signal handlers to inform the virtual CPU of exceptions. non zero
395 is returned if the signal was handled by the virtual CPU. */
397 int cpu_x86_signal_handler(int host_signum
, struct siginfo
*info
,
400 /* internal functions */
402 #define GEN_FLAG_CODE32_SHIFT 0
403 #define GEN_FLAG_ADDSEG_SHIFT 1
404 #define GEN_FLAG_SS32_SHIFT 2
405 #define GEN_FLAG_ST_SHIFT 3
407 int cpu_x86_gen_code(uint8_t *gen_code_buf
, int max_code_size
,
408 int *gen_code_size_ptr
,
409 uint8_t *pc_start
, uint8_t *cs_base
, int flags
);
410 void cpu_x86_tblocks_init(void);
412 #endif /* CPU_I386_H */