cpu-i386.h 7.8 KB
Newer Older
B
bellard 已提交
1 2 3
/* NOTE: this header is included in op-i386.c where global register
   variable are used. Care must be used when including glibc headers.
 */
B
bellard 已提交
4 5 6
#ifndef CPU_I386_H
#define CPU_I386_H

B
bellard 已提交
7
#include "config.h"
B
bellard 已提交
8 9
#include <setjmp.h>

B
bellard 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
#define R_EAX 0
#define R_ECX 1
#define R_EDX 2
#define R_EBX 3
#define R_ESP 4
#define R_EBP 5
#define R_ESI 6
#define R_EDI 7

#define R_AL 0
#define R_CL 1
#define R_DL 2
#define R_BL 3
#define R_AH 4
#define R_CH 5
#define R_DH 6
#define R_BH 7

#define R_ES 0
#define R_CS 1
#define R_SS 2
#define R_DS 3
#define R_FS 4
#define R_GS 5

#define CC_C   	0x0001
#define CC_P 	0x0004
#define CC_A	0x0010
#define CC_Z	0x0040
#define CC_S    0x0080
#define CC_O    0x0800

#define TRAP_FLAG		0x0100
#define INTERRUPT_FLAG		0x0200
#define DIRECTION_FLAG		0x0400
#define IOPL_FLAG_MASK		0x3000
#define NESTED_FLAG		0x4000
#define BYTE_FL			0x8000	/* Intel reserved! */
#define RF_FLAG			0x10000
#define VM_FLAG			0x20000
/* AC				0x40000 */

B
bellard 已提交
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#define EXCP00_DIVZ	1
#define EXCP01_SSTP	2
#define EXCP02_NMI	3
#define EXCP03_INT3	4
#define EXCP04_INTO	5
#define EXCP05_BOUND	6
#define EXCP06_ILLOP	7
#define EXCP07_PREX	8
#define EXCP08_DBLE	9
#define EXCP09_XERR	10
#define EXCP0A_TSS	11
#define EXCP0B_NOSEG	12
#define EXCP0C_STACK	13
#define EXCP0D_GPF	14
#define EXCP0E_PAGE	15
#define EXCP10_COPR	17
#define EXCP11_ALGN	18
#define EXCP12_MCHK	19

#define EXCP_SIGNAL	256 /* async signal */

B
bellard 已提交
73 74 75 76 77 78 79 80 81
enum {
    CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
    CC_OP_EFLAGS,  /* all cc are explicitely computed, CC_SRC = flags */
    CC_OP_MUL, /* modify all flags, C, O = (CC_SRC != 0) */

    CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
    CC_OP_ADDW,
    CC_OP_ADDL,

B
bellard 已提交
82 83 84 85
    CC_OP_ADCB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
    CC_OP_ADCW,
    CC_OP_ADCL,

B
bellard 已提交
86 87 88 89
    CC_OP_SUBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
    CC_OP_SUBW,
    CC_OP_SUBL,

B
bellard 已提交
90 91 92 93
    CC_OP_SBBB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
    CC_OP_SBBW,
    CC_OP_SBBL,

B
bellard 已提交
94 95 96 97
    CC_OP_LOGICB, /* modify all flags, CC_DST = res */
    CC_OP_LOGICW,
    CC_OP_LOGICL,

B
bellard 已提交
98
    CC_OP_INCB, /* modify all flags except, CC_DST = res, CC_SRC = C */
B
bellard 已提交
99 100 101
    CC_OP_INCW,
    CC_OP_INCL,

B
bellard 已提交
102
    CC_OP_DECB, /* modify all flags except, CC_DST = res, CC_SRC = C  */
B
bellard 已提交
103 104 105 106 107 108 109
    CC_OP_DECW,
    CC_OP_DECL,

