Statistics
| Branch: | Revision:

root / softmmu_header.h @ 6f06f178

History | View | Annotate | Download (6.5 kB)

1
/*
2
 *  Software MMU support
3
 *
4
 * Generate inline load/store functions for one MMU mode and data
5
 * size.
6
 *
7
 * Generate a store function as well as signed and unsigned loads. For
8
 * 32 and 64 bit cases, also generate floating point functions with
9
 * the same size.
10
 *
11
 * Not used directly but included from softmmu_exec.h and exec-all.h.
12
 *
13
 *  Copyright (c) 2003 Fabrice Bellard
14
 *
15
 * This library is free software; you can redistribute it and/or
16
 * modify it under the terms of the GNU Lesser General Public
17
 * License as published by the Free Software Foundation; either
18
 * version 2 of the License, or (at your option) any later version.
19
 *
20
 * This library is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23
 * Lesser General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Lesser General Public
26
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
27
 */
28
#if DATA_SIZE == 8
29
#define SUFFIX q
30
#define USUFFIX q
31
#define DATA_TYPE uint64_t
32
#elif DATA_SIZE == 4
33
#define SUFFIX l
34
#define USUFFIX l
35
#define DATA_TYPE uint32_t
36
#elif DATA_SIZE == 2
37
#define SUFFIX w
38
#define USUFFIX uw
39
#define DATA_TYPE uint16_t
40
#define DATA_STYPE int16_t
41
#elif DATA_SIZE == 1
42
#define SUFFIX b
43
#define USUFFIX ub
44
#define DATA_TYPE uint8_t
45
#define DATA_STYPE int8_t
46
#else
47
#error unsupported data size
48
#endif
49

    
50
#if ACCESS_TYPE < (NB_MMU_MODES)
51

    
52
#define CPU_MMU_INDEX ACCESS_TYPE
53
#define MMUSUFFIX _mmu
54

    
55
#elif ACCESS_TYPE == (NB_MMU_MODES)
56

    
57
#define CPU_MMU_INDEX (cpu_mmu_index(env))
58
#define MMUSUFFIX _mmu
59

    
60
#elif ACCESS_TYPE == (NB_MMU_MODES + 1)
61

    
62
#define CPU_MMU_INDEX (cpu_mmu_index(env))
63
#define MMUSUFFIX _cmmu
64

    
65
#else
66
#error invalid ACCESS_TYPE
67
#endif
68

    
69
#if DATA_SIZE == 8
70
#define RES_TYPE uint64_t
71
#else
72
#define RES_TYPE uint32_t
73
#endif
74

    
75
#if ACCESS_TYPE == (NB_MMU_MODES + 1)
76
#define ADDR_READ addr_code
77
#else
78
#define ADDR_READ addr_read
79
#endif
80

    
81
#ifndef CONFIG_TCG_PASS_AREG0
82
#define ENV_PARAM
83
#define ENV_VAR
84
#define CPU_PREFIX
85
#define HELPER_PREFIX __
86
#else
87
#define ENV_PARAM CPUArchState *env,
88
#define ENV_VAR env,
89
#define CPU_PREFIX cpu_
90
#define HELPER_PREFIX helper_
91
#endif
92

    
93
/* generic load/store macros */
94

    
95
static inline RES_TYPE
96
glue(glue(glue(CPU_PREFIX, ld), USUFFIX), MEMSUFFIX)(ENV_PARAM
97
                                                     target_ulong ptr)
98
{
99
    int page_index;
100
    RES_TYPE res;
101
    target_ulong addr;
102
    unsigned long physaddr;
103
    int mmu_idx;
104

    
105
    addr = ptr;
106
    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
107
    mmu_idx = CPU_MMU_INDEX;
108
    if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
109
                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
110
        res = glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_VAR
111
                                                                     addr,
112
                                                                     mmu_idx);
113
    } else {
114
        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
115
        res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
116
    }
117
    return res;
