Statistics
| Branch: | Revision:

root / softmmu_header.h @ 83f64091

History | View | Annotate | Download (10.7 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, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 */
20
#if DATA_SIZE == 8
21
#define SUFFIX q
22
#define USUFFIX q
23
#define DATA_TYPE uint64_t
24
#elif DATA_SIZE == 4
25
#define SUFFIX l
26
#define USUFFIX l
27
#define DATA_TYPE uint32_t
28
#elif DATA_SIZE == 2
29
#define SUFFIX w
30
#define USUFFIX uw
31
#define DATA_TYPE uint16_t
32
#define DATA_STYPE int16_t
33
#elif DATA_SIZE == 1
34
#define SUFFIX b
35
#define USUFFIX ub
36
#define DATA_TYPE uint8_t
37
#define DATA_STYPE int8_t
38
#else
39
#error unsupported data size
40
#endif
41

    
42
#if ACCESS_TYPE == 0
43

    
44
#define CPU_MEM_INDEX 0
45
#define MMUSUFFIX _mmu
46

    
47
#elif ACCESS_TYPE == 1
48

    
49
#define CPU_MEM_INDEX 1
50
#define MMUSUFFIX _mmu
51

    
52
#elif ACCESS_TYPE == 2
53

    
54
#ifdef TARGET_I386
55
#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
56
#elif defined (TARGET_PPC)
57
#define CPU_MEM_INDEX (msr_pr)
58
#elif defined (TARGET_MIPS)
59
#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
60
#elif defined (TARGET_SPARC)
61
#define CPU_MEM_INDEX ((env->psrs) == 0)
62
#elif defined (TARGET_ARM)
63
#define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
64
#elif defined (TARGET_SH4)
65
#define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
66
#else
67
#error unsupported CPU
68
#endif
69
#define MMUSUFFIX _mmu
70

    
71
#elif ACCESS_TYPE == 3
72

    
73
#ifdef TARGET_I386
74
#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
75
#elif defined (TARGET_PPC)
76
#define CPU_MEM_INDEX (msr_pr)
77
#elif defined (TARGET_MIPS)
78
#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
79
#elif defined (TARGET_SPARC)
80
#define CPU_MEM_INDEX ((env->psrs) == 0)
81
#elif defined (TARGET_ARM)
82
#define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
83
#elif defined (TARGET_SH4)
84
#define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
85
#else
86
#error unsupported CPU
87
#endif
88
#define MMUSUFFIX _cmmu
89

    
90
#else
91
#error invalid ACCESS_TYPE
92
#endif
93

    
94
#if DATA_SIZE == 8
95
#define RES_TYPE uint64_t
96
#else
97
#define RES_TYPE int
98
#endif
99

    
100
#if ACCESS_TYPE == 3
101
#define ADDR_READ addr_code
102
#else
103
#define ADDR_READ addr_read
104
#endif
105

    
106
DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
107
                                                         int is_user);
108
void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int is_user);
109

    
110
#if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
111
    (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU)
112

    
113
#define CPU_TLB_ENTRY_BITS 4
114

    
115
static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
116
{
117
    int res;
118

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

    
157
#if DATA_SIZE <= 2
158
static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
159
{
160
    int res;
161

    
162
    asm volatile ("movl %1, %%edx\n"
163
                  "movl %1, %%eax\n"
164
                  "shrl %3, %%edx\n"
165
                  "andl %4, %%eax\n"
166
                  "andl %2, %%edx\n"
167
                  "leal %5(%%edx, %%ebp), %%edx\n"
168
                  "cmpl (%%edx), %%eax\n"
169
                  "movl %1, %%eax\n"
170
                  "je 1f\n"
171
                  "pushl %6\n"
172
                  "call %7\n"
173
                  "popl %%edx\n"
174
#if DATA_SIZE == 1
175
                  "movsbl %%al, %0\n"
176
#elif DATA_SIZE == 2
177
                  "movswl %%ax, %0\n"
178
#else
179
#error unsupported size
180
#endif
181
                  "jmp 2f\n"
182
                  "1:\n"
183
                  "addl 12(%%edx), %%eax\n"
184
#if DATA_SIZE == 1
185
                  "movsbl (%%eax), %0\n"
186
#elif DATA_SIZE == 2
187
                  "movswl (%%eax), %0\n"
188
#else
189
#error unsupported size
190
#endif
191
                  "2:\n"
192
                  : "=r" (res)
193
                  : "r" (ptr), 
194
                  "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS), 
195
                  "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS), 
196
                  "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
197
                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_read)),
198
                  "i" (CPU_MEM_INDEX),
199
                  "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
200
                  : "%eax", "%ecx", "%edx", "memory", "cc");
201
    return res;
