exec.h 9.6 KB
Newer Older
B
bellard 已提交
1
/*
2
 *  i386 execution defines
B
bellard 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 *  Copyright (c) 2003 Fabrice Bellard
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
B
bellard 已提交
20
#include "config.h"
B
bellard 已提交
21 22
#include "dyngen-exec.h"

B
bellard 已提交
23 24 25 26 27 28 29
/* XXX: factorize this mess */
#ifdef TARGET_X86_64
#define TARGET_LONG_BITS 64
#else
#define TARGET_LONG_BITS 32
#endif

B
bellard 已提交
30 31
#include "cpu-defs.h"

B
bellard 已提交
32
register struct CPUX86State *env asm(AREG0);
B
bellard 已提交
33

34
#include "qemu-log.h"
B
bellard 已提交
35 36 37 38 39 40 41 42 43

#define EAX (env->regs[R_EAX])
#define ECX (env->regs[R_ECX])
#define EDX (env->regs[R_EDX])
#define EBX (env->regs[R_EBX])
#define ESP (env->regs[R_ESP])
#define EBP (env->regs[R_EBP])
#define ESI (env->regs[R_ESI])
#define EDI (env->regs[R_EDI])
44
#define EIP (env->eip)
B
bellard 已提交
45 46 47 48 49 50 51 52
#define DF  (env->df)

#define CC_SRC (env->cc_src)
#define CC_DST (env->cc_dst)
#define CC_OP  (env->cc_op)

/* float macros */
#define FT0    (env->ft0)
B
bellard 已提交
53 54
#define ST0    (env->fpregs[env->fpstt].d)
#define ST(n)  (env->fpregs[(env->fpstt + (n)) & 7].d)
B
bellard 已提交
55 56 57 58 59
#define ST1    ST(1)

#include "cpu.h"
#include "exec-all.h"

B
bellard 已提交
60
void cpu_x86_update_cr3(CPUX86State *env, target_ulong new_cr3);
61
void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
62
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
63
                             int is_write, int mmu_idx, int is_softmmu);
B
bellard 已提交
64 65
void __hidden cpu_lock(void);
void __hidden cpu_unlock(void);
66
void do_interrupt(int intno, int is_int, int error_code,
B
bellard 已提交
67
                  target_ulong next_eip, int is_hw);
68
void do_interrupt_user(int intno, int is_int, int error_code,
B
bellard 已提交
69
                       target_ulong next_eip);
70
void raise_interrupt(int intno, int is_int, int error_code,
71
                     int next_eip_addend);
B
bellard 已提交
72 73
void raise_exception_err(int exception_index, int error_code);
void raise_exception(int exception_index);
B
bellard 已提交
74
void do_smm_enter(void);
B
bellard 已提交
75

76 77 78 79 80 81 82 83 84
/* n must be a constant to be efficient */
static inline target_long lshift(target_long x, int n)
{
    if (n >= 0)
        return x << n;
    else
        return x >> (-n);
}

B
bellard 已提交
85 86
#include "helper.h"

87 88 89 90
static inline void svm_check_intercept(uint32_t type)
{
    helper_svm_check_intercept_param(type, 0);
}
B
bellard 已提交
91

92 93
#if !defined(CONFIG_USER_ONLY)

94
#include "softmmu_exec.h"
95 96 97

#endif /* !defined(CONFIG_USER_ONLY) */

B
bellard 已提交
98 99
#ifdef USE_X86LDOUBLE
/* use long double functions */
B
bellard 已提交
100 101
#define floatx_to_int32 floatx80_to_int32
#define floatx_to_int64 floatx80_to_int64
B
bellard 已提交
102 103
#define floatx_to_int32_round_to_zero floatx80_to_int32_round_to_zero
#define floatx_to_int64_round_to_zero floatx80_to_int64_round_to_zero
B
bellard 已提交
104 105 106 107 108 109
#define int32_to_floatx int32_to_floatx80
#define int64_to_floatx int64_to_floatx80
#define float32_to_floatx float32_to_floatx80
#define float64_to_floatx float64_to_floatx80
#define floatx_to_float32 floatx80_to_float32
#define floatx_to_float64 floatx80_to_float64
B
bellard 已提交
110 111 112
#define floatx_abs floatx80_abs
#define floatx_chs floatx80_chs
#define floatx_round_to_int floatx80_round_to_int
B
bellard 已提交
113 114
#define floatx_compare floatx80_compare
#define floatx_compare_quiet floatx80_compare_quiet
B
bellard 已提交
115
#else
B
bellard 已提交
116 117
#define floatx_to_int32 float64_to_int32
#define floatx_to_int64 float64_to_int64
B
bellard 已提交
118 119
#define floatx_to_int32_round_to_zero float64_to_int32_round_to_zero
#define floatx_to_int64_round_to_zero float64_to_int64_round_to_zero
B
bellard 已提交
120 121 122 123 124 125
#define int32_to_floatx int32_to_float64
#define int64_to_floatx int64_to_float64
#define float32_to_floatx float32_to_float64
#define float64_to_floatx(x, e) (x)
#define floatx_to_float32 float64_to_float32
#define floatx_to_float64(x, e) (x)
B
bellard 已提交
126 127 128
#define floatx_abs float64_abs
#define floatx_chs float64_chs
#define floatx_round_to_int float64_round_to_int
B
bellard 已提交
129 130
#define floatx_compare float64_compare
#define floatx_compare_quiet float64_compare_quiet
B
bellard 已提交
131
#endif
B
bellard 已提交
132

