MIPS target (Jocelyn Mayer)
[qemu] / softmmu_header.h
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 #endif
63 #define MMUSUFFIX _mmu
64
65 #elif ACCESS_TYPE == 3
66
67 #ifdef TARGET_I386
68 #define CPU_MEM_INDEX ((env->hflags & HF_CPL_MASK) == 3)
69 #elif defined (TARGET_PPC)
70 #define CPU_MEM_INDEX (msr_pr)
71 #elif defined (TARGET_MIPS)
72 #define CPU_MEM_INDEX ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM)
73 #elif defined (TARGET_SPARC)
74 #define CPU_MEM_INDEX ((env->psrs) == 0)
75 #endif
76 #define MMUSUFFIX _cmmu
77
78 #else
79 #error invalid ACCESS_TYPE
80 #endif
81
82 #if DATA_SIZE == 8
83 #define RES_TYPE uint64_t
84 #else
85 #define RES_TYPE int
86 #endif
87
88
89 DATA_TYPE REGPARM(1) glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
90                                                          int is_user);
91 void REGPARM(2) glue(glue(__st, SUFFIX), MMUSUFFIX)(target_ulong addr, DATA_TYPE v, int is_user);
92
93 #if (DATA_SIZE <= 4) && (TARGET_LONG_BITS == 32) && defined(__i386__) && \
94     (ACCESS_TYPE <= 1) && defined(ASM_SOFTMMU)
95
96 static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
97 {
98     int res;
99
100     asm volatile ("movl %1, %%edx\n"
101                   "movl %1, %%eax\n"
102                   "shrl %3, %%edx\n"
103                   "andl %4, %%eax\n"
104                   "andl %2, %%edx\n"
105                   "leal %5(%%edx, %%ebp), %%edx\n"
106                   "cmpl (%%edx), %%eax\n"
107                   "movl %1, %%eax\n"
108                   "je 1f\n"
109                   "pushl %6\n"
110                   "call %7\n"
111                   "popl %%edx\n"
112                   "movl %%eax, %0\n"
113                   "jmp 2f\n"
114                   "1:\n"
115                   "addl 4(%%edx), %%eax\n"
116 #if DATA_SIZE == 1
117                   "movzbl (%%eax), %0\n"
118 #elif DATA_SIZE == 2
119                   "movzwl (%%eax), %0\n"
120 #elif DATA_SIZE == 4
121                   "movl (%%eax), %0\n"
122 #else
123 #error unsupported size
124 #endif
125                   "2:\n"
126                   : "=r" (res)
127                   : "r" (ptr), 
128                   "i" ((CPU_TLB_SIZE - 1) << 3), 
129                   "i" (TARGET_PAGE_BITS - 3), 
130                   "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
131                   "m" (*(uint32_t *)offsetof(CPUState, tlb_read[CPU_MEM_INDEX][0].address)),
132                   "i" (CPU_MEM_INDEX),
133                   "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
134                   : "%eax", "%ecx", "%edx", "memory", "cc");
135     return res;
136 }
137
138 #if DATA_SIZE <= 2
139 static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
140 {
141     int res;
142
143     asm volatile ("movl %1, %%edx\n"
144                   "movl %1, %%eax\n"
145                   "shrl %3, %%edx\n"
146                   "andl %4, %%eax\n"
147                   "andl %2, %%edx\n"
148                   "leal %5(%%edx, %%ebp), %%edx\n"
149                   "cmpl (%%edx), %%eax\n"
150                   "movl %1, %%eax\n"
151                   "je 1f\n"
152                   "pushl %6\n"
153                   "call %7\n"
154                   "popl %%edx\n"
155 #if DATA_SIZE == 1
156                   "movsbl %%al, %0\n"
157 #elif DATA_SIZE == 2
158                   "movswl %%ax, %0\n"
159 #else
160 #error unsupported size
161 #endif
162                   "jmp 2f\n"
163                   "1:\n"
164                   "addl 4(%%edx), %%eax\n"
165 #if DATA_SIZE == 1
166                   "movsbl (%%eax), %0\n"
167 #elif DATA_SIZE == 2
168                   "movswl (%%eax), %0\n"
169 #else
170 #error unsupported size
171 #endif
172                   "2:\n"
173                   : "=r" (res)
174                   : "r" (ptr), 
175                   "i" ((CPU_TLB_SIZE - 1) << 3), 
176                   "i" (TARGET_PAGE_BITS - 3), 
177                   "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
178                   "m" (*(uint32_t *)offsetof(CPUState, tlb_read[CPU_MEM_INDEX][0].address)),
179                   "i" (CPU_MEM_INDEX),
180                   "m" (*(uint8_t *)&glue(glue(__ld, SUFFIX), MMUSUFFIX))
181                   : "%eax", "%ecx", "%edx", "memory", "cc");
182     return res;
183 }
184 #endif
185
186 static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
187 {
188     asm volatile ("movl %0, %%edx\n"
189                   "movl %0, %%eax\n"
190                   "shrl %3, %%edx\n"
191                   "andl %4, %%eax\n"
192                   "andl %2, %%edx\n"
193                   "leal %5(%%edx, %%ebp), %%edx\n"
194                   "cmpl (%%edx), %%eax\n"
195                   "movl %0, %%eax\n"
196                   "je 1f\n"
197 #if DATA_SIZE == 1
198                   "movzbl %b1, %%edx\n"
199 #elif DATA_SIZE == 2
200                   "movzwl %w1, %%edx\n"
201 #elif DATA_SIZE == 4
202                   "movl %1, %%edx\n"
203 #else
204 #error unsupported size
205 #endif
206                   "pushl %6\n"
207                   "call %7\n"
208                   "popl %%eax\n"
209                   "jmp 2f\n"
210                   "1:\n"
211                   "addl 4(%%edx), %%eax\n"
212 #if DATA_SIZE == 1
213                   "movb %b1, (%%eax)\n"
214 #elif DATA_SIZE == 2
215                   "movw %w1, (%%eax)\n"
216 #elif DATA_SIZE == 4
217                   "movl %1, (%%eax)\n"
218 #else
219 #error unsupported size
220 #endif
221                   "2:\n"
222                   : 
223                   : "r" (ptr), 
224 /* NOTE: 'q' would be needed as constraint, but we could not use it
225    with T1 ! */
226                   "r" (v), 
227                   "i" ((CPU_TLB_SIZE - 1) << 3), 
228                   "i" (TARGET_PAGE_BITS - 3), 
229                   "i" (TARGET_PAGE_MASK | (DATA_SIZE - 1)),
230                   "m" (*(uint32_t *)offsetof(CPUState, tlb_write[CPU_MEM_INDEX][0].address)),
231                   "i" (CPU_MEM_INDEX),
232                   "m" (*(uint8_t *)&glue(glue(__st, SUFFIX), MMUSUFFIX))
233                   : "%eax", "%ecx", "%edx", "memory", "cc");
234 }
235
236 #else
237
238 /* generic load/store macros */
239
240 static inline RES_TYPE glue(glue(ld, USUFFIX), MEMSUFFIX)(target_ulong ptr)
241 {
242     int index;
243     RES_TYPE res;
244     target_ulong addr;
245     unsigned long physaddr;
246     int is_user;
247
248     addr = ptr;
249     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
250     is_user = CPU_MEM_INDEX;
251     if (__builtin_expect(env->tlb_read[is_user][index].address != 
252                          (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
253         res = glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
254     } else {
255         physaddr = addr + env->tlb_read[is_user][index].addend;
256         res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)physaddr);
257     }
258     return res;
259 }
260
261 #if DATA_SIZE <= 2
262 static inline int glue(glue(lds, SUFFIX), MEMSUFFIX)(target_ulong ptr)
263 {
264     int res, index;
265     target_ulong addr;
266     unsigned long physaddr;
267     int is_user;
268
269     addr = ptr;
270     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
271     is_user = CPU_MEM_INDEX;
272     if (__builtin_expect(env->tlb_read[is_user][index].address != 
273                          (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
274         res = (DATA_STYPE)glue(glue(__ld, SUFFIX), MMUSUFFIX)(addr, is_user);
275     } else {
276         physaddr = addr + env->tlb_read[is_user][index].addend;
277         res = glue(glue(lds, SUFFIX), _raw)((uint8_t *)physaddr);
278     }
279     return res;
280 }
281 #endif
282
283 /* generic store macro */
284
285 static inline void glue(glue(st, SUFFIX), MEMSUFFIX)(target_ulong ptr, RES_TYPE v)
286 {
287     int index;
288     target_ulong addr;
289     unsigned long physaddr;
290     int is_user;
291
292     addr = ptr;
293     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
294     is_user = CPU_MEM_INDEX;
295     if (__builtin_expect(env->tlb_write[is_user][index].address != 
296                          (addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))), 0)) {
297         glue(glue(__st, SUFFIX), MMUSUFFIX)(addr, v, is_user);
298     } else {
299         physaddr = addr + env->tlb_write[is_user][index].addend;
300         glue(glue(st, SUFFIX), _raw)((uint8_t *)physaddr, v);
301     }
302 }
303
304 #endif
305
306 #if DATA_SIZE == 8
307 static inline double glue(ldfq, MEMSUFFIX)(target_ulong ptr)
308 {
309     union {
310         double d;
311         uint64_t i;
312     } u;
313     u.i = glue(ldq, MEMSUFFIX)(ptr);
314     return u.d;
315 }
316
317 static inline void glue(stfq, MEMSUFFIX)(target_ulong ptr, double v)
318 {
319     union {
320         double d;
321         uint64_t i;
322     } u;
323     u.d = v;
324     glue(stq, MEMSUFFIX)(ptr, u.i);
325 }
326 #endif /* DATA_SIZE == 8 */
327
328 #if DATA_SIZE == 4
329 static inline float glue(ldfl, MEMSUFFIX)(target_ulong ptr)
330 {
331     union {
332         float f;
333         uint32_t i;
334     } u;
335     u.i = glue(ldl, MEMSUFFIX)(ptr);
336     return u.f;
337 }
338
339 static inline void glue(stfl, MEMSUFFIX)(target_ulong ptr, float v)
340 {
341     union {
342         float f;
343         uint32_t i;
344     } u;
345     u.f = v;
346     glue(stl, MEMSUFFIX)(ptr, u.i);
347 }
348 #endif /* DATA_SIZE == 4 */
349
350 #undef RES_TYPE
351 #undef DATA_TYPE
352 #undef DATA_STYPE
353 #undef SUFFIX
354 #undef USUFFIX
355 #undef DATA_SIZE
356 #undef CPU_MEM_INDEX
357 #undef MMUSUFFIX