Statistics
| Branch: | Revision:

root / softmmu_header.h @ 5fafdf24

History | View | Annotate | Download (11 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
#elif defined (TARGET_ALPHA)
67
#define CPU_MEM_INDEX ((env->ps >> 3) & 3)
68
#elif defined (TARGET_M68K)
69
#define CPU_MEM_INDEX ((env->sr & SR_S) == 0)
70
#else
71
#error unsupported CPU
72
#endif
73
#define MMUSUFFIX _mmu
74

    
75
#elif ACCESS_TYPE == 3
76

    
77
#ifdef TARGET_I386
78
#define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
79
#elif defined (TARGET_PPC)
80
#define CPU_MEM_INDEX (msr_pr)
81
#elif defined (TARGET_MIPS)
82
#define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
83
#elif defined (TARGET_SPARC)
84
#define CPU_MEM_INDEX ((env->psrs) == 0)
85
#elif defined (TARGET_ARM)
86
#define CPU_MEM_INDEX ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR)
87
#elif defined (TARGET_SH4)
88
#define CPU_MEM_INDEX ((env->sr & SR_MD) == 0)
89
#elif defined (TARGET_ALPHA)
90
#define CPU_MEM_INDEX ((env->ps >> 3) & 3)
91
#elif defined (TARGET_M68K)
92
#define CPU_MEM_INDEX ((env->sr & SR_S) == 0)
93
#else
94
#error unsupported CPU
95
#endif
96
#define MMUSUFFIX _cmmu
97

    
98
#else
99
#error invalid ACCESS_TYPE
100
#endif
101

    
102
#if DATA_SIZE == 8
103
#define RES_TYPE uint64_t
104
#else
105
#define RES_TYPE int
106
#endif
107

    
108
#if ACCESS_TYPE == 3
109
#define ADDR_READ addr_code
110
#else
111
#define ADDR_READ addr_read
112
#endif
113

    
114
DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
115
                                                         int is_user);
116
void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int is_user);
117

    
118
#if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
119
    (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU)
120

    
121
#define CPU_TLB_ENTRY_BITS 4
122

    
123
static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
124
{
125
    int res;
126

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

    
165
#if DATA_SIZE <= 2
166
static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
167
{
168
    int res;
169

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

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

    
263
#else
264

    
265
/* generic load/store macros */
266

    
267
static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
268
{
269
    int index;
270
    RES_TYPE res;
271
    target_ulong addr;
272
    unsigned long physaddr;
273
    int is_user;
274

    
275
    addr = ptr;
276
    index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
277
    is_user = CPU_MEM_INDEX;
278
    if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ !=
279
                         (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
280
        res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
281
    } else {
282
        physaddr = addr + env->tlb_table[is_user][index].addend;
283
        res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
284
    }
285
    return res;
286
}
287

    
288
#if DATA_SIZE <= 2
289
static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
290
{
291
    int res, index;
292
    target_ulong addr;
293
    unsigned long physaddr;
294
    int is_user;
295

    
296
    addr = ptr;
297
    index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
298
    is_user = CPU_MEM_INDEX;
299
    if (__builtin_expect(env->tlb_table[is_user][index].ADDR_READ !=
300
                         (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
301
        res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
302
    } else {
303
        physaddr = addr + env->tlb_table[is_user][index].addend;
304
        res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
305
    }
306
    return res;
307
}
308
#endif
309

    
310
#if ACCESS_TYPE != 3
311

    
312
/* generic store macro */
313

    
314
static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
315
{
316
    int index;
317
    target_ulong addr;
318
    unsigned long physaddr;
319
    int is_user;
320

    
321
    addr = ptr;
322
    index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
323
    is_user = CPU_MEM_INDEX;
324
    if (__builtin_expect(env->tlb_table[is_user][index].addr_write !=
325
                         (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
326
        glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, is_user);
327
    } else {
328
        physaddr = addr + env->tlb_table[is_user][index].addend;
329
        glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
330
    }
331
}
332

    
333
#endif /* ACCESS_TYPE != 3 */
334

    
335
#endif /* !asm */
336

    
337
#if ACCESS_TYPE != 3
338

    
339
#if DATA_SIZE == 8
340
static inline float64 glue(ldfq, MEMSUFFIX)(target_ulong ptr)
341
{
342
    union {
343
        float64 d;
344
        uint64_t i;
345
    } u;
346
    u.i = glue(ldq, MEMSUFFIX)(ptr);
347
    return u.d;
348
}
349

    
350
static inline void glue(stfq, MEMSUFFIX)(target_ulong ptr, float64 v)
351
{
352
    union {
353
        float64 d;
354
        uint64_t i;
355
    } u;
356
    u.d = v;
357
    glue(stq, MEMSUFFIX)(ptr, u.i);
358
}
359
#endif /* DATA_SIZE == 8 */
360

    
361
#if DATA_SIZE == 4
362
static inline float32 glue(ldfl, MEMSUFFIX)(target_ulong ptr)
363
{
364
    union {
365
        float32 f;
366
        uint32_t i;
367
    } u;
368
    u.i = glue(ldl, MEMSUFFIX)(ptr);
369
    return u.f;
370
}
371

    
372
static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float32 v)
373
{
374
    union {
375
        float32 f;
376
        uint32_t i;
377
    } u;
378
    u.f = v;
379
    glue(stl, MEMSUFFIX)(ptr, u.i);
380
}
381
#endif /* DATA_SIZE == 4 */
382

    
383
#endif /* ACCESS_TYPE != 3 */
384

    
385
#undef RES_TYPE
386
#undef DATA_TYPE
387
#undef DATA_STYPE
388
#undef SUFFIX
389
#undef USUFFIX
390
#undef DATA_SIZE
391
#undef CPU_MEM_INDEX
392
#undef MMUSUFFIX
393
#undef ADDR_READ