Statistics
| Branch: | Revision:

root / softmmu_header.h @ 8167ee88

History | View | Annotate | Download (9.4 kB)

1
/*
2
 *  Software MMU support
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
#if DATA_SIZE == 8
20
#define SUFFIX q
21
#define USUFFIX q
22
#define DATA_TYPE uint64_t
23
#elif DATA_SIZE == 4
24
#define SUFFIX l
25
#define USUFFIX l
26
#define DATA_TYPE uint32_t
27
#elif DATA_SIZE == 2
28
#define SUFFIX w
29
#define USUFFIX uw
30
#define DATA_TYPE uint16_t
31
#define DATA_STYPE int16_t
32
#elif DATA_SIZE == 1
33
#define SUFFIX b
34
#define USUFFIX ub
35
#define DATA_TYPE uint8_t
36
#define DATA_STYPE int8_t
37
#else
38
#error unsupported data size
39
#endif
40

    
41
#if ACCESS_TYPE < (NB_MMU_MODES)
42

    
43
#define CPU_MMU_INDEX ACCESS_TYPE
44
#define MMUSUFFIX _mmu
45

    
46
#elif ACCESS_TYPE == (NB_MMU_MODES)
47

    
48
#define CPU_MMU_INDEX (cpu_mmu_index(env))
49
#define MMUSUFFIX _mmu
50

    
51
#elif ACCESS_TYPE == (NB_MMU_MODES + 1)
52

    
53
#define CPU_MMU_INDEX (cpu_mmu_index(env))
54
#define MMUSUFFIX _cmmu
55

    
56
#else
57
#error invalid ACCESS_TYPE
58
#endif
59

    
60
#if DATA_SIZE == 8
61
#define RES_TYPE uint64_t
62
#else
63
#define RES_TYPE int
64
#endif
65

    
66
#if ACCESS_TYPE == (NB_MMU_MODES + 1)
67
#define ADDR_READ addr_code
68
#else
69
#define ADDR_READ addr_read
70
#endif
71

    
72
#if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
73
    (ACCESS_TYPE < NB_MMU_MODES) && defined(ASM_SOFTMMU)
74

    
75
static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
76
{
77
    int res;
78

    
79
    asm volatile ("movl %1, %%edx\n"
80
                  "movl %1, %%eax\n"
81
                  "shrl %3, %%edx\n"
82
                  "andl %4, %%eax\n"
83
                  "andl %2, %%edx\n"
84
                  "leal %5(%%edx, %%ebp), %%edx\n"
85
                  "cmpl (%%edx), %%eax\n"
86
                  "movl %1, %%eax\n"
87
                  "je 1f\n"
88
                  "movl %6, %%edx\n"
89
                  "call %7\n"
90
                  "movl %%eax, %0\n"
91
                  "jmp 2f\n"
92
                  "1:\n"
93
                  "addl 12(%%edx), %%eax\n"
94
#if DATA_SIZE == 1
95
                  "movzbl (%%eax), %0\n"
96
#elif DATA_SIZE == 2
97
                  "movzwl (%%eax), %0\n"
98
#elif DATA_SIZE == 4
99
                  "movl (%%eax), %0\n"
100
#else
101
#error unsupported size
102
#endif
103
                  "2:\n"
104
                  : "=r" (res)
105
                  : "r" (ptr),
106
                  "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
107
                  "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
108
                  "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
109
                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_read)),
110
                  "i" (CPU_MMU_INDEX),
111
                  "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
112
                  : "%eax", "%ecx", "%edx", "memory", "cc");
113
    return res;
114
}
115

    
116
#if DATA_SIZE <= 2
117
static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
118
{
119
    int res;
120

    
121
    asm volatile ("movl %1, %%edx\n"
122
                  "movl %1, %%eax\n"
123
                  "shrl %3, %%edx\n"
124
                  "andl %4, %%eax\n"
125
                  "andl %2, %%edx\n"
126
                  "leal %5(%%edx, %%ebp), %%edx\n"
127
                  "cmpl (%%edx), %%eax\n"
128
                  "movl %1, %%eax\n"
129
                  "je 1f\n"
130
                  "movl %6, %%edx\n"
131
                  "call %7\n"
132
#if DATA_SIZE == 1
133
                  "movsbl %%al, %0\n"
134
#elif DATA_SIZE == 2
135
                  "movswl %%ax, %0\n"
136
#else
137
#error unsupported size
138
#endif
139
                  "jmp 2f\n"
140
                  "1:\n"
141
                  "addl 12(%%edx), %%eax\n"
142
#if DATA_SIZE == 1
143
                  "movsbl (%%eax), %0\n"
144
#elif DATA_SIZE == 2
145
                  "movswl (%%eax), %0\n"
146
#else
147
#error unsupported size
148
#endif
149
                  "2:\n"
150
                  : "=r" (res)
151
                  : "r" (ptr),
152
                  "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
153
                  "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
154
                  "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
155
                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_read)),
156
                  "i" (CPU_MMU_INDEX),
157
                  "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
158
                  : "%eax", "%ecx", "%edx", "memory", "cc");
159
    return res;
160
}
161
#endif
162

    
163
static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
164
{
165
    asm volatile ("movl %0, %%edx\n"
166
                  "movl %0, %%eax\n"
167
                  "shrl %3, %%edx\n"
168
                  "andl %4, %%eax\n"
169
                  "andl %2, %%edx\n"
170
                  "leal %5(%%edx, %%ebp), %%edx\n"
171
                  "cmpl (%%edx), %%eax\n"
172
                  "movl %0, %%eax\n"
173
                  "je 1f\n"
174
#if DATA_SIZE == 1
175
                  "movzbl %b1, %%edx\n"
176
#elif DATA_SIZE == 2
177
                  "movzwl %w1, %%edx\n"
178
#elif DATA_SIZE == 4
179
                  "movl %1, %%edx\n"
180
#else
181
#error unsupported size
182
#endif
183
                  "movl %6, %%ecx\n"
184
                  "call %7\n"
185
                  "jmp 2f\n"
186
                  "1:\n"
187
                  "addl 8(%%edx), %%eax\n"
188
#if DATA_SIZE == 1
189
                  "movb %b1, (%%eax)\n"
190
#elif DATA_SIZE == 2
191
                  "movw %w1, (%%eax)\n"
192
#elif DATA_SIZE == 4
193
                  "movl %1, (%%eax)\n"
194
#else
195
#error unsupported size
196
#endif
197
                  "2:\n"
198
                  :
199
                  : "r" (ptr),
200
#if DATA_SIZE == 1
201
                  "q" (v),
202
#else
203
                  "r" (v),
204
#endif
205
                  "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS),
206
                  "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS),
207
                  "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
208
                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MMU_INDEX][0].addr_write)),
209
                  "i" (CPU_MMU_INDEX),
210
                  "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
211
                  : "%eax", "%ecx", "%edx", "memory", "cc");
212
}
213

    
214
#else
215

    
216
/* generic load/store macros */
217

    
218
static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
219
{
220
    int page_index;
221
    RES_TYPE res;
222
    target_ulong addr;
223
    unsigned long physaddr;
224
    int mmu_idx;
225

    
226
    addr = ptr;
227
    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
228
    mmu_idx = CPU_MMU_INDEX;
229
    if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
230
                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
231
        res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
232
    } else {
233
        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
234
        res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
235
    }
