root / target-ppc / op_helper_mem.h @ e83ce550
History | View | Annotate | Download (10.9 kB)
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 |
#include "op_mem_access.h" |
22 |
|
23 |
/* Multiple word / string load and store */
|
24 |
void glue(do_lmw, MEMSUFFIX) (int dst) |
25 |
{ |
26 |
for (; dst < 32; dst++, T0 += 4) { |
27 |
env->gpr[dst] = glue(ldu32, MEMSUFFIX)((uint32_t)T0); |
28 |
} |
29 |
} |
30 |
|
31 |
#if defined(TARGET_PPC64)
|
32 |
void glue(do_lmw_64, MEMSUFFIX) (int dst) |
33 |
{ |
34 |
for (; dst < 32; dst++, T0 += 4) { |
35 |
env->gpr[dst] = glue(ldu32, MEMSUFFIX)((uint64_t)T0); |
36 |
} |
37 |
} |
38 |
#endif
|
39 |
|
40 |
void glue(do_stmw, MEMSUFFIX) (int src) |
41 |
{ |
42 |
for (; src < 32; src++, T0 += 4) { |
43 |
glue(st32, MEMSUFFIX)((uint32_t)T0, env->gpr[src]); |
44 |
} |
45 |
} |
46 |
|
47 |
#if defined(TARGET_PPC64)
|
48 |
void glue(do_stmw_64, MEMSUFFIX) (int src) |
49 |
{ |
50 |
for (; src < 32; src++, T0 += 4) { |
51 |
glue(st32, MEMSUFFIX)((uint64_t)T0, env->gpr[src]); |
52 |
} |
53 |
} |
54 |
#endif
|
55 |
|
56 |
void glue(do_lmw_le, MEMSUFFIX) (int dst) |
57 |
{ |
58 |
for (; dst < 32; dst++, T0 += 4) { |
59 |
env->gpr[dst] = glue(ldu32r, MEMSUFFIX)((uint32_t)T0); |
60 |
} |
61 |
} |
62 |
|
63 |
#if defined(TARGET_PPC64)
|
64 |
void glue(do_lmw_le_64, MEMSUFFIX) (int dst) |
65 |
{ |
66 |
for (; dst < 32; dst++, T0 += 4) { |
67 |
env->gpr[dst] = glue(ldu32r, MEMSUFFIX)((uint64_t)T0); |
68 |
} |
69 |
} |
70 |
#endif
|
71 |
|
72 |
void glue(do_stmw_le, MEMSUFFIX) (int src) |
73 |
{ |
74 |
for (; src < 32; src++, T0 += 4) { |
75 |
glue(st32r, MEMSUFFIX)((uint32_t)T0, env->gpr[src]); |
76 |
} |
77 |
} |
78 |
|
79 |
#if defined(TARGET_PPC64)
|
80 |
void glue(do_stmw_le_64, MEMSUFFIX) (int src) |
81 |
{ |
82 |
for (; src < 32; src++, T0 += 4) { |
83 |
glue(st32r, MEMSUFFIX)((uint64_t)T0, env->gpr[src]); |
84 |
} |
85 |
} |
86 |
#endif
|
87 |
|
88 |
void glue(do_lsw, MEMSUFFIX) (int dst) |
89 |
{ |
90 |
uint32_t tmp; |
91 |
int sh;
|
92 |
|
93 |
for (; T1 > 3; T1 -= 4, T0 += 4) { |
94 |
env->gpr[dst++] = glue(ldu32, MEMSUFFIX)((uint32_t)T0); |
95 |
if (unlikely(dst == 32)) |
96 |
dst = 0;
|
97 |
} |
98 |
if (unlikely(T1 != 0)) { |
99 |
tmp = 0;
|
100 |
for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) { |
101 |
tmp |= glue(ldu8, MEMSUFFIX)((uint32_t)T0) << sh; |
102 |
} |
103 |
env->gpr[dst] = tmp; |
104 |
} |
105 |
} |
106 |
|
107 |
#if defined(TARGET_PPC64)
|
108 |
void glue(do_lsw_64, MEMSUFFIX) (int dst) |
109 |
{ |
110 |
uint32_t tmp; |
111 |
int sh;
|
112 |
|
113 |
for (; T1 > 3; T1 -= 4, T0 += 4) { |
114 |
env->gpr[dst++] = glue(ldu32, MEMSUFFIX)((uint64_t)T0); |
115 |
if (unlikely(dst == 32)) |
116 |
dst = 0;
|
117 |
} |
118 |
if (unlikely(T1 != 0)) { |
119 |
tmp = 0;
|
120 |
for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) { |
121 |
tmp |= glue(ldu8, MEMSUFFIX)((uint64_t)T0) << sh; |
122 |
} |
123 |
env->gpr[dst] = tmp; |
124 |
} |
125 |
} |
126 |
#endif
|
127 |
|
128 |
void glue(do_stsw, MEMSUFFIX) (int src) |
129 |
{ |
130 |
int sh;
|
131 |
|
132 |
for (; T1 > 3; T1 -= 4, T0 += 4) { |
133 |
glue(st32, MEMSUFFIX)((uint32_t)T0, env->gpr[src++]); |
134 |
if (unlikely(src == 32)) |
135 |
src = 0;
|
136 |
} |
137 |
if (unlikely(T1 != 0)) { |
138 |
for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) |
139 |
glue(st8, MEMSUFFIX)((uint32_t)T0, (env->gpr[src] >> sh) & 0xFF);
|
140 |
} |
141 |
} |
142 |
|
143 |
#if defined(TARGET_PPC64)
|
144 |
void glue(do_stsw_64, MEMSUFFIX) (int src) |
145 |
{ |
146 |
int sh;
|
147 |
|
148 |
for (; T1 > 3; T1 -= 4, T0 += 4) { |
149 |
glue(st32, MEMSUFFIX)((uint64_t)T0, env->gpr[src++]); |
150 |
if (unlikely(src == 32)) |
151 |
src = 0;
|
152 |
} |
153 |
if (unlikely(T1 != 0)) { |
154 |
for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) |
155 |
glue(st8, MEMSUFFIX)((uint64_t)T0, (env->gpr[src] >> sh) & 0xFF);
|
156 |
} |
157 |
} |
158 |
#endif
|
159 |
|
160 |
/* Instruction cache invalidation helper */
|
161 |
void glue(do_icbi, MEMSUFFIX) (void) |
162 |
{ |
163 |
uint32_t tmp; |
164 |
/* Invalidate one cache line :
|
165 |
* PowerPC specification says this is to be treated like a load
|
166 |
* (not a fetch) by the MMU. To be sure it will be so,
|
167 |
* do the load "by hand".
|
168 |
*/
|
169 |
T0 &= ~(env->icache_line_size - 1);
|
170 |
tmp = glue(ldl, MEMSUFFIX)((uint32_t)T0); |
171 |
tb_invalidate_page_range((uint32_t)T0, |
172 |
(uint32_t)(T0 + env->icache_line_size)); |
173 |
} |
174 |
|
175 |
#if defined(TARGET_PPC64)
|
176 |
void glue(do_icbi_64, MEMSUFFIX) (void) |
177 |
{ |
178 |
uint64_t tmp; |
179 |
/* Invalidate one cache line :
|
180 |
* PowerPC specification says this is to be treated like a load
|
181 |
* (not a fetch) by the MMU. To be sure it will be so,
|
182 |
* do the load "by hand".
|
183 |
*/
|
184 |
T0 &= ~(env->icache_line_size - 1);
|
185 |
tmp = glue(ldq, MEMSUFFIX)((uint64_t)T0); |
186 |
tb_invalidate_page_range((uint64_t)T0, |
187 |
(uint64_t)(T0 + env->icache_line_size)); |
188 |
} |
189 |
#endif
|
190 |
|
191 |
void glue(do_dcbz, MEMSUFFIX) (void) |
192 |
{ |
193 |
int dcache_line_size = env->dcache_line_size;
|
194 |
|
195 |
/* XXX: should be 970 specific (?) */
|
196 |
if (((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1) |
197 |
dcache_line_size = 32;
|
198 |
T0 &= ~(uint32_t)(dcache_line_size - 1);
|
199 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x00), 0); |
200 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x04), 0); |
201 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x08), 0); |
202 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x0C), 0); |
203 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x10), 0); |
204 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x14), 0); |
205 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x18), 0); |
206 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x1C), 0); |
207 |
if (dcache_line_size >= 64) { |
208 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x20UL), 0); |
209 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x24UL), 0); |
210 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x28UL), 0); |
211 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x2CUL), 0); |
212 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x30UL), 0); |
213 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x34UL), 0); |
214 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x38UL), 0); |
215 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x3CUL), 0); |
216 |
if (dcache_line_size >= 128) { |
217 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x40UL), 0); |
218 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x44UL), 0); |
219 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x48UL), 0); |
220 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x4CUL), 0); |
221 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x50UL), 0); |
222 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x54UL), 0); |
223 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x58UL), 0); |
224 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x5CUL), 0); |
225 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x60UL), 0); |
226 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x64UL), 0); |
227 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x68UL), 0); |
228 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x6CUL), 0); |
229 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x70UL), 0); |
230 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x74UL), 0); |
231 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x78UL), 0); |
232 |
glue(stl, MEMSUFFIX)((uint32_t)(T0 + 0x7CUL), 0); |
233 |
} |
234 |
} |
235 |
} |
236 |
|
237 |
#if defined(TARGET_PPC64)
|
238 |
void glue(do_dcbz_64, MEMSUFFIX) (void) |
239 |
{ |
240 |
int dcache_line_size = env->dcache_line_size;
|
241 |
|
242 |
/* XXX: should be 970 specific (?) */
|
243 |
if (((env->spr[SPR_970_HID5] >> 6) & 0x3) == 0x2) |
244 |
dcache_line_size = 32;
|
245 |
T0 &= ~(uint64_t)(dcache_line_size - 1);
|
246 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x00), 0); |
247 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x04), 0); |
248 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x08), 0); |
249 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x0C), 0); |
250 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x10), 0); |
251 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x14), 0); |
252 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x18), 0); |
253 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x1C), 0); |
254 |
if (dcache_line_size >= 64) { |
255 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x20UL), 0); |
256 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x24UL), 0); |
257 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x28UL), 0); |
258 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x2CUL), 0); |
259 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x30UL), 0); |
260 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x34UL), 0); |
261 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x38UL), 0); |
262 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x3CUL), 0); |
263 |
if (dcache_line_size >= 128) { |
264 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x40UL), 0); |
265 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x44UL), 0); |
266 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x48UL), 0); |
267 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x4CUL), 0); |
268 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x50UL), 0); |
269 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x54UL), 0); |
270 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x58UL), 0); |
271 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x5CUL), 0); |
272 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x60UL), 0); |
273 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x64UL), 0); |
274 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x68UL), 0); |
275 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x6CUL), 0); |
276 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x70UL), 0); |
277 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x74UL), 0); |
278 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x78UL), 0); |
279 |
glue(stl, MEMSUFFIX)((uint64_t)(T0 + 0x7CUL), 0); |
280 |
} |
281 |
} |
282 |
} |
283 |
#endif
|
284 |
|
285 |
/* PowerPC 601 specific instructions (POWER bridge) */
|
286 |
// XXX: to be tested
|
287 |
void glue(do_POWER_lscbx, MEMSUFFIX) (int dest, int ra, int rb) |
288 |
{ |
289 |
int i, c, d, reg;
|
290 |
|
291 |
d = 24;
|
292 |
reg = dest; |
293 |
for (i = 0; i < T1; i++) { |
294 |
c = glue(ldu8, MEMSUFFIX)((uint32_t)T0++); |
295 |
/* ra (if not 0) and rb are never modified */
|
296 |
if (likely(reg != rb && (ra == 0 || reg != ra))) { |
297 |
env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d);
|
298 |
} |
299 |
if (unlikely(c == T2))
|
300 |
break;
|
301 |
if (likely(d != 0)) { |
302 |
d -= 8;
|
303 |
} else {
|
304 |
d = 24;
|
305 |
reg++; |
306 |
reg = reg & 0x1F;
|
307 |
} |
308 |
} |
309 |
T0 = i; |
310 |
} |
311 |
|
312 |
/* XXX: TAGs are not managed */
|
313 |
void glue(do_POWER2_lfq, MEMSUFFIX) (void) |
314 |
{ |
315 |
FT0 = glue(ldfq, MEMSUFFIX)((uint32_t)T0); |
316 |
FT1 = glue(ldfq, MEMSUFFIX)((uint32_t)(T0 + 4));
|
317 |
} |
318 |
|
319 |
static always_inline float64 glue(ldfqr, MEMSUFFIX) (target_ulong EA)
|
320 |
{ |
321 |
CPU_DoubleU u; |
322 |
|
323 |
u.d = glue(ldfq, MEMSUFFIX)(EA); |
324 |
u.ll = bswap64(u.ll); |
325 |
|
326 |
return u.d;
|
327 |
} |
328 |
|
329 |
void glue(do_POWER2_lfq_le, MEMSUFFIX) (void) |
330 |
{ |
331 |
FT0 = glue(ldfqr, MEMSUFFIX)((uint32_t)(T0 + 4));
|
332 |
FT1 = glue(ldfqr, MEMSUFFIX)((uint32_t)T0); |
333 |
} |
334 |
|
335 |
void glue(do_POWER2_stfq, MEMSUFFIX) (void) |
336 |
{ |
337 |
glue(stfq, MEMSUFFIX)((uint32_t)T0, FT0); |
338 |
glue(stfq, MEMSUFFIX)((uint32_t)(T0 + 4), FT1);
|
339 |
} |
340 |
|
341 |
static always_inline void glue(stfqr, MEMSUFFIX) (target_ulong EA, float64 d) |
342 |
{ |
343 |
CPU_DoubleU u; |
344 |
|
345 |
u.d = d; |
346 |
u.ll = bswap64(u.ll); |
347 |
glue(stfq, MEMSUFFIX)(EA, u.d); |
348 |
} |
349 |
|
350 |
void glue(do_POWER2_stfq_le, MEMSUFFIX) (void) |
351 |
{ |
352 |
glue(stfqr, MEMSUFFIX)((uint32_t)(T0 + 4), FT0);
|
353 |
glue(stfqr, MEMSUFFIX)((uint32_t)T0, FT1); |
354 |
} |
355 |
|
356 |
#undef MEMSUFFIX
|