Statistics
| Branch: | Revision:

root / cpu-i386.h @ 5132455e

History | View | Annotate | Download (14.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 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 d014c98c bellard
    union {
184 d014c98c bellard
        float f;
185 d014c98c bellard
        double d;
186 d014c98c bellard
        int i32;
187 d014c98c bellard
        int64_t i64;
188 d014c98c bellard
    } fp_convert;
189 d57c4e01 bellard
    
190 6dbad63e bellard
    /* segments */
191 6dbad63e bellard
    uint32_t segs[6]; /* selector values */
192 6dbad63e bellard
    SegmentCache seg_cache[6]; /* info taken from LDT/GDT */
193 6dbad63e bellard
    SegmentDescriptorTable gdt;
194 6dbad63e bellard
    SegmentDescriptorTable ldt;
195 6dbad63e bellard
    SegmentDescriptorTable idt;
196 6dbad63e bellard
    
197 9de5e440 bellard
    /* exception/interrupt handling */
198 0ecfa993 bellard
    jmp_buf jmp_env;
199 0ecfa993 bellard
    int exception_index;
200 9ba5695c bellard
    int error_code;
201 9ba5695c bellard
    uint32_t cr2;
202 9de5e440 bellard
    int interrupt_request;
203 fc2b4c48 bellard
204 fc2b4c48 bellard
    /* user data */
205 fc2b4c48 bellard
    void *opaque;
206 ba1c6e37 bellard
} CPUX86State;
207 367e86e8 bellard
208 04369ff2 bellard
/* all CPU memory access use these macros */
209 367e86e8 bellard
static inline int ldub(void *ptr)
210 367e86e8 bellard
{
211 367e86e8 bellard
    return *(uint8_t *)ptr;
212 367e86e8 bellard
}
213 367e86e8 bellard
214 367e86e8 bellard
static inline int ldsb(void *ptr)
215 367e86e8 bellard
{
216 367e86e8 bellard
    return *(int8_t *)ptr;
217 367e86e8 bellard
}
218 367e86e8 bellard
219 04369ff2 bellard
static inline void stb(void *ptr, int v)
220 04369ff2 bellard
{
221 04369ff2 bellard
    *(uint8_t *)ptr = v;
222 04369ff2 bellard
}
223 04369ff2 bellard
224 04369ff2 bellard
#ifdef WORDS_BIGENDIAN
225 04369ff2 bellard
226 04369ff2 bellard
/* conservative code for little endian unaligned accesses */
227 04369ff2 bellard
static inline int lduw(void *ptr)
228 04369ff2 bellard
{
229 04369ff2 bellard
#ifdef __powerpc__
230 04369ff2 bellard
    int val;
231 04369ff2 bellard
    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
232 04369ff2 bellard
    return val;
233 04369ff2 bellard
#else
234 04369ff2 bellard
    uint8_t *p = ptr;
235 04369ff2 bellard
    return p[0] | (p[1] << 8);
236 04369ff2 bellard
#endif
237 04369ff2 bellard
}
238 04369ff2 bellard
239 04369ff2 bellard
static inline int ldsw(void *ptr)
240 04369ff2 bellard
{
241 04369ff2 bellard
#ifdef __powerpc__
242 04369ff2 bellard
    int val;
243 04369ff2 bellard
    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
244 04369ff2 bellard
    return (int16_t)val;
245 04369ff2 bellard
#else
246 04369ff2 bellard
    uint8_t *p = ptr;
247 04369ff2 bellard
    return (int16_t)(p[0] | (p[1] << 8));
248 04369ff2 bellard
#endif
249 04369ff2 bellard
}
250 04369ff2 bellard
251 04369ff2 bellard
static inline int ldl(void *ptr)
252 04369ff2 bellard
{
253 04369ff2 bellard
#ifdef __powerpc__
254 04369ff2 bellard
    int val;
255 04369ff2 bellard
    __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
256 04369ff2 bellard
    return val;
257 04369ff2 bellard
#else
258 04369ff2 bellard
    uint8_t *p = ptr;
259 04369ff2 bellard
    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
260 04369ff2 bellard
#endif
261 04369ff2 bellard
}
262 04369ff2 bellard
263 04369ff2 bellard
static inline uint64_t ldq(void *ptr)
264 04369ff2 bellard
{
265 04369ff2 bellard
    uint8_t *p = ptr;
266 04369ff2 bellard
    uint32_t v1, v2;
267 04369ff2 bellard
    v1 = ldl(p);
268 04369ff2 bellard
    v2 = ldl(p + 4);
269 04369ff2 bellard
    return v1 | ((uint64_t)v2 << 32);
270 04369ff2 bellard
}
271 04369ff2 bellard
272 04369ff2 bellard
static inline void stw(void *ptr, int v)
273 04369ff2 bellard
{
274 04369ff2 bellard
#ifdef __powerpc__
275 04369ff2 bellard
    __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
276 04369ff2 bellard
#else
277 04369ff2 bellard
    uint8_t *p = ptr;
278 04369ff2 bellard
    p[0] = v;
279 04369ff2 bellard
    p[1] = v >> 8;
280 04369ff2 bellard
#endif
281 04369ff2 bellard
}
282 04369ff2 bellard
283 04369ff2 bellard
static inline void stl(void *ptr, int v)
284 04369ff2 bellard
{
285 04369ff2 bellard
#ifdef __powerpc__
286 04369ff2 bellard
    __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
287 04369ff2 bellard
#else
288 04369ff2 bellard
    uint8_t *p = ptr;
289 04369ff2 bellard
    p[0] = v;
290 04369ff2 bellard
    p[1] = v >> 8;
291 04369ff2 bellard
    p[2] = v >> 16;
292 04369ff2 bellard
    p[3] = v >> 24;
293 04369ff2 bellard
#endif
294 04369ff2 bellard
}
295 04369ff2 bellard
296 04369ff2 bellard
static inline void stq(void *ptr, uint64_t v)
297 04369ff2 bellard
{
298 04369ff2 bellard
    uint8_t *p = ptr;
299 04369ff2 bellard
    stl(p, (uint32_t)v);
300 04369ff2 bellard
    stl(p + 4, v >> 32);
301 04369ff2 bellard
}
302 04369ff2 bellard
303 04369ff2 bellard
/* float access */
304 04369ff2 bellard
305 04369ff2 bellard
static inline float ldfl(void *ptr)
306 04369ff2 bellard
{
307 04369ff2 bellard
    union {
308 04369ff2 bellard
        float f;
309 04369ff2 bellard
        uint32_t i;
310 04369ff2 bellard
    } u;
311 04369ff2 bellard
    u.i = ldl(ptr);
312 04369ff2 bellard
    return u.f;
313 04369ff2 bellard
}
314 04369ff2 bellard
315 04369ff2 bellard
static inline double ldfq(void *ptr)
316 04369ff2 bellard
{
317 04369ff2 bellard
    union {
318 04369ff2 bellard
        double d;
319 04369ff2 bellard
        uint64_t i;
320 04369ff2 bellard
    } u;
321 04369ff2 bellard
    u.i = ldq(ptr);
322 04369ff2 bellard
    return u.d;
323 04369ff2 bellard
}
324 04369ff2 bellard
325 04369ff2 bellard
static inline void stfl(void *ptr, float v)
326 04369ff2 bellard
{
327 04369ff2 bellard
    union {
328 04369ff2 bellard
        float f;
329 04369ff2 bellard
        uint32_t i;
330 04369ff2 bellard
    } u;
331 04369ff2 bellard
    u.f = v;
332 04369ff2 bellard
    stl(ptr, u.i);
333 04369ff2 bellard
}
334 04369ff2 bellard
335 04369ff2 bellard
static inline void stfq(void *ptr, double v)
336 04369ff2 bellard
{
337 04369ff2 bellard
    union {
338 04369ff2 bellard
        double d;
339 04369ff2 bellard
        uint64_t i;
340 04369ff2 bellard
    } u;
341 04369ff2 bellard
    u.d = v;
342 04369ff2 bellard
    stq(ptr, u.i);
343 04369ff2 bellard
}
344 04369ff2 bellard
345 04369ff2 bellard
#else
346 04369ff2 bellard
347 367e86e8 bellard
static inline int lduw(void *ptr)
348 367e86e8 bellard
{
349 367e86e8 bellard
    return *(uint16_t *)ptr;
350 367e86e8 bellard
}
351 367e86e8 bellard
352 367e86e8 bellard
static inline int ldsw(void *ptr)
353 367e86e8 bellard
{
354 367e86e8 bellard
    return *(int16_t *)ptr;
355 367e86e8 bellard
}
356 367e86e8 bellard
357 367e86e8 bellard
static inline int ldl(void *ptr)
358 367e86e8 bellard
{
359 367e86e8 bellard
    return *(uint32_t *)ptr;
360 367e86e8 bellard
}
361 367e86e8 bellard
362 927f621e bellard
static inline uint64_t ldq(void *ptr)
363 927f621e bellard
{
364 927f621e bellard
    return *(uint64_t *)ptr;
365 927f621e bellard
}
366 367e86e8 bellard
367 367e86e8 bellard
static inline void stw(void *ptr, int v)
368 367e86e8 bellard
{
369 367e86e8 bellard
    *(uint16_t *)ptr = v;
370 367e86e8 bellard
}
371 367e86e8 bellard
372 367e86e8 bellard
static inline void stl(void *ptr, int v)
373 367e86e8 bellard
{
374 367e86e8 bellard
    *(uint32_t *)ptr = v;
375 367e86e8 bellard
}
376 367e86e8 bellard
377 77f8dd5a bellard
static inline void stq(void *ptr, uint64_t v)
378 927f621e bellard
{
379 927f621e bellard
    *(uint64_t *)ptr = v;
380 927f621e bellard
}
381 927f621e bellard
382 927f621e bellard
/* float access */
383 927f621e bellard
384 927f621e bellard
static inline float ldfl(void *ptr)
385 927f621e bellard
{
386 927f621e bellard
    return *(float *)ptr;
387 927f621e bellard
}
388 927f621e bellard
389 927f621e bellard
static inline double ldfq(void *ptr)
390 927f621e bellard
{
391 927f621e bellard
    return *(double *)ptr;
392 927f621e bellard
}
393 927f621e bellard
394 927f621e bellard
static inline void stfl(void *ptr, float v)
395 927f621e bellard
{
396 927f621e bellard
    *(float *)ptr = v;
397 927f621e bellard
}
398 927f621e bellard
399 927f621e bellard
static inline void stfq(void *ptr, double v)
400 927f621e bellard
{
401 927f621e bellard
    *(double *)ptr = v;
402 927f621e bellard
}
403 04369ff2 bellard
#endif
404 927f621e bellard
405 927f621e bellard
#ifndef IN_OP_I386
406 9ba5695c bellard
void cpu_x86_outb(CPUX86State *env, int addr, int val);
407 9ba5695c bellard
void cpu_x86_outw(CPUX86State *env, int addr, int val);
408 9ba5695c bellard
void cpu_x86_outl(CPUX86State *env, int addr, int val);
409 9ba5695c bellard
int cpu_x86_inb(CPUX86State *env, int addr);
410 9ba5695c bellard
int cpu_x86_inw(CPUX86State *env, int addr);
411 9ba5695c bellard
int cpu_x86_inl(CPUX86State *env, int addr);
412 927f621e bellard
#endif
413 367e86e8 bellard
414 ba1c6e37 bellard
CPUX86State *cpu_x86_init(void);
415 ba1c6e37 bellard
int cpu_x86_exec(CPUX86State *s);
416 9de5e440 bellard
void cpu_x86_interrupt(CPUX86State *s);
417 ba1c6e37 bellard
void cpu_x86_close(CPUX86State *s);
418 ba1c6e37 bellard
419 6dbad63e bellard
/* needed to load some predefinied segment registers */
420 6dbad63e bellard
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
421 6dbad63e bellard
422 d691f669 bellard
/* you can call this signal handler from your SIGBUS and SIGSEGV
423 9de5e440 bellard
   signal handlers to inform the virtual CPU of exceptions. non zero
424 9de5e440 bellard
   is returned if the signal was handled by the virtual CPU.  */
