qemu/target-i386/mem_helper.c
<<
>>
Prefs
   1/*
   2 *  x86 memory access helpers
   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, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include "qemu/osdep.h"
  21#include "cpu.h"
  22#include "exec/helper-proto.h"
  23#include "exec/cpu_ldst.h"
  24
  25/* broken thread support */
  26
  27#if defined(CONFIG_USER_ONLY)
  28QemuMutex global_cpu_lock;
  29
  30void helper_lock(void)
  31{
  32    qemu_mutex_lock(&global_cpu_lock);
  33}
  34
  35void helper_unlock(void)
  36{
  37    qemu_mutex_unlock(&global_cpu_lock);
  38}
  39
  40void helper_lock_init(void)
  41{
  42    qemu_mutex_init(&global_cpu_lock);
  43}
  44#else
  45void helper_lock(void)
  46{
  47}
  48
  49void helper_unlock(void)
  50{
  51}
  52
  53void helper_lock_init(void)
  54{
  55}
  56#endif
  57
  58void helper_cmpxchg8b(CPUX86State *env, target_ulong a0)
  59{
  60    uint64_t d;
  61    int eflags;
  62
  63    eflags = cpu_cc_compute_all(env, CC_OP);
  64    d = cpu_ldq_data_ra(env, a0, GETPC());
  65    if (d == (((uint64_t)env->regs[R_EDX] << 32) | (uint32_t)env->regs[R_EAX])) {
  66        cpu_stq_data_ra(env, a0, ((uint64_t)env->regs[R_ECX] << 32)
  67                                  | (uint32_t)env->regs[R_EBX], GETPC());
  68        eflags |= CC_Z;
  69    } else {
  70        /* always do the store */
  71        cpu_stq_data_ra(env, a0, d, GETPC());
  72        env->regs[R_EDX] = (uint32_t)(d >> 32);
  73        env->regs[R_EAX] = (uint32_t)d;
  74        eflags &= ~CC_Z;
  75    }
  76    CC_SRC = eflags;
  77}
  78
  79#ifdef TARGET_X86_64
  80void helper_cmpxchg16b(CPUX86State *env, target_ulong a0)
  81{
  82    uint64_t d0, d1;
  83    int eflags;
  84
  85    if ((a0 & 0xf) != 0) {
  86        raise_exception_ra(env, EXCP0D_GPF, GETPC());
  87    }
  88    eflags = cpu_cc_compute_all(env, CC_OP);
  89    d0 = cpu_ldq_data_ra(env, a0, GETPC());
  90    d1 = cpu_ldq_data_ra(env, a0 + 8, GETPC());
  91    if (d0 == env->regs[R_EAX] && d1 == env->regs[R_EDX]) {
  92        cpu_stq_data_ra(env, a0, env->regs[R_EBX], GETPC());
  93        cpu_stq_data_ra(env, a0 + 8, env->regs[R_ECX], GETPC());
  94        eflags |= CC_Z;
  95    } else {
  96        /* always do the store */
  97        cpu_stq_data_ra(env, a0, d0, GETPC());
  98        cpu_stq_data_ra(env, a0 + 8, d1, GETPC());
  99        env->regs[R_EDX] = d1;
 100        env->regs[R_EAX] = d0;
 101        eflags &= ~CC_Z;
 102    }
 103    CC_SRC = eflags;
 104}
 105#endif
 106
 107void helper_boundw(CPUX86State *env, target_ulong a0, int v)
 108{
 109    int low, high;
 110
 111    low = cpu_ldsw_data_ra(env, a0, GETPC());
 112    high = cpu_ldsw_data_ra(env, a0 + 2, GETPC());
 113    v = (int16_t)v;
 114    if (v < low || v > high) {
 115        if (env->hflags & HF_MPX_EN_MASK) {
 116            env->bndcs_regs.sts = 0;
 117        }
 118        raise_exception_ra(env, EXCP05_BOUND, GETPC());
 119    }
 120}
 121
 122void helper_boundl(CPUX86State *env, target_ulong a0, int v)
 123{
 124    int low, high;
 125
 126    low = cpu_ldl_data_ra(env, a0, GETPC());
 127    high = cpu_ldl_data_ra(env, a0 + 4, GETPC());
 128    if (v < low || v > high) {
 129        if (env->hflags & HF_MPX_EN_MASK) {
 130            env->bndcs_regs.sts = 0;
 131        }
 132        raise_exception_ra(env, EXCP05_BOUND, GETPC());
 133    }
 134}
 135
 136#if !defined(CONFIG_USER_ONLY)
 137/* try to fill the TLB and return an exception if error. If retaddr is
 138 * NULL, it means that the function was called in C code (i.e. not
 139 * from generated code or from helper.c)
 140 */
 141/* XXX: fix it to restore all registers */
 142void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx,
 143              uintptr_t retaddr)
 144{
 145    int ret;
 146
 147    ret = x86_cpu_handle_mmu_fault(cs, addr, is_write, mmu_idx);
 148    if (ret) {
 149        X86CPU *cpu = X86_CPU(cs);
 150        CPUX86State *env = &cpu->env;
 151
 152        raise_exception_err_ra(env, cs->exception_index, env->error_code, retaddr);
 153    }
 154}
 155#endif
 156