B
bellard 已提交
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
#define RC_MASK         0xc00
#define RC_NEAR		0x000
#define RC_DOWN		0x400
#define RC_UP		0x800
#define RC_CHOP		0xc00

#define MAXTAN 9223372036854775808.0

#ifdef USE_X86LDOUBLE

/* only for x86 */
typedef union {
    long double d;
    struct {
        unsigned long long lower;
        unsigned short upper;
    } l;
} CPU86_LDoubleU;

/* the following deal with x86 long double-precision numbers */
#define MAXEXPD 0x7fff
#define EXPBIAS 16383
#define EXPD(fp)	(fp.l.upper & 0x7fff)
#define SIGND(fp)	((fp.l.upper) & 0x8000)
#define MANTD(fp)       (fp.l.lower)
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS

#else

/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
typedef union {
    double d;
#if !defined(WORDS_BIGENDIAN) && !defined(__arm__)
    struct {
        uint32_t lower;
        int32_t upper;
    } l;
#else
    struct {
        int32_t upper;
        uint32_t lower;
    } l;
#endif
#ifndef __arm__
    int64_t ll;
#endif
} CPU86_LDoubleU;

/* the following deal with IEEE double-precision numbers */
#define MAXEXPD 0x7ff
#define EXPBIAS 1023
#define EXPD(fp)	(((fp.l.upper) >> 20) & 0x7FF)
#define SIGND(fp)	((fp.l.upper) & 0x80000000)
#ifdef __arm__
#define MANTD(fp)	(fp.l.lower | ((uint64_t)(fp.l.upper & ((1 << 20) - 1)) << 32))
#else
#define MANTD(fp)	(fp.ll & ((1LL << 52) - 1))
#endif
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
#endif

static inline void fpush(void)
{
    env->fpstt = (env->fpstt - 1) & 7;
    env->fptags[env->fpstt] = 0; /* validate stack entry */
}

static inline void fpop(void)
{
    env->fptags[env->fpstt] = 1; /* invvalidate stack entry */
    env->fpstt = (env->fpstt + 1) & 7;
}

#ifndef USE_X86LDOUBLE
B
bellard 已提交
207
static inline CPU86_LDouble helper_fldt(target_ulong ptr)
B
bellard 已提交
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
{
    CPU86_LDoubleU temp;
    int upper, e;
    uint64_t ll;

    /* mantissa */
    upper = lduw(ptr + 8);
    /* XXX: handle overflow ? */
    e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
    e |= (upper >> 4) & 0x800; /* sign */
    ll = (ldq(ptr) >> 11) & ((1LL << 52) - 1);
#ifdef __arm__
    temp.l.upper = (e << 20) | (ll >> 32);
    temp.l.lower = ll;
#else
    temp.ll = ll | ((uint64_t)e << 52);
#endif
    return temp.d;
}

B
bellard 已提交
228
static inline void helper_fstt(CPU86_LDouble f, target_ulong ptr)
B
bellard 已提交
229 230 231 232 233 234 235 236 237 238 239 240
{
    CPU86_LDoubleU temp;
    int e;

    temp.d = f;
    /* mantissa */
    stq(ptr, (MANTD(temp) << 11) | (1LL << 63));
    /* exponent + sign */
    e = EXPD(temp) - EXPBIAS + 16383;
    e |= SIGND(temp) >> 16;
    stw(ptr + 8, e);
}
241 242 243 244
#else

/* we use memory access macros */

B
bellard 已提交
245
static inline CPU86_LDouble helper_fldt(target_ulong ptr)
246 247 248 249 250 251 252 253
{
    CPU86_LDoubleU temp;

    temp.l.lower = ldq(ptr);
    temp.l.upper = lduw(ptr + 8);
    return temp.d;
}