425 9de5e440 bellard
struct siginfo;
426 9de5e440 bellard
int cpu_x86_signal_handler(int host_signum, struct siginfo *info, 
427 9de5e440 bellard
                           void *puc);
428 9de5e440 bellard
429 f351077e bellard
/* used to debug */
430 f351077e bellard
#define X86_DUMP_FPU  0x0001 /* dump FPU state too */
431 f351077e bellard
#define X86_DUMP_CCOP 0x0002 /* dump qemu flag cache */
432 f351077e bellard
void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags);
433 f351077e bellard
434 54936004 bellard
/* page related stuff */
435 54936004 bellard
#define TARGET_PAGE_BITS 12
436 54936004 bellard
#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
437 54936004 bellard
#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
438 54936004 bellard
#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
439 54936004 bellard
440 54936004 bellard
extern unsigned long real_host_page_size;
441 54936004 bellard
extern unsigned long host_page_bits;
442 54936004 bellard
extern unsigned long host_page_size;
443 54936004 bellard
extern unsigned long host_page_mask;
444 54936004 bellard
445 54936004 bellard
#define HOST_PAGE_ALIGN(addr) (((addr) + host_page_size - 1) & host_page_mask)
446 54936004 bellard
447 54936004 bellard
/* same as PROT_xxx */
448 fd6ce8f6 bellard
#define PAGE_READ      0x0001
449 fd6ce8f6 bellard
#define PAGE_WRITE     0x0002
450 fd6ce8f6 bellard
#define PAGE_EXEC      0x0004
451 fd6ce8f6 bellard
#define PAGE_BITS      (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
452 fd6ce8f6 bellard
#define PAGE_VALID     0x0008
453 fd6ce8f6 bellard
/* original state of the write flag (used when tracking self-modifying
454 fd6ce8f6 bellard
   code */