236
    return res;
237
}
238

    
239
#if DATA_SIZE <= 2
240
static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
241
{
242
    int res, page_index;
243
    target_ulong addr;
244
    unsigned long physaddr;
245
    int mmu_idx;
246

    
247
    addr = ptr;
248
    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
249
    mmu_idx = CPU_MMU_INDEX;
250
    if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
251
                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
252
        res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, mmu_idx);
253
    } else {
254
        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
255
        res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
256
    }
257
    return res;
258
}
259
#endif
260

    
261
#if ACCESS_TYPE != (NB_MMU_MODES + 1)
262

    
263
/* generic store macro */
264

    
265
static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
266
{
267
    int page_index;
268
    target_ulong addr;
269
    unsigned long physaddr;
270
    int mmu_idx;
271

    
272
    addr = ptr;
273
    page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
274
    mmu_idx = CPU_MMU_INDEX;
275
    if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
276
                 (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
277
        glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, mmu_idx);
278
    } else {
279
        physaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
280
        glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
281
    }
282
}
283

    
284
#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
285

    
286
#endif /* !asm */
287

    
288
#if ACCESS_TYPE != (NB_MMU_MODES + 1)
289

    
290
#if DATA_SIZE == 8
291
static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr)
292
{
293
    union {
294
        float64 d;
295
        uint64_t i;
296
    } u;
297
    u.i = glue(ldq, MEMSUFFIX)(ptr);
298
    return u.d;
299
}
300

    
301
static inline void glue(stfq, MEMSUFFIX)(target_ulong ptr, float64 v)
302
{
303
    union {
304
        float64 d;
305
        uint64_t i;
306
    } u;
307
    u.d = v;
308
    glue(stq, MEMSUFFIX)(ptr, u.i);
309
}
310
#endif /* DATA_SIZE == 8 */
311

    
312
#if DATA_SIZE == 4
313
static inline float32 glue(ldfl, MEMSUFFIX)(target_ulong ptr)
314
{
315
    union {
316
        float32 f;
317
        uint32_t i;
318
    } u;
319
    u.i = glue(ldl, MEMSUFFIX)(ptr);
320
    return u.f;
321
}
322

    
323
static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
324
{
325
    union {
326
        float32 f;
327
        uint32_t i;
328
    } u;
329
    u.f = v;
330
    glue(stl, MEMSUFFIX)(ptr, u.i);
331
}
332
#endif /* DATA_SIZE == 4 */
333

    
334
#endif /* ACCESS_TYPE != (NB_MMU_MODES + 1) */
335

    
336
#undef RES_TYPE
337
#undef DATA_TYPE
338
#undef DATA_STYPE
339
#undef SUFFIX
340
#undef USUFFIX
341
#undef DATA_SIZE
342
#undef CPU_MMU_INDEX
343
#undef MMUSUFFIX
344
#undef ADDR_READ