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