]> git.proxmox.com Git - qemu.git/blob - cpu-i386.h
glibc2.2 fixes - more command line options - misc doc fixes
[qemu.git] / 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 this signal handler from your 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 */