Statistics
| Branch: | Revision:

root / target-i386 / mem_helper.c @ feature-archipelago

History | View | Annotate | Download (3.8 kB)

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 "helper.h"
22

    
23
#if !defined(CONFIG_USER_ONLY)
24
#include "exec/softmmu_exec.h"
25
#endif /* !defined(CONFIG_USER_ONLY) */
26

    
27
/* broken thread support */
28

    
29
static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
30

    
31
void helper_lock(void)
32
{
33
    spin_lock(&global_cpu_lock);
34
}
35

    
36
void helper_unlock(void)
37
{
38
    spin_unlock(&global_cpu_lock);
39
}
40

    
41
void helper_cmpxchg8b(CPUX86State *env, target_ulong a0)
42
{
43
    uint64_t d;
44
    int eflags;
45

    
46
    eflags = cpu_cc_compute_all(env, CC_OP);
47
    d = cpu_ldq_data(env, a0);
48
    if (d == (((uint64_t)env->regs[R_EDX] << 32) | (uint32_t)env->regs[R_EAX])) {
49
        cpu_stq_data(env, a0, ((uint64_t)env->regs[R_ECX] << 32) | (uint32_t)env->regs[R_EBX]);
50
        eflags |= CC_Z;
51
    } else {
52
        /* always do the store */
53
        cpu_stq_data(env, a0, d);
54
        env->regs[R_EDX] = (uint32_t)(d >> 32);
55
        env->regs[R_EAX] = (uint32_t)d;
56
        eflags &= ~CC_Z;
57
    }
58
    CC_SRC = eflags;
59
}
60

    
61
#ifdef TARGET_X86_64
62
void helper_cmpxchg16b(CPUX86State *env, target_ulong a0)
63
{
64
    uint64_t d0, d1;
65
    int eflags;
66

    
67
    if ((a0 & 0xf) != 0) {
68
        raise_exception(env, EXCP0D_GPF);
69
    }
70
    eflags = cpu_cc_compute_all(env, CC_OP);
71
    d0 = cpu_ldq_data(env, a0);
72
    d1 = cpu_ldq_data(env, a0 + 8);
73
    if (d0 == env->regs[R_EAX] && d1 == env->regs[R_EDX]) {
74
        cpu_stq_data(env, a0, env->regs[R_EBX]);
75
        cpu_stq_data(env, a0 + 8, env->regs[R_ECX]);
76
        eflags |= CC_Z;
77
    } else {
78
        /* always do the store */
79
        cpu_stq_data(env, a0, d0);
80
        cpu_stq_data(env, a0 + 8, d1);
81
        env->regs[R_EDX] = d1;
82
        env->regs[R_EAX] = d0;
83
        eflags &= ~CC_Z;
84
    }
85
    CC_SRC = eflags;
86
}
87
#endif
88

    
89
void helper_boundw(CPUX86State *env, target_ulong a0, int v)
90
{
91
    int low, high;
92

    
93
    low = cpu_ldsw_data(env, a0);
94
    high = cpu_ldsw_data(env, a0 + 2);
95
    v = (int16_t)v;
96
    if (v < low || v > high) {
97
        raise_exception(env, EXCP05_BOUND);
98
    }
99
}
100

    
101
void helper_boundl(CPUX86State *env, target_ulong a0, int v)
102
{
103
    int low, high;
104

    
105
    low = cpu_ldl_data(env, a0);
106
    high = cpu_ldl_data(env, a0 + 4);
107
    if (v < low || v > high) {
108
        raise_exception(env, EXCP05_BOUND);
109
    }
110
}
111

    
112
#if !defined(CONFIG_USER_ONLY)
113

    
114
#define MMUSUFFIX _mmu
115

    
116
#define SHIFT 0
117
#include "exec/softmmu_template.h"
118

    
119
#define SHIFT 1
120
#include "exec/softmmu_template.h"
121

    
122
#define SHIFT 2
123
#include "exec/softmmu_template.h"
124

    
125
#define SHIFT 3
126
#include "exec/softmmu_template.h"
127

    
128
#endif
129

    
130
#if !defined(CONFIG_USER_ONLY)
131
/* try to fill the TLB and return an exception if error. If retaddr is
132
   NULL, it means that the function was called in C code (i.e. not
133
   from generated code or from helper.c) */
134
/* XXX: fix it to restore all registers */
135
void tlb_fill(CPUX86State *env, target_ulong addr, int is_write, int mmu_idx,
136
              uintptr_t retaddr)
137
{
138
    int ret;
139

    
140
    ret = cpu_x86_handle_mmu_fault(env, addr, is_write, mmu_idx);
141
    if (ret) {
142
        if (retaddr) {
143
            /* now we have a real cpu fault */
144
            cpu_restore_state(env, retaddr);
145
        }
146
        raise_exception_err(env, env->exception_index, env->error_code);
147
    }
148
}
149
#endif