Statistics
| Branch: | Revision:

root / cpu-i386.h @ 3ef693a0

History | View | Annotate | Download (8.9 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 367e86e8 bellard
#define CC_C           0x0001
52 367e86e8 bellard
#define CC_P         0x0004
53 367e86e8 bellard
#define CC_A        0x0010
54 367e86e8 bellard
#define CC_Z        0x0040
55 367e86e8 bellard
#define CC_S    0x0080
56 367e86e8 bellard
#define CC_O    0x0800
57 367e86e8 bellard
58 367e86e8 bellard
#define TRAP_FLAG                0x0100
59 367e86e8 bellard
#define INTERRUPT_FLAG                0x0200
60 367e86e8 bellard
#define DIRECTION_FLAG                0x0400
61 367e86e8 bellard
#define IOPL_FLAG_MASK                0x3000
62 367e86e8 bellard
#define NESTED_FLAG                0x4000
63 367e86e8 bellard
#define BYTE_FL                        0x8000        /* Intel reserved! */
64 367e86e8 bellard
#define RF_FLAG                        0x10000
65 367e86e8 bellard
#define VM_FLAG                        0x20000
66 367e86e8 bellard
/* AC                                0x40000 */
67 367e86e8 bellard
68 0ecfa993 bellard
#define EXCP00_DIVZ        1
69 0ecfa993 bellard
#define EXCP01_SSTP        2
70 0ecfa993 bellard
#define EXCP02_NMI        3
71 0ecfa993 bellard
#define EXCP03_INT3        4
72 0ecfa993 bellard
#define EXCP04_INTO        5
73 0ecfa993 bellard
#define EXCP05_BOUND        6
74 0ecfa993 bellard
#define EXCP06_ILLOP        7
75 0ecfa993 bellard
#define EXCP07_PREX        8
76 0ecfa993 bellard
#define EXCP08_DBLE        9
77 0ecfa993 bellard
#define EXCP09_XERR        10
78 0ecfa993 bellard
#define EXCP0A_TSS        11
79 0ecfa993 bellard
#define EXCP0B_NOSEG        12
80 0ecfa993 bellard
#define EXCP0C_STACK        13
81 0ecfa993 bellard
#define EXCP0D_GPF        14
82 0ecfa993 bellard
#define EXCP0E_PAGE        15
83 0ecfa993 bellard
#define EXCP10_COPR        17
84 0ecfa993 bellard
#define EXCP11_ALGN        18
85 0ecfa993 bellard
#define EXCP12_MCHK        19
86 0ecfa993 bellard
87 9de5e440 bellard
#define EXCP_INTERRUPT         256 /* async interruption */
88 0ecfa993 bellard
89 367e86e8 bellard
enum {
90 367e86e8 bellard
    CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
91 367e86e8 bellard
    CC_OP_EFLAGS,  /* all cc are explicitely computed, CC_SRC = flags */
92 367e86e8 bellard
    CC_OP_MUL, /* modify all flags, C, O = (CC_SRC != 0) */
93 367e86e8 bellard
94 367e86e8 bellard
    CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
95 367e86e8 bellard
    CC_OP_ADDW,
96 367e86e8 bellard
    CC_OP_ADDL,
97 367e86e8 bellard
98 4b74fe1f bellard
    CC_OP_ADCB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
99 4b74fe1f bellard
    CC_OP_ADCW,
100 4b74fe1f bellard
    CC_OP_ADCL,
101 4b74fe1f bellard
102 367e86e8 bellard
    CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
103 367e86e8 bellard
    CC_OP_SUBW,
104 367e86e8 bellard
    CC_OP_SUBL,
105 367e86e8 bellard
106 4b74fe1f bellard
    CC_OP_SBBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
107 4b74fe1f bellard
    CC_OP_SBBW,
108 4b74fe1f bellard
    CC_OP_SBBL,
109 4b74fe1f bellard
110 367e86e8 bellard
    CC_OP_LOGICB, /* modify all flags, CC_DST = res */
111 367e86e8 bellard
    CC_OP_LOGICW,
112 367e86e8 bellard
    CC_OP_LOGICL,
113 367e86e8 bellard
114 4b74fe1f bellard
    CC_OP_INCB, /* modify all flags except, CC_DST = res, CC_SRC = C */
115 367e86e8 bellard
    CC_OP_INCW,
116 367e86e8 bellard
    CC_OP_INCL,
117 367e86e8 bellard
118 4b74fe1f bellard
    CC_OP_DECB, /* modify all flags except, CC_DST = res, CC_SRC = C  */
119 367e86e8 bellard
    CC_OP_DECW,
120 367e86e8 bellard
    CC_OP_DECL,
121 367e86e8 bellard
122 367e86e8 bellard
    CC_OP_SHLB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
123 367e86e8 bellard
    CC_OP_SHLW,
124 367e86e8 bellard
    CC_OP_SHLL,
125 367e86e8 bellard
126 4b74fe1f bellard
    CC_OP_SARB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
127 4b74fe1f bellard
    CC_OP_SARW,
128 4b74fe1f bellard
    CC_OP_SARL,
129 4b74fe1f bellard
130 367e86e8 bellard
    CC_OP_NB,
131 367e86e8 bellard
};
132 367e86e8 bellard
133 927f621e bellard
#ifdef __i386__
134 27362c82 bellard
#define USE_X86LDOUBLE
135 927f621e bellard
#endif
136 927f621e bellard
137 927f621e bellard
#ifdef USE_X86LDOUBLE
138 927f621e bellard
typedef long double CPU86_LDouble;
139 927f621e bellard
#else
140 927f621e bellard
typedef double CPU86_LDouble;
141 927f621e bellard
#endif
142 927f621e bellard
143 6dbad63e bellard
typedef struct SegmentCache {
144 6dbad63e bellard
    uint8_t *base;
145 6dbad63e bellard
    unsigned long limit;
146 6dbad63e bellard
    uint8_t seg_32bit;
147 6dbad63e bellard
} SegmentCache;
148 6dbad63e bellard
149 6dbad63e bellard
typedef struct SegmentDescriptorTable {
150 6dbad63e bellard
    uint8_t *base;
151 6dbad63e bellard
    unsigned long limit;
152 6dbad63e bellard
    /* this is the returned base when reading the register, just to
153 6dbad63e bellard
    avoid that the emulated program modifies it */
154 6dbad63e bellard
    unsigned long emu_base;
155 6dbad63e bellard
} SegmentDescriptorTable;
156 6dbad63e bellard
157 ba1c6e37 bellard
typedef struct CPUX86State {
158 367e86e8 bellard
    /* standard registers */
159 367e86e8 bellard
    uint32_t regs[8];
160 dab2ed99 bellard
    uint32_t eip;
161 367e86e8 bellard
    uint32_t eflags;
162 0ecfa993 bellard
163 0ecfa993 bellard
    /* emulator internal eflags handling */
164 367e86e8 bellard
    uint32_t cc_src;
165 367e86e8 bellard
    uint32_t cc_dst;
166 367e86e8 bellard
    uint32_t cc_op;
167 367e86e8 bellard
    int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
168 0ecfa993 bellard
169 927f621e bellard
    /* FPU state */
170 927f621e bellard
    unsigned int fpstt; /* top of stack index */
171 927f621e bellard
    unsigned int fpus;
172 927f621e bellard
    unsigned int fpuc;
173 0ecfa993 bellard
    uint8_t fptags[8];   /* 0 = valid, 1 = empty */
174 0ecfa993 bellard
    CPU86_LDouble fpregs[8];    
175 0ecfa993 bellard
176 367e86e8 bellard
    /* emulator internal variables */
177 927f621e bellard
    CPU86_LDouble ft0;
178 d57c4e01 bellard
    
179 6dbad63e bellard
    /* segments */
180 6dbad63e bellard
    uint32_t segs[6]; /* selector values */
181 6dbad63e bellard
    SegmentCache seg_cache[6]; /* info taken from LDT/GDT */
182 6dbad63e bellard
    SegmentDescriptorTable gdt;
183 6dbad63e bellard
    SegmentDescriptorTable ldt;
184 6dbad63e bellard
    SegmentDescriptorTable idt;
185 6dbad63e bellard
    
186 6dbad63e bellard
    /* various CPU modes */
187 6dbad63e bellard
    int vm86;
188 6dbad63e bellard
189 9de5e440 bellard
    /* exception/interrupt handling */
190 0ecfa993 bellard
    jmp_buf jmp_env;
191 0ecfa993 bellard
    int exception_index;
192 9de5e440 bellard
    int interrupt_request;
193 ba1c6e37 bellard
} CPUX86State;
194 367e86e8 bellard
195 04369ff2 bellard
/* all CPU memory access use these macros */
196 367e86e8 bellard
static inline int ldub(void *ptr)
197 367e86e8 bellard
{
198 367e86e8 bellard
    return *(uint8_t *)ptr;
199 367e86e8 bellard
}
200 367e86e8 bellard
201 367e86e8 bellard
static inline int ldsb(void *ptr)
202 367e86e8 bellard
{
203 367e86e8 bellard
    return *(int8_t *)ptr;
204 367e86e8 bellard
}
205 367e86e8 bellard
206 04369ff2 bellard
static inline void stb(void *ptr, int v)
207 04369ff2 bellard
{
208 04369ff2 bellard
    *(uint8_t *)ptr = v;
209 04369ff2 bellard
}
210 04369ff2 bellard
211 04369ff2 bellard
#ifdef WORDS_BIGENDIAN
212 04369ff2 bellard
213 04369ff2 bellard
/* conservative code for little endian unaligned accesses */
214 04369ff2 bellard
static inline int lduw(void *ptr)
215 04369ff2 bellard
{
216 04369ff2 bellard
#ifdef __powerpc__
217 04369ff2 bellard
    int val;
218 04369ff2 bellard
    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
219 04369ff2 bellard
    return val;
220 04369ff2 bellard
#else
221 04369ff2 bellard
    uint8_t *p = ptr;
222 04369ff2 bellard
    return p[0] | (p[1] << 8);
223 04369ff2 bellard
#endif
224 04369ff2 bellard
}
225 04369ff2 bellard
226 04369ff2 bellard
static inline int ldsw(void *ptr)
227 04369ff2 bellard
{
228 04369ff2 bellard
#ifdef __powerpc__
229 04369ff2 bellard
    int val;
230 04369ff2 bellard
    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
231 04369ff2 bellard
    return (int16_t)val;
232 04369ff2 bellard
#else
233 04369ff2 bellard
    uint8_t *p = ptr;
234 04369ff2 bellard
    return (int16_t)(p[0] | (p[1] << 8));
235 04369ff2 bellard
#endif
236 04369ff2 bellard
}
237 04369ff2 bellard
238 04369ff2 bellard
static inline int ldl(void *ptr)
239 04369ff2 bellard
{
240 04369ff2 bellard
#ifdef __powerpc__
241 04369ff2 bellard
    int val;
242 04369ff2 bellard
    __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
243 04369ff2 bellard
    return val;
244 04369ff2 bellard
#else
245 04369ff2 bellard
    uint8_t *p = ptr;
246 04369ff2 bellard
    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
247 04369ff2 bellard
#endif
248 04369ff2 bellard
}
249 04369ff2 bellard
250 04369ff2 bellard
static inline uint64_t ldq(void *ptr)
251 04369ff2 bellard
{
252 04369ff2 bellard
    uint8_t *p = ptr;
253 04369ff2 bellard
    uint32_t v1, v2;
254 04369ff2 bellard
    v1 = ldl(p);
255 04369ff2 bellard
    v2 = ldl(p + 4);
256 04369ff2 bellard
    return v1 | ((uint64_t)v2 << 32);
257 04369ff2 bellard
}
258 04369ff2 bellard
259 04369ff2 bellard
static inline void stw(void *ptr, int v)
260 04369ff2 bellard
{
261 04369ff2 bellard
#ifdef __powerpc__
262 04369ff2 bellard
    __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
263 04369ff2 bellard
#else
264 04369ff2 bellard
    uint8_t *p = ptr;
265 04369ff2 bellard
    p[0] = v;
266 04369ff2 bellard
    p[1] = v >> 8;
267 04369ff2 bellard
#endif
268 04369ff2 bellard
}
269 04369ff2 bellard
270 04369ff2 bellard
static inline void stl(void *ptr, int v)
271 04369ff2 bellard
{
272 04369ff2 bellard
#ifdef __powerpc__
273 04369ff2 bellard
    __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
274 04369ff2 bellard
#else
275 04369ff2 bellard
    uint8_t *p = ptr;
276 04369ff2 bellard
    p[0] = v;
277 04369ff2 bellard
    p[1] = v >> 8;
278 04369ff2 bellard
    p[2] = v >> 16;
279 04369ff2 bellard
    p[3] = v >> 24;
280 04369ff2 bellard
#endif
281 04369ff2 bellard
}
282 04369ff2 bellard
283 04369ff2 bellard
static inline void stq(void *ptr, uint64_t v)
284 04369ff2 bellard
{
285 04369ff2 bellard
    uint8_t *p = ptr;
286 04369ff2 bellard
    stl(p, (uint32_t)v);
287 04369ff2 bellard
    stl(p + 4, v >> 32);
288 04369ff2 bellard
}
289 04369ff2 bellard
290 04369ff2 bellard
/* float access */
291 04369ff2 bellard
292 04369ff2 bellard
static inline float ldfl(void *ptr)
293 04369ff2 bellard
{
294 04369ff2 bellard
    union {
295 04369ff2 bellard
        float f;
296 04369ff2 bellard
        uint32_t i;
297 04369ff2 bellard
    } u;
298 04369ff2 bellard
    u.i = ldl(ptr);
299 04369ff2 bellard
    return u.f;
300 04369ff2 bellard
}
301 04369ff2 bellard
302 04369ff2 bellard
static inline double ldfq(void *ptr)
303 04369ff2 bellard
{
304 04369ff2 bellard
    union {
305 04369ff2 bellard
        double d;
306 04369ff2 bellard
        uint64_t i;
307 04369ff2 bellard
    } u;
308 04369ff2 bellard
    u.i = ldq(ptr);
309 04369ff2 bellard
    return u.d;
310 04369ff2 bellard
}
311 04369ff2 bellard
312 04369ff2 bellard
static inline void stfl(void *ptr, float v)
313 04369ff2 bellard
{
314 04369ff2 bellard
    union {
315 04369ff2 bellard
        float f;
316 04369ff2 bellard
        uint32_t i;
317 04369ff2 bellard
    } u;
318 04369ff2 bellard
    u.f = v;
319 04369ff2 bellard
    stl(ptr, u.i);
320 04369ff2 bellard
}
321 04369ff2 bellard
322 04369ff2 bellard
static inline void stfq(void *ptr, double v)
323 04369ff2 bellard
{
324 04369ff2 bellard
    union {
325 04369ff2 bellard
        double d;
326 04369ff2 bellard
        uint64_t i;
327 04369ff2 bellard
    } u;
328 04369ff2 bellard
    u.d = v;
329 04369ff2 bellard
    stq(ptr, u.i);
330 04369ff2 bellard
}
331 04369ff2 bellard
332 04369ff2 bellard
#else
333 04369ff2 bellard
334 367e86e8 bellard
static inline int lduw(void *ptr)
335 367e86e8 bellard
{
336 367e86e8 bellard
    return *(uint16_t *)ptr;
337 367e86e8 bellard
}
338 367e86e8 bellard
339 367e86e8 bellard
static inline int ldsw(void *ptr)
340 367e86e8 bellard
{
341 367e86e8 bellard
    return *(int16_t *)ptr;
342 367e86e8 bellard
}
343 367e86e8 bellard
344 367e86e8 bellard
static inline int ldl(void *ptr)
345 367e86e8 bellard
{
346 367e86e8 bellard
    return *(uint32_t *)ptr;
347 367e86e8 bellard
}
348 367e86e8 bellard
349 927f621e bellard
static inline uint64_t ldq(void *ptr)
350 927f621e bellard
{
351 927f621e bellard
    return *(uint64_t *)ptr;
352 927f621e bellard
}
353 367e86e8 bellard
354 367e86e8 bellard
static inline void stw(void *ptr, int v)
355 367e86e8 bellard
{
356 367e86e8 bellard
    *(uint16_t *)ptr = v;
357 367e86e8 bellard
}
358 367e86e8 bellard
359 367e86e8 bellard
static inline void stl(void *ptr, int v)
360 367e86e8 bellard
{
361 367e86e8 bellard
    *(uint32_t *)ptr = v;
362 367e86e8 bellard
}
363 367e86e8 bellard
364 77f8dd5a bellard
static inline void stq(void *ptr, uint64_t v)
365 927f621e bellard
{
366 927f621e bellard
    *(uint64_t *)ptr = v;
367 927f621e bellard
}
368 927f621e bellard
369 927f621e bellard
/* float access */
370 927f621e bellard
371 927f621e bellard
static inline float ldfl(void *ptr)
372 927f621e bellard
{
373 927f621e bellard
    return *(float *)ptr;
374 927f621e bellard
}
375 927f621e bellard
376 927f621e bellard
static inline double ldfq(void *ptr)
377 927f621e bellard
{
378 927f621e bellard
    return *(double *)ptr;
379 927f621e bellard
}
380 927f621e bellard
381 927f621e bellard
static inline void stfl(void *ptr, float v)
382 927f621e bellard
{
383 927f621e bellard
    *(float *)ptr = v;
384 927f621e bellard
}
385 927f621e bellard
386 927f621e bellard
static inline void stfq(void *ptr, double v)
387 927f621e bellard
{
388 927f621e bellard
    *(double *)ptr = v;
389 927f621e bellard
}
390 04369ff2 bellard
#endif
391 927f621e bellard
392 927f621e bellard
#ifndef IN_OP_I386
393 ba1c6e37 bellard
void cpu_x86_outb(int addr, int val);
394 ba1c6e37 bellard
void cpu_x86_outw(int addr, int val);
395 ba1c6e37 bellard
void cpu_x86_outl(int addr, int val);
396 ba1c6e37 bellard
int cpu_x86_inb(int addr);
397 ba1c6e37 bellard
int cpu_x86_inw(int addr);
398 ba1c6e37 bellard
int cpu_x86_inl(int addr);
399 927f621e bellard
#endif
400 367e86e8 bellard
401 ba1c6e37 bellard
CPUX86State *cpu_x86_init(void);
402 ba1c6e37 bellard
int cpu_x86_exec(CPUX86State *s);
403 9de5e440 bellard
void cpu_x86_interrupt(CPUX86State *s);
404 ba1c6e37 bellard
void cpu_x86_close(CPUX86State *s);
405 ba1c6e37 bellard
406 6dbad63e bellard
/* needed to load some predefinied segment registers */
407 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
408 6dbad63e bellard
409 9de5e440 bellard
/* you can call these signal handler from you SIGBUS and SIGSEGV
410 9de5e440 bellard
   signal handlers to inform the virtual CPU of exceptions. non zero
411 9de5e440 bellard
   is returned if the signal was handled by the virtual CPU.  */
412 9de5e440 bellard
struct siginfo;
413 9de5e440 bellard
int cpu_x86_signal_handler(int host_signum, struct siginfo *info, 
414 9de5e440 bellard
                           void *puc);
415 9de5e440 bellard
416 ba1c6e37 bellard
/* internal functions */
417 6dbad63e bellard
418 6dbad63e bellard
#define GEN_FLAG_CODE32_SHIFT 0
419 6dbad63e bellard
#define GEN_FLAG_ADDSEG_SHIFT 1
420 dab2ed99 bellard
#define GEN_FLAG_SS32_SHIFT   2
421 dab2ed99 bellard
#define GEN_FLAG_ST_SHIFT     3
422 dab2ed99 bellard
423 1017ebe9 bellard
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
424 dab2ed99 bellard
                     int *gen_code_size_ptr,
425 dab2ed99 bellard
                     uint8_t *pc_start,  uint8_t *cs_base, int flags);
426 7d13299d bellard
void cpu_x86_tblocks_init(void);
427 ba1c6e37 bellard
428 367e86e8 bellard
#endif /* CPU_I386_H */