exec.h 8.4 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
 *
 *  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
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
B
bellard 已提交
18
 */
B
bellard 已提交
19
#include "config.h"
B
bellard 已提交
20 21
#include "dyngen-exec.h"

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

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

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

B
blueswir1 已提交
33
#include "qemu-common.h"
34
#include "qemu-log.h"
B
bellard 已提交
35

36
#undef EAX
B
bellard 已提交
37
#define EAX (env->regs[R_EAX])
38
#undef ECX
B
bellard 已提交
39
#define ECX (env->regs[R_ECX])
40
#undef EDX
B
bellard 已提交
41
#define EDX (env->regs[R_EDX])
42
#undef EBX
B
bellard 已提交
43
#define EBX (env->regs[R_EBX])
44
#undef ESP
B
bellard 已提交
45
#define ESP (env->regs[R_ESP])
46
#undef EBP
B
bellard 已提交
47
#define EBP (env->regs[R_EBP])
48
#undef ESI
B
bellard 已提交
49
#define ESI (env->regs[R_ESI])
50
#undef EDI
B
bellard 已提交
51
#define EDI (env->regs[R_EDI])
52
#undef EIP
53
#define EIP (env->eip)
B
bellard 已提交
54 55 56 57 58 59 60 61
#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 已提交
62 63
#define ST0    (env->fpregs[env->fpstt].d)
#define ST(n)  (env->fpregs[(env->fpstt + (n)) & 7].d)
B
bellard 已提交
64 65 66 67 68
#define ST1    ST(1)

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

B
blueswir1 已提交
69
/* op_helper.c */
70
void do_interrupt(int intno, int is_int, int error_code,
B
bellard 已提交
71
                  target_ulong next_eip, int is_hw);
72
void do_interrupt_user(int intno, int is_int, int error_code,
B
bellard 已提交
73
                       target_ulong next_eip);
M
malc 已提交
74 75
void QEMU_NORETURN raise_exception_err(int exception_index, int error_code);
void QEMU_NORETURN raise_exception(int exception_index);
B
bellard 已提交
76
void do_smm_enter(void);
B
bellard 已提交
77

78 79 80 81 82 83 84 85 86
/* 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 已提交
87 88
#include "helper.h"

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

94 95
#if !defined(CONFIG_USER_ONLY)

96
#include "softmmu_exec.h"
97 98 99

#endif /* !defined(CONFIG_USER_ONLY) */

B
bellard 已提交
100 101
#ifdef USE_X86LDOUBLE
/* use long double functions */
B
bellard 已提交
102 103
#define floatx_to_int32 floatx80_to_int32
#define floatx_to_int64 floatx80_to_int64
B
bellard 已提交
104 105
#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 已提交
106 107 108 109 110 111
#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 已提交
112 113 114
#define floatx_abs floatx80_abs
#define floatx_chs floatx80_chs
#define floatx_round_to_int floatx80_round_to_int
B
bellard 已提交
115 116
#define floatx_compare floatx80_compare
#define floatx_compare_quiet floatx80_compare_quiet
B
bellard 已提交
117
#else
B
bellard 已提交
118 119
#define floatx_to_int32 float64_to_int32
#define floatx_to_int64 float64_to_int64
B
bellard 已提交
120 121
#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 已提交
122 123 124 125 126 127
#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 已提交
128 129 130
#define floatx_abs float64_abs
#define floatx_chs float64_chs
#define floatx_round_to_int float64_round_to_int
B
bellard 已提交
131 132
#define floatx_compare float64_compare
#define floatx_compare_quiet float64_compare_quiet
B
bellard 已提交
133
#endif
B
bellard 已提交
134

B
bellard 已提交
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
#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;
167
#if !defined(HOST_WORDS_BIGENDIAN) && !defined(__arm__)
B
bellard 已提交
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 207 208
    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 已提交
209
static inline CPU86_LDouble helper_fldt(target_ulong ptr)
B
bellard 已提交
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
{
    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 已提交
230
static inline void helper_fstt(CPU86_LDouble f, target_ulong ptr)
B
bellard 已提交
231 232 233 234 235 236 237 238 239 240 241 242
{
    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);
}
243 244 245 246
#else

/* we use memory access macros */

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

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

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

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

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

B
bellard 已提交
267 268 269 270 271 272 273 274 275 276 277 278
#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

B
bellard 已提交
279 280
static inline uint32_t compute_eflags(void)
{
P
pbrook 已提交
281
    return env->eflags | helper_cc_compute_all(CC_OP) | (DF & DF_MASK);
B
bellard 已提交
282 283 284 285 286 287 288
}

/* 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));
289
    env->eflags = (env->eflags & ~update_mask) |
B
bellard 已提交
290
        (eflags & update_mask) | 0x2;
B
bellard 已提交
291 292
}

293 294 295 296 297 298 299
static inline int cpu_has_work(CPUState *env)
{
    int work;

    work = (env->interrupt_request & CPU_INTERRUPT_HARD) &&
           (env->eflags & IF_MASK);
    work |= env->interrupt_request & CPU_INTERRUPT_NMI;
300 301
    work |= env->interrupt_request & CPU_INTERRUPT_INIT;
    work |= env->interrupt_request & CPU_INTERRUPT_SIPI;
302 303 304 305

    return work;
}

306 307
static inline int cpu_halted(CPUState *env) {
    /* handle exit of HALTED state */
B
bellard 已提交
308
    if (!env->halted)
309 310
        return 0;
    /* disable halt condition */
311
    if (cpu_has_work(env)) {
B
bellard 已提交
312
        env->halted = 0;
313 314 315 316
        return 0;
    }
    return EXCP_HALTED;
}
T
ths 已提交
317

B
bellard 已提交
318 319 320 321 322 323 324 325 326 327 328
/* 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;
}