202
}
203
#endif
204

    
205
static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
206
{
207
    asm volatile ("movl %0, %%edx\n"
208
                  "movl %0, %%eax\n"
209
                  "shrl %3, %%edx\n"
210
                  "andl %4, %%eax\n"
211
                  "andl %2, %%edx\n"
212
                  "leal %5(%%edx, %%ebp), %%edx\n"
213
                  "cmpl (%%edx), %%eax\n"
214
                  "movl %0, %%eax\n"
215
                  "je 1f\n"
216
#if DATA_SIZE == 1
217
                  "movzbl %b1, %%edx\n"
218
#elif DATA_SIZE == 2
219
                  "movzwl %w1, %%edx\n"
220
#elif DATA_SIZE == 4
221
                  "movl %1, %%edx\n"
222
#else
223
#error unsupported size
224
#endif
225
                  "pushl %6\n"
226
                  "call %7\n"
227
                  "popl %%eax\n"
228
                  "jmp 2f\n"
229
                  "1:\n"
230
                  "addl 8(%%edx), %%eax\n"
231
#if DATA_SIZE == 1
232
                  "movb %b1, (%%eax)\n"
233
#elif DATA_SIZE == 2
234
                  "movw %w1, (%%eax)\n"
235
#elif DATA_SIZE == 4
236
                  "movl %1, (%%eax)\n"
237
#else
238
#error unsupported size
239
#endif
240
                  "2:\n"
241
                  : 
242
                  : "r" (ptr), 
243
/* NOTE: 'q' would be needed as constraint, but we could not use it
244
   with T1 ! */
245
                  "r" (v), 
246
                  "i" ((CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS), 
247
                  "i" (TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS), 
248
                  "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
249
                  "m" (*(uint32_t *)offsetof(CPUState, tlb_table[CPU_MEM_INDEX][0].addr_write)),
250
                  "i" (CPU_MEM_INDEX),
251
                  "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
252
                  : "%eax", "%ecx", "%edx", "memory", "cc");
253
}
254

    
255
#else
256

    
257
/* generic load/store macros */
258

    
259
static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
260
{
261
    int index;
262
    RES_TYPE res;
263
    target_ulong addr;
264
    unsigned long physaddr;
265
    int is_user;
266

    
267
    addr = ptr;
268
    index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
269
    is_user = CPU_MEM_INDEX;
270
    if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ != 
271
                         (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
272
        res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
273
    } else {
274
        physaddr = addr + env->tlb_table[is_user][index].addend;
275
        res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
276
    }
277
    return res;
278
}
279

    
280
#if DATA_SIZE <= 2
281
static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
282
{
283
    int res, index;
284
    target_ulong addr;
285
    unsigned long physaddr;
286
    int is_user;
287

    
288
    addr = ptr;
289
    index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
290
    is_user = CPU_MEM_INDEX;
291
    if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ != 
292
                         (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
293
        res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
294
    } else {
295
        physaddr = addr + env->tlb_table[is_user][index].addend;
296
        res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
297
    }
298
    return res;
299
}
300
#endif
301

    
302
#if ACCESS_TYPE != 3
303

    
304
/* generic store macro */
305

    
306
static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
307
{
308
    int index;
309
    target_ulong addr;
310
    unsigned long physaddr;
311
    int is_user;
312

    
313
    addr = ptr;
314
    index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
315
    is_user = CPU_MEM_INDEX;
316
    if (__builtin_expect(env->tlb_table[is_user][index].addr_write != 
317
                         (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
318
        glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, is_user);
319
    } else {
320
        physaddr = addr + env->tlb_table[is_user][index].addend;
321
        glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
322
    }
323
}
324

    
325
#endif /* ACCESS_TYPE != 3 */
326

    
327
#endif /* !asm */
328

    
329
#if ACCESS_TYPE != 3
330

    
331
#if DATA_SIZE == 8
332
static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr)
333
{
334
    union {
335
        float64 d;
336
        uint64_t i;
337
    } u;
338
    u.i = glue(ldq, MEMSUFFIX)(ptr);
339
    return u.d;
340
}
341

    
342
static inline void glue(stfq, MEMSUFFIX)(target_ulong ptr, float64 v)
343
{
344
    union {
345
        float64 d;
346
        uint64_t i;
347
    } u;
348
    u.d = v;
349
    glue(stq, MEMSUFFIX)(ptr, u.i);
350
}
351
#endif /* DATA_SIZE == 8 */
352

    
353
#if DATA_SIZE == 4
354
static inline float32 glue(ldfl, MEMSUFFIX)(target_ulong ptr)
355
{
356
    union {
357
        float32 f;
358
        uint32_t i;
359
    } u;
360
    u.i = glue(ldl, MEMSUFFIX)(ptr);
361
    return u.f;
362
}
363

    
364
static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
365
{
366
    union {
367
        float32 f;
368
        uint32_t i;
369
    } u;
370
    u.f = v;
371
    glue(stl, MEMSUFFIX)(ptr, u.i);
372
}
373
#endif /* DATA_SIZE == 4 */
374

    
375
#endif /* ACCESS_TYPE != 3 */
376

    
377
#undef RES_TYPE
378
#undef DATA_TYPE
379
#undef DATA_STYPE
380
#undef SUFFIX
381
#undef USUFFIX
382
#undef DATA_SIZE
383
#undef CPU_MEM_INDEX
384
#undef MMUSUFFIX
385
#undef ADDR_READ