Statistics
| Branch: | Revision:

root / cpu-i386.h @ 3ef693a0

History | View | Annotate | Download (8.9 kB)

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 */