118
}
119

    
120
#if DATA_SIZE <= 2
121
static inline int
122
glue(glue(glue(CPU_PREFIX, lds), SUFFIX), MEMSUFFIX)(ENV_PARAM
123
                                                     target_ulong ptr)
124
{
125
    int res, page_index;
126
    target_ulong addr;
127
    unsigned long physaddr;
128
    int mmu_idx;
129

    
130
    addr = ptr;
131
    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
132
    mmu_idx = CPU_MMU_INDEX;
133
    if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
134
                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
135
        res = (DATA_STYPE)glue(glue(glue(HELPER_PREFIX, ld), SUFFIX),
136
                               MMUSUFFIX)(ENV_VAR addr, mmu_idx);
137
    } else {
138
        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
139
        res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
140
    }
141
    return res;
142
}
143
#endif
144

    
145
#if ACCESS_TYPE != (NB_MMU_MODES + 1)
146

    
147
/* generic store macro */
148

    
149
static inline void
150
glue(glue(glue(CPU_PREFIX, st), SUFFIX), MEMSUFFIX)(ENV_PARAM target_ulong ptr,
151
                                                    RES_TYPE v)
152
{
153
    int page_index;
154
    target_ulong addr;
155
    unsigned long physaddr;
156
    int mmu_idx;
157

    
158
    addr = ptr;
159
    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
160
    mmu_idx = CPU_MMU_INDEX;
161
    if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
162
                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
163
        glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_VAR addr, v,
164
                                                               mmu_idx);
165
    } else {
166
        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
167
        glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
168
    }
169
}
170

    
171
#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
172

    
173
#if ACCESS_TYPE != (NB_MMU_MODES + 1)
174

    
175
#if DATA_SIZE == 8
176
static inline float64 glue(glue(CPU_PREFIX, ldfq), MEMSUFFIX)(ENV_PARAM
177
                                                              target_ulong ptr)
178
{
179
    union {
180
        float64 d;
181
        uint64_t i;
182
    } u;
183
    u.i = glue(glue(CPU_PREFIX, ldq), MEMSUFFIX)(ENV_VAR ptr);
184
    return u.d;
185
}
186

    
187
static inline void glue(glue(CPU_PREFIX, stfq), MEMSUFFIX)(ENV_PARAM
188
                                                           target_ulong ptr,
189
                                                           float64 v)
190
{
191
    union {
192
        float64 d;
193
        uint64_t i;
194
    } u;
195
    u.d = v;
196
    glue(glue(CPU_PREFIX, stq), MEMSUFFIX)(ENV_VAR ptr, u.i);
197
}
198
#endif /* DATA_SIZE == 8 */
199

    
200
#if DATA_SIZE == 4
201
static inline float32 glue(glue(CPU_PREFIX, ldfl), MEMSUFFIX)(ENV_PARAM
202
                                                              target_ulong ptr)
203
{
204
    union {
205
        float32 f;
206
        uint32_t i;
207
    } u;
208
    u.i = glue(glue(CPU_PREFIX, ldl), MEMSUFFIX)(ENV_VAR ptr);
209
    return u.f;
210
}
211

    
212
static inline void glue(glue(CPU_PREFIX, stfl), MEMSUFFIX)(ENV_PARAM
213
                                                           target_ulong ptr,
214
                                                           float32 v)
215
{
216
    union {
217
        float32 f;
218
        uint32_t i;
219
    } u;
220
    u.f = v;
221
    glue(glue(CPU_PREFIX, stl), MEMSUFFIX)(ENV_VAR ptr, u.i);
222
}
223
#endif /* DATA_SIZE == 4 */
224

    
225
#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
226

    
227
#undef RES_TYPE
228
#undef DATA_TYPE
229
#undef DATA_STYPE
230
#undef SUFFIX
231
#undef USUFFIX
232
#undef DATA_SIZE
233
#undef CPU_MMU_INDEX
234
#undef MMUSUFFIX
235
#undef ADDR_READ
236
#undef ENV_PARAM
237
#undef ENV_VAR
238
#undef CPU_PREFIX
239
#undef HELPER_PREFIX