B
bellard 已提交
254
static inline void helper_fstt(CPU86_LDouble f, target_ulong ptr)
255 256
{
    CPU86_LDoubleU temp;
257

258 259 260 261 262 263
    temp.d = f;
    stq(ptr, temp.l.lower);
    stw(ptr + 8, temp.l.upper);
}

#endif /* USE_X86LDOUBLE */
B
bellard 已提交
264

B
bellard 已提交
265 266 267 268 269 270 271 272 273 274 275 276
#define FPUS_IE (1 << 0)
#define FPUS_DE (1 << 1)
#define FPUS_ZE (1 << 2)
#define FPUS_OE (1 << 3)
#define FPUS_UE (1 << 4)
#define FPUS_PE (1 << 5)
#define FPUS_SF (1 << 6)
#define FPUS_SE (1 << 7)
#define FPUS_B  (1 << 15)

#define FPUC_EM 0x3f

277
extern const CPU86_LDouble f15rk[7];
B
bellard 已提交
278

B
bellard 已提交
279
void fpu_raise_exception(void);
B
bellard 已提交
280 281
void restore_native_fp_state(CPUState *env);
void save_native_fp_state(CPUState *env);
B
bellard 已提交
282

283 284 285
extern const uint8_t parity_table[256];
extern const uint8_t rclw_table[32];
extern const uint8_t rclb_table[32];
B
bellard 已提交
286 287 288

static inline uint32_t compute_eflags(void)
{
P
pbrook 已提交
289
    return env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
B
bellard 已提交
290 291 292 293 294 295 296
}

/* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */
static inline void load_eflags(int eflags, int update_mask)
{
    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
    DF = 1 - (2 * ((eflags >> 10) & 1));
297
    env->eflags = (env->eflags & ~update_mask) |
B
bellard 已提交
298
        (eflags & update_mask) | 0x2;
B
bellard 已提交
299 300
}

B
bellard 已提交
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
static inline void env_to_regs(void)
{
#ifdef reg_EAX
    EAX = env->regs[R_EAX];
#endif
#ifdef reg_ECX
    ECX = env->regs[R_ECX];
#endif
#ifdef reg_EDX
    EDX = env->regs[R_EDX];
#endif
#ifdef reg_EBX
    EBX = env->regs[R_EBX];
#endif
#ifdef reg_ESP
    ESP = env->regs[R_ESP];
#endif
#ifdef reg_EBP
    EBP = env->regs[R_EBP];
#endif
#ifdef reg_ESI
    ESI = env->regs[R_ESI];
#endif
#ifdef reg_EDI
    EDI = env->regs[R_EDI];
#endif
}

static inline void regs_to_env(void)
{
#ifdef reg_EAX
    env->regs[R_EAX] = EAX;
#endif
#ifdef reg_ECX
    env->regs[R_ECX] = ECX;
#endif
#ifdef reg_EDX
    env->regs[R_EDX] = EDX;
#endif
#ifdef reg_EBX
    env->regs[R_EBX] = EBX;
#endif
#ifdef reg_ESP
    env->regs[R_ESP] = ESP;
#endif
#ifdef reg_EBP
    env->regs[R_EBP] = EBP;
#endif
#ifdef reg_ESI
    env->regs[R_ESI] = ESI;
#endif
#ifdef reg_EDI
    env->regs[R_EDI] = EDI;
#endif
}
356 357 358

static inline int cpu_halted(CPUState *env) {
    /* handle exit of HALTED state */
B
bellard 已提交
359
    if (!env->halted)
360 361
        return 0;
    /* disable halt condition */
A
aurel32 已提交
362 363 364
    if (((env->interrupt_request & CPU_INTERRUPT_HARD) &&
         (env->eflags & IF_MASK)) ||
        (env->interrupt_request & CPU_INTERRUPT_NMI)) {
B
bellard 已提交
365
        env->halted = 0;
366 367 368 369
        return 0;
    }
    return EXCP_HALTED;
}
T
ths 已提交
370

B
bellard 已提交
371 372 373 374 375 376 377 378 379 380 381
/* load efer and update the corresponding hflags. XXX: do consistency
   checks with cpuid bits ? */
static inline void cpu_load_efer(CPUState *env, uint64_t val)
{
    env->efer = val;
    env->hflags &= ~(HF_LMA_MASK | HF_SVME_MASK);
    if (env->efer & MSR_EFER_LMA)
        env->hflags |= HF_LMA_MASK;
    if (env->efer & MSR_EFER_SVME)
        env->hflags |= HF_SVME_MASK;
}