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