455 fd6ce8f6 bellard
#define PAGE_WRITE_ORG 0x0010 
456 54936004 bellard
457 54936004 bellard
void page_dump(FILE *f);
458 54936004 bellard
int page_get_flags(unsigned long address);
459 54936004 bellard
void page_set_flags(unsigned long start, unsigned long end, int flags);
460 fd6ce8f6 bellard
void page_unprotect_range(uint8_t *data, unsigned long data_size);
461 54936004 bellard
462 fd6ce8f6 bellard
/***************************************************/
463 ba1c6e37 bellard
/* internal functions */
464 6dbad63e bellard
465 6dbad63e bellard
#define GEN_FLAG_CODE32_SHIFT 0
466 6dbad63e bellard
#define GEN_FLAG_ADDSEG_SHIFT 1
467 dab2ed99 bellard
#define GEN_FLAG_SS32_SHIFT   2
468 fc2b4c48 bellard
#define GEN_FLAG_VM_SHIFT     3
469 fc2b4c48 bellard
#define GEN_FLAG_ST_SHIFT     4
470 9ba5695c bellard
#define GEN_FLAG_CPL_SHIFT    7
471 9ba5695c bellard
#define GEN_FLAG_IOPL_SHIFT   9
472 cabb4d61 bellard
#define GEN_FLAG_TF_SHIFT     11
473 dab2ed99 bellard
474 1017ebe9 bellard
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
475 dab2ed99 bellard
                     int *gen_code_size_ptr,
