Statistics
| Branch: | Revision:

root / target-ppc / op_helper_mem.h @ f0685f6e

History | View | Annotate | Download (13.8 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
/* 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
    T0 &= ~(env->icache_line_size - 1);
256
    tmp = glue(ldl, MEMSUFFIX)((uint32_t)T0);
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
    T0 &= ~(env->icache_line_size - 1);
271
    tmp = glue(ldq, MEMSUFFIX)((uint64_t)T0);
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