    CC_OP_SHLB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
    CC_OP_SHLW,
    CC_OP_SHLL,

B
bellard 已提交
110 111 112 113
    CC_OP_SARB, /* modify all flags, CC_DST = res, CC_SRC.lsb = C */
    CC_OP_SARW,
    CC_OP_SARL,

B
bellard 已提交
114 115 116
    CC_OP_NB,
};

B
bellard 已提交
117
#ifdef __i386__
B
bellard 已提交
118
#define USE_X86LDOUBLE
B
bellard 已提交
119 120 121 122 123 124 125 126
#endif

#ifdef USE_X86LDOUBLE
typedef long double CPU86_LDouble;
#else
typedef double CPU86_LDouble;
#endif

B
bellard 已提交
127 128 129 130 131 132 133 134 135 136 137 138 139 140
typedef struct SegmentCache {
    uint8_t *base;
    unsigned long limit;
    uint8_t seg_32bit;
} SegmentCache;

typedef struct SegmentDescriptorTable {
    uint8_t *base;
    unsigned long limit;
    /* this is the returned base when reading the register, just to
    avoid that the emulated program modifies it */
    unsigned long emu_base;
} SegmentDescriptorTable;

B
bellard 已提交
141
typedef struct CPUX86State {
B
bellard 已提交
142 143 144 145
    /* standard registers */
    uint32_t regs[8];
    uint32_t pc; /* cs_case + eip value */
    uint32_t eflags;
B
bellard 已提交
146 147

    /* emulator internal eflags handling */
B
bellard 已提交
148 149 150 151
    uint32_t cc_src;
    uint32_t cc_dst;
    uint32_t cc_op;
    int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
B
bellard 已提交
152

B
bellard 已提交
153 154 155 156
    /* FPU state */
    unsigned int fpstt; /* top of stack index */
    unsigned int fpus;
    unsigned int fpuc;
B
bellard 已提交
157 158 159
    uint8_t fptags[8];   /* 0 = valid, 1 = empty */
    CPU86_LDouble fpregs[8];    

B
bellard 已提交
160
    /* emulator internal variables */
B
bellard 已提交
161
    CPU86_LDouble ft0;
162
    
B
bellard 已提交
163 164 165 166 167 168 169 170 171 172
    /* segments */
    uint32_t segs[6]; /* selector values */
    SegmentCache seg_cache[6]; /* info taken from LDT/GDT */
    SegmentDescriptorTable gdt;
    SegmentDescriptorTable ldt;
    SegmentDescriptorTable idt;
    
    /* various CPU modes */
    int vm86;

B
bellard 已提交
173 174 175
    /* exception handling */
    jmp_buf jmp_env;
    int exception_index;
B
bellard 已提交
176
} CPUX86State;
B
bellard 已提交
177

B
bellard 已提交
178
/* all CPU memory access use these macros */
B
bellard 已提交
179 180 181 182 183 184 185 186 187 188
static inline int ldub(void *ptr)
{
    return *(uint8_t *)ptr;
}

static inline int ldsb(void *ptr)
{
    return *(int8_t *)ptr;
}

B
bellard 已提交
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
static inline void stb(void *ptr, int v)
{
    *(uint8_t *)ptr = v;
}

#ifdef WORDS_BIGENDIAN

/* conservative code for little endian unaligned accesses */
static inline int lduw(void *ptr)
{
#ifdef __powerpc__
    int val;
    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
    return val;
#else
    uint8_t *p = ptr;
    return p[0] | (p[1] << 8);
#endif
}

static inline int ldsw(void *ptr)
{
#ifdef __powerpc__
    int val;
    __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
    return (int16_t)val;
#else
    uint8_t *p = ptr;
    return (int16_t)(p[0] | (p[1] << 8));
#endif
}

static inline int ldl(void *ptr)
{
#ifdef __powerpc__
    int val;
    __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
    return val;
#else
    uint8_t *p = ptr;
    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
#endif
}

static inline uint64_t ldq(void *ptr)
{
    uint8_t *p = ptr;
    uint32_t v1, v2;
    v1 = ldl(p);
    v2 = ldl(p + 4);
    return v1 | ((uint64_t)v2 << 32);
}