476 fd6ce8f6 bellard
                     uint8_t *pc_start,  uint8_t *cs_base, int flags,
477 fd6ce8f6 bellard
                     int *code_size_ptr);
478 7d13299d bellard
void cpu_x86_tblocks_init(void);
479 54936004 bellard
void page_init(void);
480 fd6ce8f6 bellard
int page_unprotect(unsigned long address);
481 fd6ce8f6 bellard
482 fd6ce8f6 bellard
#define CODE_GEN_MAX_SIZE        65536
483 fd6ce8f6 bellard
#define CODE_GEN_ALIGN           16 /* must be >= of the size of a icache line */
484 fd6ce8f6 bellard
485 fd6ce8f6 bellard
#define CODE_GEN_HASH_BITS     15
486 fd6ce8f6 bellard
#define CODE_GEN_HASH_SIZE     (1 << CODE_GEN_HASH_BITS)
487 fd6ce8f6 bellard
488 fd6ce8f6 bellard
/* maximum total translate dcode allocated */
489 fd6ce8f6 bellard
#define CODE_GEN_BUFFER_SIZE     (2048 * 1024)
490 fd6ce8f6 bellard
//#define CODE_GEN_BUFFER_SIZE     (128 * 1024)
491 fd6ce8f6 bellard
492 fd6ce8f6 bellard
typedef struct TranslationBlock {
493 fd6ce8f6 bellard
    unsigned long pc;   /* simulated PC corresponding to this block (EIP + CS base) */
494 fd6ce8f6 bellard
    unsigned long cs_base; /* CS base for this block */
495 fd6ce8f6 bellard
    unsigned int flags; /* flags defining in which context the code was generated */
496 fd6ce8f6 bellard
    uint16_t size;      /* size of target code for this block (1 <=
497 fd6ce8f6 bellard
                           size <= TARGET_PAGE_SIZE) */
498 fd6ce8f6 bellard
    uint8_t *tc_ptr;    /* pointer to the translated code */
499 fd6ce8f6 bellard
    struct TranslationBlock *hash_next; /* next matching block */
500 fd6ce8f6 bellard
    struct TranslationBlock *page_next[2]; /* next blocks in even/odd page */
501 fd6ce8f6 bellard
} TranslationBlock;
502 fd6ce8f6 bellard
503 fd6ce8f6 bellard
static inline unsigned int tb_hash_func(unsigned long pc)
504 fd6ce8f6 bellard
{
505 fd6ce8f6 bellard
    return pc & (CODE_GEN_HASH_SIZE - 1);
506 fd6ce8f6 bellard
}
507 fd6ce8f6 bellard
508 fd6ce8f6 bellard
void tb_flush(void);
509 fd6ce8f6 bellard
TranslationBlock *tb_alloc(unsigned long pc, 
510 fd6ce8f6 bellard
                           unsigned long size);
