Statistics
| Branch: | Revision:

root / cpu-i386.h @ ae48a073

History | View | Annotate | Download (9.2 kB)

1 3ef693a0 bellard
/*
2 3ef693a0 bellard
 * i386 virtual CPU header
3 3ef693a0 bellard
 * 
4 3ef693a0 bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 3ef693a0 bellard
 *
6 3ef693a0 bellard
 * This library is free software; you can redistribute it and/or
7 3ef693a0 bellard
 * modify it under the terms of the GNU Lesser General Public
8 3ef693a0 bellard
 * License as published by the Free Software Foundation; either
9 3ef693a0 bellard
 * version 2 of the License, or (at your option) any later version.
10 3ef693a0 bellard
 *
11 3ef693a0 bellard
 * This library is distributed in the hope that it will be useful,
12 3ef693a0 bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 3ef693a0 bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 3ef693a0 bellard
 * Lesser General Public License for more details.
15 3ef693a0 bellard
 *
16 3ef693a0 bellard
 * You should have received a copy of the GNU Lesser General Public
17 3ef693a0 bellard
 * License along with this library; if not, write to the Free Software
18 3ef693a0 bellard
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 0ecfa993 bellard
 */
20 367e86e8 bellard
#ifndef CPU_I386_H
21 367e86e8 bellard
#define CPU_I386_H
22 367e86e8 bellard
23 04369ff2 bellard
#include "config.h"
24 0ecfa993 bellard
#include <setjmp.h>
25 0ecfa993 bellard
26 367e86e8 bellard
#define R_EAX 0
27 367e86e8 bellard
#define R_ECX 1
28 367e86e8 bellard
#define R_EDX 2
29 367e86e8 bellard
#define R_EBX 3
30 367e86e8 bellard
#define R_ESP 4
31 367e86e8 bellard
#define R_EBP 5
32 367e86e8 bellard
#define R_ESI 6
33 367e86e8 bellard
#define R_EDI 7
34 367e86e8 bellard
35 367e86e8 bellard
#define R_AL 0
36 367e86e8 bellard
#define R_CL 1
37 367e86e8 bellard
#define R_DL 2
38 367e86e8 bellard
#define R_BL 3
39 367e86e8 bellard
#define R_AH 4
40 367e86e8 bellard
#define R_CH 5
41 367e86e8 bellard
#define R_DH 6
42 367e86e8 bellard
#define R_BH 7
43 367e86e8 bellard
44 367e86e8 bellard
#define R_ES 0
45 367e86e8 bellard
#define R_CS 1
46 367e86e8 bellard
#define R_SS 2
47 367e86e8 bellard
#define R_DS 3
48 367e86e8 bellard
#define R_FS 4
49 367e86e8 bellard
#define R_GS 5
50 367e86e8 bellard
51 fc2b4c48 bellard
/* eflags masks */
52 367e86e8 bellard
#define CC_C           0x0001
53 367e86e8 bellard
#define CC_P         0x0004
54 367e86e8 bellard
#define CC_A        0x0010
55 367e86e8 bellard
#define CC_Z        0x0040
56 367e86e8 bellard
#define CC_S    0x0080
57 367e86e8 bellard
#define CC_O    0x0800
58 367e86e8 bellard
59 fc2b4c48 bellard
#define TF_MASK                 0x00000100
60 fc2b4c48 bellard
#define IF_MASK                 0x00000200
61 fc2b4c48 bellard
#define DF_MASK                 0x00000400
62 fc2b4c48 bellard
#define IOPL_MASK                0x00003000
63 fc2b4c48 bellard
#define NT_MASK                         0x00004000
64 fc2b4c48 bellard
#define RF_MASK                        0x00010000
65 fc2b4c48 bellard
#define VM_MASK                        0x00020000
66 fc2b4c48 bellard
#define AC_MASK                        0x00040000 
67 fc2b4c48 bellard
#define VIF_MASK                0x00080000
68 fc2b4c48 bellard
#define VIP_MASK                0x00100000
69 fc2b4c48 bellard
#define ID_MASK                 0x00200000
70 367e86e8 bellard
71 bc8a22cc bellard
#define EXCP00_DIVZ        0
72 bc8a22cc bellard
#define EXCP01_SSTP        1
73 bc8a22cc bellard
#define EXCP02_NMI        2
74 bc8a22cc bellard
#define EXCP03_INT3        3
75 bc8a22cc bellard
#define EXCP04_INTO        4
76 bc8a22cc bellard
#define EXCP05_BOUND        5
77 bc8a22cc bellard
#define EXCP06_ILLOP        6
78 bc8a22cc bellard
#define EXCP07_PREX        7
79 bc8a22cc bellard
#define EXCP08_DBLE        8
80 bc8a22cc bellard
#define EXCP09_XERR        9
81 bc8a22cc bellard
#define EXCP0A_TSS        10
82 bc8a22cc bellard
#define EXCP0B_NOSEG        11
83 bc8a22cc bellard
#define EXCP0C_STACK        12
84 bc8a22cc bellard
#define EXCP0D_GPF        13
85 bc8a22cc bellard
#define EXCP0E_PAGE        14
86 bc8a22cc bellard
#define EXCP10_COPR        16
87 bc8a22cc bellard
#define EXCP11_ALGN        17
88 bc8a22cc bellard
#define EXCP12_MCHK        18
89 0ecfa993 bellard
90 9de5e440 bellard
#define EXCP_INTERRUPT         256 /* async interruption */
91 0ecfa993 bellard
92 367e86e8 bellard
enum {
93 367e86e8 bellard
    CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
94 367e86e8 bellard
    CC_OP_EFLAGS,  /* all cc are explicitely computed, CC_SRC = flags */
95 367e86e8 bellard
    CC_OP_MUL, /* modify all flags, C, O = (CC_SRC != 0) */
96 367e86e8 bellard
97 367e86e8 bellard
    CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
98 367e86e8 bellard
    CC_OP_ADDW,
99 367e86e8 bellard
    CC_OP_ADDL,
100 367e86e8 bellard
101 4b74fe1f bellard
    CC_OP_ADCB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
102 4b74fe1f bellard
    CC_OP_ADCW,
103 4b74fe1f bellard
    CC_OP_ADCL,
104 4b74fe1f bellard
105 367e86e8 bellard
    CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
106 367e86e8 bellard
    CC_OP_SUBW,
107 367e86e8 bellard
    CC_OP_SUBL,
108 367e86e8 bellard
109 4b74fe1f bellard
    CC_OP_SBBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
110 4b74fe1f bellard
    CC_OP_SBBW,
111 4b74fe1f bellard
    CC_OP_SBBL,
112 4b74fe1f bellard
113 367e86e8 bellard
    CC_OP_LOGICB, /* modify all flags, CC_DST = res */
114 367e86e8 bellard
    CC_OP_LOGICW,
115 367e86e8 bellard
    CC_OP_LOGICL,
116 367e86e8 bellard
117 4b74fe1f bellard
    CC_OP_INCB, /* modify all flags except, CC_DST = res, CC_SRC = C */
118 367e86e8 bellard
    CC_OP_INCW,
119 367e86e8 bellard
    CC_OP_INCL,
120 367e86e8 bellard
121 4b74fe1f bellard
    CC_OP_DECB, /* modify all flags except, CC_DST = res, CC_SRC = C  */
122 367e86e8 bellard
    CC_OP_DECW,
123 367e86e8 bellard
    CC_OP_DECL,
124 367e86e8 bellard
125 367e86e8 bellard
    CC_OP_SHLB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
126 367e86e8 bellard
    CC_OP_SHLW,
127 367e86e8 bellard
    CC_OP_SHLL,
128 367e86e8 bellard
129 4b74fe1f bellard
    CC_OP_SARB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
130 4b74fe1f bellard
    CC_OP_SARW,
131 4b74fe1f bellard
    CC_OP_SARL,
132 4b74fe1f bellard
133 367e86e8 bellard
    CC_OP_NB,
134 367e86e8 bellard
};
135 367e86e8 bellard
136 927f621e bellard
#ifdef __i386__
137 27362c82 bellard
#define USE_X86LDOUBLE
138 927f621e bellard
#endif
139 927f621e bellard
140 927f621e bellard
#ifdef USE_X86LDOUBLE
141 927f621e bellard
typedef long double CPU86_LDouble;
142 927f621e bellard
#else
143 927f621e bellard
typedef double CPU86_LDouble;
144 927f621e bellard
#endif
145 927f621e bellard
146 6dbad63e bellard
typedef struct SegmentCache {
147 6dbad63e bellard
    uint8_t *base;
148 6dbad63e bellard
    unsigned long limit;
149 6dbad63e bellard
    uint8_t seg_32bit;
150 6dbad63e bellard
} SegmentCache;
151 6dbad63e bellard
152 6dbad63e bellard
typedef struct SegmentDescriptorTable {
153 6dbad63e bellard
    uint8_t *base;
154 6dbad63e bellard
    unsigned long limit;
155 6dbad63e bellard
    /* this is the returned base when reading the register, just to
156 6dbad63e bellard
    avoid that the emulated program modifies it */
157 6dbad63e bellard
    unsigned long emu_base;
158 6dbad63e bellard
} SegmentDescriptorTable;
159 6dbad63e bellard
160 ba1c6e37 bellard
typedef struct CPUX86State {
161 367e86e8 bellard
    /* standard registers */
162 367e86e8 bellard
    uint32_t regs[8];
163 dab2ed99 bellard
    uint32_t eip;
164 fc2b4c48 bellard
    uint32_t eflags; /* eflags register. During CPU emulation, CC
165 fc2b4c48 bellard
                        flags and DF are set to zero because they are
166 d34720fd bellard
                        stored elsewhere */
167 0ecfa993 bellard
168 0ecfa993 bellard
    /* emulator internal eflags handling */
169 367e86e8 bellard
    uint32_t cc_src;
170 367e86e8 bellard
    uint32_t cc_dst;
171 367e86e8 bellard
    uint32_t cc_op;
172 367e86e8 bellard
    int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
173 0ecfa993 bellard
174 927f621e bellard
    /* FPU state */
175 927f621e bellard
    unsigned int fpstt; /* top of stack index */
176 927f621e bellard
    unsigned int fpus;
177 927f621e bellard
    unsigned int fpuc;
178 0ecfa993 bellard
    uint8_t fptags[8];   /* 0 = valid, 1 = empty */
179 0ecfa993 bellard
    CPU86_LDouble fpregs[8];    
180 0ecfa993 bellard
181 367e86e8 bellard
    /* emulator internal variables */
182 927f621e bellard
    CPU86_LDouble ft0;
183 d57c4e01 bellard
    
184 6dbad63e bellard
    /* segments */
185 6dbad63e bellard
    uint32_t segs[6]; /* selector values */
186 6dbad63e bellard
    SegmentCache seg_cache[6]; /* info taken from LDT/GDT */
187 6dbad63e bellard
    SegmentDescriptorTable gdt;
188 6dbad63e bellard
    SegmentDescriptorTable ldt;
189 6dbad63e bellard
    SegmentDescriptorTable idt;
190 6dbad63e bellard
    
191 9de5e440 bellard
    /* exception/interrupt handling */
192 0ecfa993 bellard
    jmp_buf jmp_env;
193 0ecfa993 bellard
    int exception_index;
194 9de5e440 bellard
    int interrupt_request;
195 fc2b4c48 bellard
196 fc2b4c48 bellard
    /* user data */
197 fc2b4c48 bellard
    void *opaque;
198 ba1c6e37 bellard
} CPUX86State;
199 367e86e8 bellard
200 04369ff2 bellard
/* all CPU memory access use these macros */
201 367e86e8 bellard
static inline int ldub(void *ptr)
202 367e86e8 bellard
{
203 367e86e8 bellard
    return *(uint8_t *)ptr;
204 367e86e8 bellard
}
205 367e86e8 bellard
206 367e86e8 bellard
static inline int ldsb(void *ptr)
207 367e86e8 bellard
{
208 367e86e8 bellard
    return *(int8_t *)ptr;
209 367e86e8 bellard
}
210 367e86e8 bellard
211 04369ff2 bellard
static inline void stb(void *ptr, int v)
212 04369ff2 bellard
{
213 04369ff2 bellard
    *(uint8_t *)ptr = v;
214 04369ff2 bellard
}
215 04369ff2 bellard
216 04369ff2 bellard
#ifdef WORDS_BIGENDIAN
217 04369ff2 bellard
218 04369ff2 bellard
/* conservative code for little endian unaligned accesses */
219 04369ff2 bellard
static inline int lduw(void *ptr)
220 04369ff2 bellard
{
221 04369ff2 bellard
#ifdef __powerpc__
222 04369ff2 bellard
    int val;
223 04369ff2 bellard
    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
224 04369ff2 bellard
    return val;
225 04369ff2 bellard
#else
226 04369ff2 bellard
    uint8_t *p = ptr;
227 04369ff2 bellard
    return p[0] | (p[1] << 8);
228 04369ff2 bellard
#endif
229 04369ff2 bellard
}
230 04369ff2 bellard
231 04369ff2 bellard
static inline int ldsw(void *ptr)
232 04369ff2 bellard
{
233 04369ff2 bellard
#ifdef __powerpc__
234 04369ff2 bellard
    int val;
235 04369ff2 bellard
    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
236 04369ff2 bellard
    return (int16_t)val;
237 04369ff2 bellard
#else
238 04369ff2 bellard
    uint8_t *p = ptr;
239 04369ff2 bellard
    return (int16_t)(p[0] | (p[1] << 8));
240 04369ff2 bellard
#endif
241 04369ff2 bellard
}
242 04369ff2 bellard
243 04369ff2 bellard
static inline int ldl(void *ptr)
244 04369ff2 bellard
{
245 04369ff2 bellard
#ifdef __powerpc__
246 04369ff2 bellard
    int val;
247 04369ff2 bellard
    __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
248 04369ff2 bellard
    return val;
249 04369ff2 bellard
#else
250 04369ff2 bellard
    uint8_t *p = ptr;
251 04369ff2 bellard
    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
252 04369ff2 bellard
#endif
253 04369ff2 bellard
}
254 04369ff2 bellard
255 04369ff2 bellard
static inline uint64_t ldq(void *ptr)
256 04369ff2 bellard
{
257 04369ff2 bellard
    uint8_t *p = ptr;
258 04369ff2 bellard
    uint32_t v1, v2;
259 04369ff2 bellard
    v1 = ldl(p);
260 04369ff2 bellard
    v2 = ldl(p + 4);
261 04369ff2 bellard
    return v1 | ((uint64_t)v2 << 32);
262 04369ff2 bellard
}
263 04369ff2 bellard
264 04369ff2 bellard
static inline void stw(void *ptr, int v)
265 04369ff2 bellard
{
266 04369ff2 bellard
#ifdef __powerpc__
267 04369ff2 bellard
    __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
268 04369ff2 bellard
#else
269 04369ff2 bellard
    uint8_t *p = ptr;
270 04369ff2 bellard
    p[0] = v;
271 04369ff2 bellard
    p[1] = v >> 8;
272 04369ff2 bellard
#endif
273 04369ff2 bellard
}
274 04369ff2 bellard
275 04369ff2 bellard
static inline void stl(void *ptr, int v)
276 04369ff2 bellard
{
277 04369ff2 bellard
#ifdef __powerpc__
278 04369ff2 bellard
    __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
279 04369ff2 bellard
#else
280 04369ff2 bellard
    uint8_t *p = ptr;
281 04369ff2 bellard
    p[0] = v;
282 04369ff2 bellard
    p[1] = v >> 8;
283 04369ff2 bellard
    p[2] = v >> 16;
284 04369ff2 bellard
    p[3] = v >> 24;
285 04369ff2 bellard
#endif
286 04369ff2 bellard
}
287 04369ff2 bellard
288 04369ff2 bellard
static inline void stq(void *ptr, uint64_t v)
289 04369ff2 bellard
{
290 04369ff2 bellard
    uint8_t *p = ptr;
291 04369ff2 bellard
    stl(p, (uint32_t)v);
292 04369ff2 bellard
    stl(p + 4, v >> 32);
293 04369ff2 bellard
}
294 04369ff2 bellard
295 04369ff2 bellard
/* float access */
296 04369ff2 bellard
297 04369ff2 bellard
static inline float ldfl(void *ptr)
298 04369ff2 bellard
{
299 04369ff2 bellard
    union {
300 04369ff2 bellard
        float f;
301 04369ff2 bellard
        uint32_t i;
302 04369ff2 bellard
    } u;
303 04369ff2 bellard
    u.i = ldl(ptr);
304 04369ff2 bellard
    return u.f;
305 04369ff2 bellard
}
306 04369ff2 bellard
307 04369ff2 bellard
static inline double ldfq(void *ptr)
308 04369ff2 bellard
{
309 04369ff2 bellard
    union {
310 04369ff2 bellard
        double d;
311 04369ff2 bellard
        uint64_t i;
312 04369ff2 bellard
    } u;
313 04369ff2 bellard
    u.i = ldq(ptr);
314 04369ff2 bellard
    return u.d;
315 04369ff2 bellard
}
316 04369ff2 bellard
317 04369ff2 bellard
static inline void stfl(void *ptr, float v)
318 04369ff2 bellard
{
319 04369ff2 bellard
    union {
320 04369ff2 bellard
        float f;
321 04369ff2 bellard
        uint32_t i;
322 04369ff2 bellard
    } u;
323 04369ff2 bellard
    u.f = v;
324 04369ff2 bellard
    stl(ptr, u.i);
325 04369ff2 bellard
}
326 04369ff2 bellard
327 04369ff2 bellard
static inline void stfq(void *ptr, double v)
328 04369ff2 bellard
{
329 04369ff2 bellard
    union {
330 04369ff2 bellard
        double d;
331 04369ff2 bellard
        uint64_t i;
332 04369ff2 bellard
    } u;
333 04369ff2 bellard
    u.d = v;
334 04369ff2 bellard
    stq(ptr, u.i);
335 04369ff2 bellard
}
336 04369ff2 bellard
337 04369ff2 bellard
#else
338 04369ff2 bellard
339 367e86e8 bellard
static inline int lduw(void *ptr)
340 367e86e8 bellard
{
341 367e86e8 bellard
    return *(uint16_t *)ptr;
342 367e86e8 bellard
}
343 367e86e8 bellard
344 367e86e8 bellard
static inline int ldsw(void *ptr)
345 367e86e8 bellard
{
346 367e86e8 bellard
    return *(int16_t *)ptr;
347 367e86e8 bellard
}
348 367e86e8 bellard
349 367e86e8 bellard
static inline int ldl(void *ptr)
350 367e86e8 bellard
{
351 367e86e8 bellard
    return *(uint32_t *)ptr;
352 367e86e8 bellard
}
353 367e86e8 bellard
354 927f621e bellard
static inline uint64_t ldq(void *ptr)
355 927f621e bellard
{
356 927f621e bellard
    return *(uint64_t *)ptr;
357 927f621e bellard
}
358 367e86e8 bellard
359 367e86e8 bellard
static inline void stw(void *ptr, int v)
360 367e86e8 bellard
{
361 367e86e8 bellard
    *(uint16_t *)ptr = v;
362 367e86e8 bellard
}
363 367e86e8 bellard
364 367e86e8 bellard
static inline void stl(void *ptr, int v)
365 367e86e8 bellard
{
366 367e86e8 bellard
    *(uint32_t *)ptr = v;
367 367e86e8 bellard
}
368 367e86e8 bellard
369 77f8dd5a bellard
static inline void stq(void *ptr, uint64_t v)
370 927f621e bellard
{
371 927f621e bellard
    *(uint64_t *)ptr = v;
372 927f621e bellard
}
373 927f621e bellard
374 927f621e bellard
/* float access */
375 927f621e bellard
376 927f621e bellard
static inline float ldfl(void *ptr)
377 927f621e bellard
{
378 927f621e bellard
    return *(float *)ptr;
379 927f621e bellard
}
380 927f621e bellard
381 927f621e bellard
static inline double ldfq(void *ptr)
382 927f621e bellard
{
383 927f621e bellard
    return *(double *)ptr;
384 927f621e bellard
}
385 927f621e bellard
386 927f621e bellard
static inline void stfl(void *ptr, float v)
387 927f621e bellard
{
388 927f621e bellard
    *(float *)ptr = v;
389 927f621e bellard
}
390 927f621e bellard
391 927f621e bellard
static inline void stfq(void *ptr, double v)
392 927f621e bellard
{
393 927f621e bellard
    *(double *)ptr = v;
394 927f621e bellard
}
395 04369ff2 bellard
#endif
396 927f621e bellard
397 927f621e bellard
#ifndef IN_OP_I386
398 ba1c6e37 bellard
void cpu_x86_outb(int addr, int val);
399 ba1c6e37 bellard
void cpu_x86_outw(int addr, int val);
400 ba1c6e37 bellard
void cpu_x86_outl(int addr, int val);
401 ba1c6e37 bellard
int cpu_x86_inb(int addr);
402 ba1c6e37 bellard
int cpu_x86_inw(int addr);
403 ba1c6e37 bellard
int cpu_x86_inl(int addr);
404 927f621e bellard
#endif
405 367e86e8 bellard
406 ba1c6e37 bellard
CPUX86State *cpu_x86_init(void);
407 ba1c6e37 bellard
int cpu_x86_exec(CPUX86State *s);
408 9de5e440 bellard
void cpu_x86_interrupt(CPUX86State *s);
409 ba1c6e37 bellard
void cpu_x86_close(CPUX86State *s);
410 ba1c6e37 bellard
411 6dbad63e bellard
/* needed to load some predefinied segment registers */
412 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
413 6dbad63e bellard
414 d691f669 bellard
/* you can call this signal handler from your SIGBUS and SIGSEGV
415 9de5e440 bellard
   signal handlers to inform the virtual CPU of exceptions. non zero
416 9de5e440 bellard
   is returned if the signal was handled by the virtual CPU.  */
417 9de5e440 bellard
struct siginfo;
418 9de5e440 bellard
int cpu_x86_signal_handler(int host_signum, struct siginfo *info, 
419 9de5e440 bellard
                           void *puc);
420 9de5e440 bellard
421 ba1c6e37 bellard
/* internal functions */
422 6dbad63e bellard
423 6dbad63e bellard
#define GEN_FLAG_CODE32_SHIFT 0
424 6dbad63e bellard
#define GEN_FLAG_ADDSEG_SHIFT 1
425 dab2ed99 bellard
#define GEN_FLAG_SS32_SHIFT   2
426 fc2b4c48 bellard
#define GEN_FLAG_VM_SHIFT     3
427 fc2b4c48 bellard
#define GEN_FLAG_ST_SHIFT     4
428 dab2ed99 bellard
429 1017ebe9 bellard
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
430 dab2ed99 bellard
                     int *gen_code_size_ptr,
431 dab2ed99 bellard
                     uint8_t *pc_start,  uint8_t *cs_base, int flags);
432 7d13299d bellard
void cpu_x86_tblocks_init(void);
433 ba1c6e37 bellard
434 367e86e8 bellard
#endif /* CPU_I386_H */