static inline void stw(void *ptr, int v)
{
#ifdef __powerpc__
    __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
#else
    uint8_t *p = ptr;
    p[0] = v;
    p[1] = v >> 8;
#endif
}

static inline void stl(void *ptr, int v)
{
#ifdef __powerpc__
    __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
#else
    uint8_t *p = ptr;
    p[0] = v;
    p[1] = v >> 8;
    p[2] = v >> 16;
    p[3] = v >> 24;
#endif
}

static inline void stq(void *ptr, uint64_t v)
{
    uint8_t *p = ptr;
    stl(p, (uint32_t)v);
    stl(p + 4, v >> 32);
}

/* float access */

static inline float ldfl(void *ptr)
{
    union {
        float f;
        uint32_t i;
    } u;
    u.i = ldl(ptr);
    return u.f;
}

static inline double ldfq(void *ptr)
{
    union {
        double d;
        uint64_t i;
    } u;
    u.i = ldq(ptr);
    return u.d;
}

static inline void stfl(void *ptr, float v)
{
    union {
        float f;
        uint32_t i;
    } u;
    u.f = v;
    stl(ptr, u.i);
}

static inline void stfq(void *ptr, double v)
{
    union {
        double d;
        uint64_t i;
    } u;
    u.d = v;
    stq(ptr, u.i);
}

#else

B
bellard 已提交
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
static inline int lduw(void *ptr)
{
    return *(uint16_t *)ptr;
}

static inline int ldsw(void *ptr)
{
    return *(int16_t *)ptr;
}

static inline int ldl(void *ptr)
{
    return *(uint32_t *)ptr;
}

B
bellard 已提交
332 333 334 335
static inline uint64_t ldq(void *ptr)
{
    return *(uint64_t *)ptr;
}
B
bellard 已提交
336 337 338 339 340 341 342 343 344 345 346

static inline void stw(void *ptr, int v)
{
    *(uint16_t *)ptr = v;
}

static inline void stl(void *ptr, int v)
{
    *(uint32_t *)ptr = v;
}

B
bellard 已提交
347
static inline void stq(void *ptr, uint64_t v)
B
bellard 已提交
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
{
    *(uint64_t *)ptr = v;
}

/* float access */

static inline float ldfl(void *ptr)
{
    return *(float *)ptr;
}

static inline double ldfq(void *ptr)
{
    return *(double *)ptr;
}

static inline void stfl(void *ptr, float v)
{
    *(float *)ptr = v;
}

static inline void stfq(void *ptr, double v)
{
    *(double *)ptr = v;
}
B
bellard 已提交
373
#endif
B
bellard 已提交
374 375

#ifndef IN_OP_I386
B
bellard 已提交
376 377 378 379 380 381
void cpu_x86_outb(int addr, int val);
void cpu_x86_outw(int addr, int val);
void cpu_x86_outl(int addr, int val);
int cpu_x86_inb(int addr);
int cpu_x86_inw(int addr);
int cpu_x86_inl(int addr);
B
bellard 已提交
382
#endif
B
bellard 已提交
383

B
bellard 已提交
384 385 386 387
CPUX86State *cpu_x86_init(void);
int cpu_x86_exec(CPUX86State *s);
void cpu_x86_close(CPUX86State *s);

B
bellard 已提交
388 389 390
/* needed to load some predefinied segment registers */
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);

B
bellard 已提交
391
/* internal functions */
B
bellard 已提交
392 393 394 395

#define GEN_FLAG_CODE32_SHIFT 0
#define GEN_FLAG_ADDSEG_SHIFT 1
#define GEN_FLAG_ST_SHIFT     2
396
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
B
bellard 已提交
397 398
                     int *gen_code_size_ptr, uint8_t *pc_start, 
                     int flags);
B
bellard 已提交
399
void cpu_x86_tblocks_init(void);
B
bellard 已提交
400

B
bellard 已提交
401
#endif /* CPU_I386_H */