511 fd6ce8f6 bellard
512 fd6ce8f6 bellard
extern TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
513 fd6ce8f6 bellard
514 fd6ce8f6 bellard
extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
515 fd6ce8f6 bellard
extern uint8_t *code_gen_ptr;
516 fd6ce8f6 bellard
517 fd6ce8f6 bellard
/* find a translation block in the translation cache. If not found,
518 fd6ce8f6 bellard
   return NULL and the pointer to the last element of the list in pptb */
519 fd6ce8f6 bellard
static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
520 fd6ce8f6 bellard
                                        unsigned long pc, 
521 fd6ce8f6 bellard
                                        unsigned long cs_base,
522 fd6ce8f6 bellard
                                        unsigned int flags)
523 fd6ce8f6 bellard
{
524 fd6ce8f6 bellard
    TranslationBlock **ptb, *tb;
525 fd6ce8f6 bellard
    unsigned int h;
526 fd6ce8f6 bellard
 
527 fd6ce8f6 bellard
    h = tb_hash_func(pc);
528 fd6ce8f6 bellard
    ptb = &tb_hash[h];
529 fd6ce8f6 bellard
    for(;;) {
530 fd6ce8f6 bellard
        tb = *ptb;
531 fd6ce8f6 bellard
        if (!tb)
532 fd6ce8f6 bellard
            break;
533 fd6ce8f6 bellard
        if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)
534 fd6ce8f6 bellard
            return tb;
535 fd6ce8f6 bellard
        ptb = &tb->hash_next;
536 fd6ce8f6 bellard
    }
537 fd6ce8f6 bellard
    *pptb = ptb;
538 fd6ce8f6 bellard
    return NULL;
539 fd6ce8f6 bellard
}
540 fd6ce8f6 bellard
541 fd6ce8f6 bellard
#ifndef offsetof
542 fd6ce8f6 bellard
#define offsetof(type, field) ((size_t) &((type *)0)->field)
543 fd6ce8f6 bellard
#endif
544 ba1c6e37 bellard
545 eb51d102 bellard
#ifdef __powerpc__
546 eb51d102 bellard
static inline int testandset (int *p)
547 eb51d102 bellard
{
548 eb51d102 bellard
    int ret;
549 eb51d102 bellard
    __asm__ __volatile__ (
550 eb51d102 bellard
                          "0:    lwarx %0,0,%1 ;"
551 eb51d102 bellard
                          "      xor. %0,%3,%0;"
552 eb51d102 bellard
                          "      bne 1f;"
553 eb51d102 bellard
                          "      stwcx. %2,0,%1;"
554 eb51d102 bellard
                          "      bne- 0b;"
555 eb51d102 bellard
                          "1:    "
556 eb51d102 bellard
                          : "=&r" (ret)
557 eb51d102 bellard
                          : "r" (p), "r" (1), "r" (0)
558 eb51d102 bellard
                          : "cr0", "memory");
559 eb51d102 bellard
    return ret;
560 eb51d102 bellard
}
561 eb51d102 bellard
#endif
562 eb51d102 bellard
563 eb51d102 bellard
#ifdef __i386__
564 eb51d102 bellard
static inline int testandset (int *p)
565 eb51d102 bellard
{
566 eb51d102 bellard
    char ret;
567 eb51d102 bellard
    long int readval;
568 eb51d102 bellard
    
569 eb51d102 bellard
    __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
570 eb51d102 bellard
                          : "=q" (ret), "=m" (*p), "=a" (readval)
571 eb51d102 bellard
                          : "r" (1), "m" (*p), "a" (0)
572 eb51d102 bellard
                          : "memory");
