PowerPC target optimisations: make intensive use of always_inline.
[qemu] / target-ppc / op_helper_mem.h
1 /*
2  *  PowerPC emulation micro-operations helpers for qemu.
3  *
4  *  Copyright (c) 2003-2007 Jocelyn Mayer
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
21 /* Multiple word / string load and store */
22 static always_inline target_ulong glue(ld32r, MEMSUFFIX) (target_ulong EA)
23 {
24     uint32_t tmp = glue(ldl, MEMSUFFIX)(EA);
25     return ((tmp & 0xFF000000UL) >> 24) | ((tmp & 0x00FF0000UL) >> 8) |
26         ((tmp & 0x0000FF00UL) << 8) | ((tmp & 0x000000FFUL) << 24);
27 }
28
29 static always_inline void glue(st32r, MEMSUFFIX) (target_ulong EA,
30                                                   target_ulong data)
31 {
32     uint32_t tmp =
33         ((data & 0xFF000000UL) >> 24) | ((data & 0x00FF0000UL) >> 8) |
34         ((data & 0x0000FF00UL) << 8) | ((data & 0x000000FFUL) << 24);
35     glue(stl, MEMSUFFIX)(EA, tmp);
36 }
37
38 void glue(do_lmw, MEMSUFFIX) (int dst)
39 {
40     for (; dst < 32; dst++, T0 += 4) {
41         env->gpr[dst] = glue(ldl, MEMSUFFIX)((uint32_t)T0);
42     }
43 }
44
45 #if defined(TARGET_PPC64)
46 void glue(do_lmw_64, MEMSUFFIX) (int dst)
47 {
48     for (; dst < 32; dst++, T0 += 4) {
49         env->gpr[dst] = glue(ldl, MEMSUFFIX)((uint64_t)T0);
50     }
51 }
52 #endif
53
54 void glue(do_stmw, MEMSUFFIX) (int src)
55 {
56     for (; src < 32; src++, T0 += 4) {
57         glue(stl, MEMSUFFIX)((uint32_t)T0, env->gpr[src]);
58     }
59 }
60
61 #if defined(TARGET_PPC64)
62 void glue(do_stmw_64, MEMSUFFIX) (int src)
63 {
64     for (; src < 32; src++, T0 += 4) {
65         glue(stl, MEMSUFFIX)((uint64_t)T0, env->gpr[src]);
66     }
67 }
68 #endif
69
70 void glue(do_lmw_le, MEMSUFFIX) (int dst)
71 {
72     for (; dst < 32; dst++, T0 += 4) {
73         env->gpr[dst] = glue(ld32r, MEMSUFFIX)((uint32_t)T0);
74     }
75 }
76
77 #if defined(TARGET_PPC64)
78 void glue(do_lmw_le_64, MEMSUFFIX) (int dst)
79 {
80     for (; dst < 32; dst++, T0 += 4) {
81         env->gpr[dst] = glue(ld32r, MEMSUFFIX)((uint64_t)T0);
82     }
83 }
84 #endif
85
86 void glue(do_stmw_le, MEMSUFFIX) (int src)
87 {
88     for (; src < 32; src++, T0 += 4) {
89         glue(st32r, MEMSUFFIX)((uint32_t)T0, env->gpr[src]);
90     }
91 }
92
93 #if defined(TARGET_PPC64)
94 void glue(do_stmw_le_64, MEMSUFFIX) (int src)
95 {
96     for (; src < 32; src++, T0 += 4) {
97         glue(st32r, MEMSUFFIX)((uint64_t)T0, env->gpr[src]);
98     }
99 }
100 #endif
101
102 void glue(do_lsw, MEMSUFFIX) (int dst)
103 {
104     uint32_t tmp;
105     int sh;
106
107     for (; T1 > 3; T1 -= 4, T0 += 4) {
108         env->gpr[dst++] = glue(ldl, MEMSUFFIX)((uint32_t)T0);
109         if (unlikely(dst == 32))
110             dst = 0;
111     }
112     if (unlikely(T1 != 0)) {
113         tmp = 0;
114         for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) {
115             tmp |= glue(ldub, MEMSUFFIX)((uint32_t)T0) << sh;
116         }
117         env->gpr[dst] = tmp;
118     }
119 }
120
121 #if defined(TARGET_PPC64)
122 void glue(do_lsw_64, MEMSUFFIX) (int dst)
123 {
124     uint32_t tmp;
125     int sh;
126
127     for (; T1 > 3; T1 -= 4, T0 += 4) {
128         env->gpr[dst++] = glue(ldl, MEMSUFFIX)((uint64_t)T0);
129         if (unlikely(dst == 32))
130             dst = 0;
131     }
132     if (unlikely(T1 != 0)) {
133         tmp = 0;
134         for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) {
135             tmp |= glue(ldub, MEMSUFFIX)((uint64_t)T0) << sh;
136         }
137         env->gpr[dst] = tmp;
138     }
139 }
140 #endif
141
142 void glue(do_stsw, MEMSUFFIX) (int src)
143 {
144     int sh;
145
146     for (; T1 > 3; T1 -= 4, T0 += 4) {
147         glue(stl, MEMSUFFIX)((uint32_t)T0, env->gpr[src++]);
148         if (unlikely(src == 32))
149             src = 0;
150     }
151     if (unlikely(T1 != 0)) {
152         for (sh = 24; T1 > 0; T1--, T0++, sh -= 8)
153             glue(stb, MEMSUFFIX)((uint32_t)T0, (env->gpr[src] >> sh) & 0xFF);
154     }
155 }
156
157 #if defined(TARGET_PPC64)
158 void glue(do_stsw_64, MEMSUFFIX) (int src)
159 {
160     int sh;
161
162     for (; T1 > 3; T1 -= 4, T0 += 4) {
163         glue(stl, MEMSUFFIX)((uint64_t)T0, env->gpr[src++]);
164         if (unlikely(src == 32))
165             src = 0;
166     }
167     if (unlikely(T1 != 0)) {
168         for (sh = 24; T1 > 0; T1--, T0++, sh -= 8)
169             glue(stb, MEMSUFFIX)((uint64_t)T0, (env->gpr[src] >> sh) & 0xFF);
170     }
171 }
172 #endif
173
174 void glue(do_lsw_le, MEMSUFFIX) (int dst)
175 {
176     uint32_t tmp;
177     int sh;
178
179     for (; T1 > 3; T1 -= 4, T0 += 4) {
180         env->gpr[dst++] = glue(ld32r, MEMSUFFIX)((uint32_t)T0);
181         if (unlikely(dst == 32))
182             dst = 0;
183     }
184     if (unlikely(T1 != 0)) {
185         tmp = 0;
186         for (sh = 0; T1 > 0; T1--, T0++, sh += 8) {
187             tmp |= glue(ldub, MEMSUFFIX)((uint32_t)T0) << sh;
188         }
189         env->gpr[dst] = tmp;
190     }
191 }
192
193 #if defined(TARGET_PPC64)
194 void glue(do_lsw_le_64, MEMSUFFIX) (int dst)
195 {
196     uint32_t tmp;
197     int sh;
198
199     for (; T1 > 3; T1 -= 4, T0 += 4) {
200         env->gpr[dst++] = glue(ld32r, MEMSUFFIX)((uint64_t)T0);
201         if (unlikely(dst == 32))
202             dst = 0;
203     }
204     if (unlikely(T1 != 0)) {
205         tmp = 0;
206         for (sh = 0; T1 > 0; T1--, T0++, sh += 8) {
207             tmp |= glue(ldub, MEMSUFFIX)((uint64_t)T0) << sh;
208         }
209         env->gpr[dst] = tmp;
210     }
211 }
212 #endif
213
214 void glue(do_stsw_le, MEMSUFFIX) (int src)
215 {
216     int sh;
217
218     for (; T1 > 3; T1 -= 4, T0 += 4) {
219         glue(st32r, MEMSUFFIX)((uint32_t)T0, env->gpr[src++]);
220         if (unlikely(src == 32))
221             src = 0;
222     }
223     if (unlikely(T1 != 0)) {
224         for (sh = 0; T1 > 0; T1--, T0++, sh += 8)
225             glue(stb, MEMSUFFIX)((uint32_t)T0, (env->gpr[src] >> sh) & 0xFF);
226     }
227 }
228
229 #if defined(TARGET_PPC64)
230 void glue(do_stsw_le_64, MEMSUFFIX) (int src)
231 {
232     int sh;
233
234     for (; T1 > 3; T1 -= 4, T0 += 4) {
235         glue(st32r, MEMSUFFIX)((uint64_t)T0, env->gpr[src++]);
236         if (unlikely(src == 32))
237             src = 0;
238     }
239     if (unlikely(T1 != 0)) {
240         for (sh = 0; T1 > 0; T1--, T0++, sh += 8)
241             glue(stb, MEMSUFFIX)((uint64_t)T0, (env->gpr[src] >> sh) & 0xFF);
242     }
243 }
244 #endif
245
246 /* Instruction cache invalidation helper */
247 void glue(do_icbi, MEMSUFFIX) (void)
248 {
249     uint32_t tmp;
250     /* Invalidate one cache line :
251      * PowerPC specification says this is to be treated like a load
252      * (not a fetch) by the MMU. To be sure it will be so,
253      * do the load "by hand".
254      */
255     tmp = glue(ldl, MEMSUFFIX)((uint32_t)T0);
256     T0 &= ~(env->icache_line_size - 1);
257     tb_invalidate_page_range((uint32_t)T0,
258                              (uint32_t)(T0 + env->icache_line_size));
259 }
260
261 #if defined(TARGET_PPC64)
262 void glue(do_icbi_64, MEMSUFFIX) (void)
263 {
264     uint64_t tmp;
265     /* Invalidate one cache line :
266      * PowerPC specification says this is to be treated like a load
267      * (not a fetch) by the MMU. To be sure it will be so,
268      * do the load "by hand".
269      */
270     tmp = glue(ldq, MEMSUFFIX)((uint64_t)T0);
271     T0 &= ~(env->icache_line_size - 1);
272     tb_invalidate_page_range((uint64_t)T0,
273                              (uint64_t)(T0 + env->icache_line_size));
274 }
275 #endif
276
277 void glue(do_dcbz, MEMSUFFIX) (void)
278 {
279     int dcache_line_size = env->dcache_line_size;
280
281     /* XXX: should be 970 specific (?) */
282     if (((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1)
283         dcache_line_size = 32;
284     glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x00), 0);
285     glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x04), 0);
286     glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x08), 0);
287     glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x0C), 0);
288     glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x10), 0);
289     glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x14), 0);
290     glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x18), 0);
291     glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x1C), 0);
292     if (dcache_line_size >= 64) {
293         glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x20UL), 0);
294         glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x24UL), 0);
295         glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x28UL), 0);
296         glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x2CUL), 0);
297         glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x30UL), 0);
298         glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x34UL), 0);
299         glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x38UL), 0);
300         glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x3CUL), 0);
301         if (dcache_line_size >= 128) {
302             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x40UL), 0);
303             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x44UL), 0);
304             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x48UL), 0);
305             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x4CUL), 0);
306             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x50UL), 0);
307             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x54UL), 0);
308             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x58UL), 0);
309             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x5CUL), 0);
310             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x60UL), 0);
311             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x64UL), 0);
312             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x68UL), 0);
313             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x6CUL), 0);
314             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x70UL), 0);
315             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x74UL), 0);
316             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x78UL), 0);
317             glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x7CUL), 0);
318         }
319     }
320 }
321
322 #if defined(TARGET_PPC64)
323 void glue(do_dcbz_64, MEMSUFFIX) (void)
324 {
325     int dcache_line_size = env->dcache_line_size;
326
327     /* XXX: should be 970 specific (?) */
328     if (((env->spr[SPR_970_HID5] >> 6) & 0x3) == 0x2)
329         dcache_line_size = 32;
330     glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x00), 0);
331     glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x04), 0);
332     glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x08), 0);
333     glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x0C), 0);
334     glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x10), 0);
335     glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x14), 0);
336     glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x18), 0);
337     glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x1C), 0);
338     if (dcache_line_size >= 64) {
339         glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x20UL), 0);
340         glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x24UL), 0);
341         glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x28UL), 0);
342         glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x2CUL), 0);
343         glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x30UL), 0);
344         glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x34UL), 0);
345         glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x38UL), 0);
346         glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x3CUL), 0);
347         if (dcache_line_size >= 128) {
348             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x40UL), 0);
349             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x44UL), 0);
350             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x48UL), 0);
351             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x4CUL), 0);
352             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x50UL), 0);
353             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x54UL), 0);
354             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x58UL), 0);
355             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x5CUL), 0);
356             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x60UL), 0);
357             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x64UL), 0);
358             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x68UL), 0);
359             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x6CUL), 0);
360             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x70UL), 0);
361             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x74UL), 0);
362             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x78UL), 0);
363             glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x7CUL), 0);
364         }
365     }
366 }
367 #endif
368
369 /* PowerPC 601 specific instructions (POWER bridge) */
370 // XXX: to be tested
371 void glue(do_POWER_lscbx, MEMSUFFIX) (int dest, int ra, int rb)
372 {
373     int i, c, d, reg;
374
375     d = 24;
376     reg = dest;
377     for (i = 0; i < T1; i++) {
378         c = glue(ldub, MEMSUFFIX)((uint32_t)T0++);
379         /* ra (if not 0) and rb are never modified */
380         if (likely(reg != rb && (ra == 0 || reg != ra))) {
381             env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d);
382         }
383         if (unlikely(c == T2))
384             break;
385         if (likely(d != 0)) {
386             d -= 8;
387         } else {
388             d = 24;
389             reg++;
390             reg = reg & 0x1F;
391         }
392     }
393     T0 = i;
394 }
395
396 /* XXX: TAGs are not managed */
397 void glue(do_POWER2_lfq, MEMSUFFIX) (void)
398 {
399     FT0 = glue(ldfq, MEMSUFFIX)((uint32_t)T0);
400     FT1 = glue(ldfq, MEMSUFFIX)((uint32_t)(T0 + 4));
401 }
402
403 static always_inline double glue(ldfqr, MEMSUFFIX) (target_ulong EA)
404 {
405     union {
406         double d;
407         uint64_t u;
408     } u;
409
410     u.d = glue(ldfq, MEMSUFFIX)(EA);
411     u.u = ((u.u & 0xFF00000000000000ULL) >> 56) |
412         ((u.u & 0x00FF000000000000ULL) >> 40) |
413         ((u.u & 0x0000FF0000000000ULL) >> 24) |
414         ((u.u & 0x000000FF00000000ULL) >> 8) |
415         ((u.u & 0x00000000FF000000ULL) << 8) |
416         ((u.u & 0x0000000000FF0000ULL) << 24) |
417         ((u.u & 0x000000000000FF00ULL) << 40) |
418         ((u.u & 0x00000000000000FFULL) << 56);
419
420     return u.d;
421 }
422
423 void glue(do_POWER2_lfq_le, MEMSUFFIX) (void)
424 {
425     FT0 = glue(ldfqr, MEMSUFFIX)((uint32_t)(T0 + 4));
426     FT1 = glue(ldfqr, MEMSUFFIX)((uint32_t)T0);
427 }
428
429 void glue(do_POWER2_stfq, MEMSUFFIX) (void)
430 {
431     glue(stfq, MEMSUFFIX)((uint32_t)T0, FT0);
432     glue(stfq, MEMSUFFIX)((uint32_t)(T0 + 4), FT1);
433 }
434
435 static always_inline void glue(stfqr, MEMSUFFIX) (target_ulong EA, double d)
436 {
437     union {
438         double d;
439         uint64_t u;
440     } u;
441
442     u.d = d;
443     u.u = ((u.u & 0xFF00000000000000ULL) >> 56) |
444         ((u.u & 0x00FF000000000000ULL) >> 40) |
445         ((u.u & 0x0000FF0000000000ULL) >> 24) |
446         ((u.u & 0x000000FF00000000ULL) >> 8) |
447         ((u.u & 0x00000000FF000000ULL) << 8) |
448         ((u.u & 0x0000000000FF0000ULL) << 24) |
449         ((u.u & 0x000000000000FF00ULL) << 40) |
450         ((u.u & 0x00000000000000FFULL) << 56);
451     glue(stfq, MEMSUFFIX)(EA, u.d);
452 }
453
454 void glue(do_POWER2_stfq_le, MEMSUFFIX) (void)
455 {
456     glue(stfqr, MEMSUFFIX)((uint32_t)(T0 + 4), FT0);
457     glue(stfqr, MEMSUFFIX)((uint32_t)T0, FT1);
458 }
459
460 #undef MEMSUFFIX