573 eb51d102 bellard
    return ret;
574 eb51d102 bellard
}
575 eb51d102 bellard
#endif
576 eb51d102 bellard
577 eb51d102 bellard
#ifdef __s390__
578 eb51d102 bellard
static inline int testandset (int *p)
579 eb51d102 bellard
{
580 eb51d102 bellard
    int ret;
581 eb51d102 bellard
582 eb51d102 bellard
    __asm__ __volatile__ ("0: cs    %0,%1,0(%2)\n"
583 eb51d102 bellard
                          "   jl    0b"
584 eb51d102 bellard
                          : "=&d" (ret)
585 eb51d102 bellard
                          : "r" (1), "a" (p), "0" (*p) 
586 eb51d102 bellard
                          : "cc", "memory" );
587 eb51d102 bellard
    return ret;
588 eb51d102 bellard
}
589 eb51d102 bellard
#endif
590 eb51d102 bellard
591 eb51d102 bellard
#ifdef __alpha__
592 eb51d102 bellard
int testandset (int *p)
593 eb51d102 bellard
{
594 eb51d102 bellard
    int ret;
595 eb51d102 bellard
    unsigned long one;
596 eb51d102 bellard
597 eb51d102 bellard
    __asm__ __volatile__ ("0:        mov 1,%2\n"
598 eb51d102 bellard
                          "        ldl_l %0,%1\n"
599 eb51d102 bellard
                          "        stl_c %2,%1\n"
600 eb51d102 bellard
                          "        beq %2,1f\n"
601 eb51d102 bellard
                          ".subsection 2\n"
602 eb51d102 bellard
                          "1:        br 0b\n"
603 eb51d102 bellard
                          ".previous"
604 eb51d102 bellard
                          : "=r" (ret), "=m" (*p), "=r" (one)
605 eb51d102 bellard
                          : "m" (*p));
606 eb51d102 bellard
    return ret;
607 eb51d102 bellard
}
608 eb51d102 bellard
#endif
609 eb51d102 bellard
610 eb51d102 bellard
#ifdef __sparc__
611 eb51d102 bellard
static inline int testandset (int *p)
612 eb51d102 bellard
{
613 eb51d102 bellard
        int ret;
614 eb51d102 bellard
615 eb51d102 bellard
        __asm__ __volatile__("ldstub        [%1], %0"
616 eb51d102 bellard
                             : "=r" (ret)
617 eb51d102 bellard
                             : "r" (p)
618 eb51d102 bellard
                             : "memory");
619 eb51d102 bellard
620 eb51d102 bellard
        return (ret ? 1 : 0);
621 eb51d102 bellard
}
622 eb51d102 bellard
#endif
623 eb51d102 bellard
624 eb51d102 bellard
typedef int spinlock_t;
625 eb51d102 bellard
626 eb51d102 bellard
#define SPIN_LOCK_UNLOCKED 0
627 eb51d102 bellard
628 eb51d102 bellard
static inline void spin_lock(spinlock_t *lock)
629 eb51d102 bellard
{
630 eb51d102 bellard
    while (testandset(lock));
631 eb51d102 bellard
}
632 eb51d102 bellard
633 eb51d102 bellard
static inline void spin_unlock(spinlock_t *lock)
634 eb51d102 bellard
{
635 eb51d102 bellard
    *lock = 0;
636 eb51d102 bellard
}
637 eb51d102 bellard
638 eb51d102 bellard
static inline int spin_trylock(spinlock_t *lock)
639 eb51d102 bellard
{
640 eb51d102 bellard
    return !testandset(lock);
641 eb51d102 bellard
}
642 eb51d102 bellard
643 eb51d102 bellard
extern spinlock_t tb_lock;
644 eb51d102 bellard
645 367e86e8 bellard
#endif /* CPU_I386_H */