Statistics
| Branch: | Revision:

root / target-sparc / helper.c @ 3deaeab7

History | View | Annotate | Download (19.7 kB)

1
/*
2
 *  sparc helpers
3
 *
4
 *  Copyright (c) 2003-2005 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
#include <stdarg.h>
21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <string.h>
24
#include <inttypes.h>
25
#include <signal.h>
26
#include <assert.h>
27

    
28
#include "cpu.h"
29
#include "exec-all.h"
30

    
31
//#define DEBUG_MMU
32

    
33
/* Sparc MMU emulation */
34

    
35
/* thread support */
36

    
37
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
38

    
39
void cpu_lock(void)
40
{
41
    spin_lock(&global_cpu_lock);
42
}
43

    
44
void cpu_unlock(void)
45
{
46
    spin_unlock(&global_cpu_lock);
47
}
48

    
49
#if defined(CONFIG_USER_ONLY)
50

    
51
int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw,
52
                               int mmu_idx, int is_softmmu)
53
{
54
    if (rw & 2)
55
        env->exception_index = TT_TFAULT;
56
    else
57
        env->exception_index = TT_DFAULT;
58
    return 1;
59
}
60

    
61
#else
62

    
63
#ifndef TARGET_SPARC64
64
/*
65
 * Sparc V8 Reference MMU (SRMMU)
66
 */
67
static const int access_table[8][8] = {
68
    { 0, 0, 0, 0, 2, 0, 3, 3 },
69
    { 0, 0, 0, 0, 2, 0, 0, 0 },
70
    { 2, 2, 0, 0, 0, 2, 3, 3 },
71
    { 2, 2, 0, 0, 0, 2, 0, 0 },
72
    { 2, 0, 2, 0, 2, 2, 3, 3 },
73
    { 2, 0, 2, 0, 2, 0, 2, 0 },
74
    { 2, 2, 2, 0, 2, 2, 3, 3 },
75
    { 2, 2, 2, 0, 2, 2, 2, 0 }
76
};
77

    
78
static const int perm_table[2][8] = {
79
    {
80
        PAGE_READ,
81
        PAGE_READ | PAGE_WRITE,
82
        PAGE_READ | PAGE_EXEC,
83
        PAGE_READ | PAGE_WRITE | PAGE_EXEC,
84
        PAGE_EXEC,
85
        PAGE_READ | PAGE_WRITE,
86
        PAGE_READ | PAGE_EXEC,
87
        PAGE_READ | PAGE_WRITE | PAGE_EXEC
88
    },
89
    {
90
        PAGE_READ,
91
        PAGE_READ | PAGE_WRITE,
92
        PAGE_READ | PAGE_EXEC,
93
        PAGE_READ | PAGE_WRITE | PAGE_EXEC,
94
        PAGE_EXEC,
95
        PAGE_READ,
96
        0,
97
        0,
98
    }
99
};
100

    
101
int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot,
102
                          int *access_index, target_ulong address, int rw,
103
                          int mmu_idx)
104
{
105
    int access_perms = 0;
106
    target_phys_addr_t pde_ptr;
107
    uint32_t pde;
108
    target_ulong virt_addr;
109
    int error_code = 0, is_dirty, is_user;
110
    unsigned long page_offset;
111

    
112
    is_user = mmu_idx == MMU_USER_IDX;
113
    virt_addr = address & TARGET_PAGE_MASK;
114

    
115
    if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
116
        // Boot mode: instruction fetches are taken from PROM
117
        if (rw == 2 && (env->mmuregs[0] & env->mmu_bm)) {
118
            *physical = env->prom_addr | (address & 0x7ffffULL);
119
            *prot = PAGE_READ | PAGE_EXEC;
120
            return 0;
121
        }
122
        *physical = address;
123
        *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
124
        return 0;
125
    }
126

    
127
    *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
128
    *physical = 0xffffffffffff0000ULL;
129

    
130
    /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
131
    /* Context base + context number */
132
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
133
    pde = ldl_phys(pde_ptr);
134

    
135
    /* Ctx pde */
136
    switch (pde & PTE_ENTRYTYPE_MASK) {
137
    default:
138
    case 0: /* Invalid */
139
        return 1 << 2;
140
    case 2: /* L0 PTE, maybe should not happen? */
141
    case 3: /* Reserved */
142
        return 4 << 2;
143
    case 1: /* L0 PDE */
144
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
145
        pde = ldl_phys(pde_ptr);
146

    
147
        switch (pde & PTE_ENTRYTYPE_MASK) {
148
        default:
149
        case 0: /* Invalid */
150
            return (1 << 8) | (1 << 2);
151
        case 3: /* Reserved */
152
            return (1 << 8) | (4 << 2);
153
        case 1: /* L1 PDE */
154
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
155
            pde = ldl_phys(pde_ptr);
156

    
157
            switch (pde & PTE_ENTRYTYPE_MASK) {
158
            default:
159
            case 0: /* Invalid */
160
                return (2 << 8) | (1 << 2);
161
            case 3: /* Reserved */
162
                return (2 << 8) | (4 << 2);
163
            case 1: /* L2 PDE */
164
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
165
                pde = ldl_phys(pde_ptr);
166

    
167
                switch (pde & PTE_ENTRYTYPE_MASK) {
168
                default:
169
                case 0: /* Invalid */
170
                    return (3 << 8) | (1 << 2);
171
                case 1: /* PDE, should not happen */
172
                case 3: /* Reserved */
173
                    return (3 << 8) | (4 << 2);
174
                case 2: /* L3 PTE */
175
                    virt_addr = address & TARGET_PAGE_MASK;
176
                    page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1);
177
                }
178
                break;
179
            case 2: /* L2 PTE */
180
                virt_addr = address & ~0x3ffff;
181
                page_offset = address & 0x3ffff;
182
            }
183
            break;
184
        case 2: /* L1 PTE */
185
            virt_addr = address & ~0xffffff;
186
            page_offset = address & 0xffffff;
187
        }
188
    }
189

    
190
    /* update page modified and dirty bits */
191
    is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
192
    if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
193
        pde |= PG_ACCESSED_MASK;
194
        if (is_dirty)
195
            pde |= PG_MODIFIED_MASK;
196
        stl_phys_notdirty(pde_ptr, pde);
197
    }
198
    /* check access */
199
    access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
200
    error_code = access_table[*access_index][access_perms];
201
    if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user))
202
        return error_code;
203

    
204
    /* the page can be put in the TLB */
205
    *prot = perm_table[is_user][access_perms];
206
    if (!(pde & PG_MODIFIED_MASK)) {
207
        /* only set write access if already dirty... otherwise wait
208
           for dirty access */
209
        *prot &= ~PAGE_WRITE;
210
    }
211

    
212
    /* Even if large ptes, we map only one 4KB page in the cache to
213
       avoid filling it too fast */
214
    *physical = ((target_phys_addr_t)(pde & PTE_ADDR_MASK) << 4) + page_offset;
215
    return error_code;
216
}
217

    
218
/* Perform address translation */
219
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
220
                              int mmu_idx, int is_softmmu)
221
{
222
    target_phys_addr_t paddr;
223
    target_ulong vaddr;
224
    int error_code = 0, prot, ret = 0, access_index;
225

    
226
    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, mmu_idx);
227
    if (error_code == 0) {
228
        vaddr = address & TARGET_PAGE_MASK;
229
        paddr &= TARGET_PAGE_MASK;
230
#ifdef DEBUG_MMU
231
        printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
232
               TARGET_FMT_lx "\n", address, paddr, vaddr);
233
#endif
234
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
235
        return ret;
236
    }
237

    
238
    if (env->mmuregs[3]) /* Fault status register */
239
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
240
    env->mmuregs[3] |= (access_index << 5) | error_code | 2;
241
    env->mmuregs[4] = address; /* Fault address register */
242

    
243
    if ((env->mmuregs[0] & MMU_NF) || env->psret == 0)  {
244
        // No fault mode: if a mapping is available, just override
245
        // permissions. If no mapping is available, redirect accesses to
246
        // neverland. Fake/overridden mappings will be flushed when
247
        // switching to normal mode.
248
        vaddr = address & TARGET_PAGE_MASK;
249
        prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
250
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
251
        return ret;
252
    } else {
253
        if (rw & 2)
254
            env->exception_index = TT_TFAULT;
255
        else
256
            env->exception_index = TT_DFAULT;
257
        return 1;
258
    }
259
}
260

    
261
target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
262
{
263
    target_phys_addr_t pde_ptr;
264
    uint32_t pde;
265

    
266
    /* Context base + context number */
267
    pde_ptr = (target_phys_addr_t)(env->mmuregs[1] << 4) +
268
        (env->mmuregs[2] << 2);
269
    pde = ldl_phys(pde_ptr);
270

    
271
    switch (pde & PTE_ENTRYTYPE_MASK) {
272
    default:
273
    case 0: /* Invalid */
274
    case 2: /* PTE, maybe should not happen? */
275
    case 3: /* Reserved */
276
        return 0;
277
    case 1: /* L1 PDE */
278
        if (mmulev == 3)
279
            return pde;
280
        pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
281
        pde = ldl_phys(pde_ptr);
282

    
283
        switch (pde & PTE_ENTRYTYPE_MASK) {
284
        default:
285
        case 0: /* Invalid */
286
        case 3: /* Reserved */
287
            return 0;
288
        case 2: /* L1 PTE */
289
            return pde;
290
        case 1: /* L2 PDE */
291
            if (mmulev == 2)
292
                return pde;
293
            pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
294
            pde = ldl_phys(pde_ptr);
295

    
296
            switch (pde & PTE_ENTRYTYPE_MASK) {
297
            default:
298
            case 0: /* Invalid */
299
            case 3: /* Reserved */
300
                return 0;
301
            case 2: /* L2 PTE */
302
                return pde;
303
            case 1: /* L3 PDE */
304
                if (mmulev == 1)
305
                    return pde;
306
                pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
307
                pde = ldl_phys(pde_ptr);
308

    
309
                switch (pde & PTE_ENTRYTYPE_MASK) {
310
                default:
311
                case 0: /* Invalid */
312
                case 1: /* PDE, should not happen */
313
                case 3: /* Reserved */
314
                    return 0;
315
                case 2: /* L3 PTE */
316
                    return pde;
317
                }
318
            }
319
        }
320
    }
321
    return 0;
322
}
323

    
324
#ifdef DEBUG_MMU
325
void dump_mmu(CPUState *env)
326
{
327
    target_ulong va, va1, va2;
328
    unsigned int n, m, o;
329
    target_phys_addr_t pde_ptr, pa;
330
    uint32_t pde;
331

    
332
    printf("MMU dump:\n");
333
    pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
334
    pde = ldl_phys(pde_ptr);
335
    printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
336
           (target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
337
    for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
338
        pde = mmu_probe(env, va, 2);
339
        if (pde) {
340
            pa = cpu_get_phys_page_debug(env, va);
341
            printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
342
                   " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
343
            for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
344
                pde = mmu_probe(env, va1, 1);
345
                if (pde) {
346
                    pa = cpu_get_phys_page_debug(env, va1);
347
                    printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
348
                           " PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
349
                    for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
350
                        pde = mmu_probe(env, va2, 0);
351
                        if (pde) {
352
                            pa = cpu_get_phys_page_debug(env, va2);
353
                            printf("  VA: " TARGET_FMT_lx ", PA: "
354
                                   TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
355
                                   va2, pa, pde);
356
                        }
357
                    }
358
                }
359
            }
360
        }
361
    }
362
    printf("MMU dump ends\n");
363
}
364
#endif /* DEBUG_MMU */
365

    
366
#else /* !TARGET_SPARC64 */
367
/*
368
 * UltraSparc IIi I/DMMUs
369
 */
370
static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot,
371
                          int *access_index, target_ulong address, int rw,
372
                          int is_user)
373
{
374
    target_ulong mask;
375
    unsigned int i;
376

    
377
    if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
378
        *physical = address;
379
        *prot = PAGE_READ | PAGE_WRITE;
380
        return 0;
381
    }
382

    
383
    for (i = 0; i < 64; i++) {
384
        switch ((env->dtlb_tte[i] >> 61) & 3) {
385
        default:
386
        case 0x0: // 8k
387
            mask = 0xffffffffffffe000ULL;
388
            break;
389
        case 0x1: // 64k
390
            mask = 0xffffffffffff0000ULL;
391
            break;
392
        case 0x2: // 512k
393
            mask = 0xfffffffffff80000ULL;
394
            break;
395
        case 0x3: // 4M
396
            mask = 0xffffffffffc00000ULL;
397
            break;
398
        }
399
        // ctx match, vaddr match?
400
        if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
401
            (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
402
            // valid, access ok?
403
            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
404
                ((env->dtlb_tte[i] & 0x4) && is_user) ||
405
                (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
406
                if (env->dmmuregs[3]) /* Fault status register */
407
                    env->dmmuregs[3] = 2; /* overflow (not read before another fault) */
408
                env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1;
409
                env->dmmuregs[4] = address; /* Fault address register */
410
                env->exception_index = TT_DFAULT;
411
#ifdef DEBUG_MMU
412
                printf("DFAULT at 0x%" PRIx64 "\n", address);
413
#endif
414
                return 1;
415
            }
416
            *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
417
            *prot = PAGE_READ;
418
            if (env->dtlb_tte[i] & 0x2)
419
                *prot |= PAGE_WRITE;
420
            return 0;
421
        }
422
    }
423
#ifdef DEBUG_MMU
424
    printf("DMISS at 0x%" PRIx64 "\n", address);
425
#endif
426
    env->exception_index = TT_DMISS;
427
    return 1;
428
}
429

    
430
static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical, int *prot,
431
                          int *access_index, target_ulong address, int rw,
432
                          int is_user)
433
{
434
    target_ulong mask;
435
    unsigned int i;
436

    
437
    if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */
438
        *physical = address;
439
        *prot = PAGE_EXEC;
440
        return 0;
441
    }
442

    
443
    for (i = 0; i < 64; i++) {
444
        switch ((env->itlb_tte[i] >> 61) & 3) {
445
        default:
446
        case 0x0: // 8k
447
            mask = 0xffffffffffffe000ULL;
448
            break;
449
        case 0x1: // 64k
450
            mask = 0xffffffffffff0000ULL;
451
            break;
452
        case 0x2: // 512k
453
            mask = 0xfffffffffff80000ULL;
454
            break;
455
        case 0x3: // 4M
456
            mask = 0xffffffffffc00000ULL;
457
                break;
458
        }
459
        // ctx match, vaddr match?
460
        if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
461
            (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
462
            // valid, access ok?
463
            if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
464
                ((env->itlb_tte[i] & 0x4) && is_user)) {
465
                if (env->immuregs[3]) /* Fault status register */
466
                    env->immuregs[3] = 2; /* overflow (not read before another fault) */
467
                env->immuregs[3] |= (is_user << 3) | 1;
468
                env->exception_index = TT_TFAULT;
469
#ifdef DEBUG_MMU
470
                printf("TFAULT at 0x%" PRIx64 "\n", address);
471
#endif
472
                return 1;
473
            }
474
            *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL);
475
            *prot = PAGE_EXEC;
476
            return 0;
477
        }
478
    }
479
#ifdef DEBUG_MMU
480
    printf("TMISS at 0x%" PRIx64 "\n", address);
481
#endif
482
    env->exception_index = TT_TMISS;
483
    return 1;
484
}
485

    
486
int get_physical_address(CPUState *env, target_phys_addr_t *physical, int *prot,
487
                          int *access_index, target_ulong address, int rw,
488
                          int mmu_idx)
489
{
490
    int is_user = mmu_idx == MMU_USER_IDX;
491

    
492
    if (rw == 2)
493
        return get_physical_address_code(env, physical, prot, access_index, address, rw, is_user);
494
    else
495
        return get_physical_address_data(env, physical, prot, access_index, address, rw, is_user);
496
}
497

    
498
/* Perform address translation */
499
int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
500
                              int mmu_idx, int is_softmmu)
501
{
502
    target_ulong virt_addr, vaddr;
503
    target_phys_addr_t paddr;
504
    int error_code = 0, prot, ret = 0, access_index;
505

    
506
    error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, mmu_idx);
507
    if (error_code == 0) {
508
        virt_addr = address & TARGET_PAGE_MASK;
509
        vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
510
#ifdef DEBUG_MMU
511
        printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64 "\n", address, paddr, vaddr);
512
#endif
513
        ret = tlb_set_page_exec(env, vaddr, paddr, prot, mmu_idx, is_softmmu);
514
        return ret;
515
    }
516
    // XXX
517
    return 1;
518
}
519

    
520
#ifdef DEBUG_MMU
521
void dump_mmu(CPUState *env)
522
{
523
    unsigned int i;
524
    const char *mask;
525

    
526
    printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n", env->dmmuregs[1], env->dmmuregs[2]);
527
    if ((env->lsu & DMMU_E) == 0) {
528
        printf("DMMU disabled\n");
529
    } else {
530
        printf("DMMU dump:\n");
531
        for (i = 0; i < 64; i++) {
532
            switch ((env->dtlb_tte[i] >> 61) & 3) {
533
            default:
534
            case 0x0:
535
                mask = "  8k";
536
                break;
537
            case 0x1:
538
                mask = " 64k";
539
                break;
540
            case 0x2:
541
                mask = "512k";
542
                break;
543
            case 0x3:
544
                mask = "  4M";
545
                break;
546
            }
547
            if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
548
                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, %s, ctx %" PRId64 "\n",
549
                       env->dtlb_tag[i] & ~0x1fffULL,
550
                       env->dtlb_tte[i] & 0x1ffffffe000ULL,
551
                       mask,
552
                       env->dtlb_tte[i] & 0x4? "priv": "user",
553
                       env->dtlb_tte[i] & 0x2? "RW": "RO",
554
                       env->dtlb_tte[i] & 0x40? "locked": "unlocked",
555
                       env->dtlb_tag[i] & 0x1fffULL);
556
            }
557
        }
558
    }
559
    if ((env->lsu & IMMU_E) == 0) {
560
        printf("IMMU disabled\n");
561
    } else {
562
        printf("IMMU dump:\n");
563
        for (i = 0; i < 64; i++) {
564
            switch ((env->itlb_tte[i] >> 61) & 3) {
565
            default:
566
            case 0x0:
567
                mask = "  8k";
568
                break;
569
            case 0x1:
570
                mask = " 64k";
571
                break;
572
            case 0x2:
573
                mask = "512k";
574
                break;
575
            case 0x3:
576
                mask = "  4M";
577
                break;
578
            }
579
            if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
580
                printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, ctx %" PRId64 "\n",
581
                       env->itlb_tag[i] & ~0x1fffULL,
582
                       env->itlb_tte[i] & 0x1ffffffe000ULL,
583
                       mask,
584
                       env->itlb_tte[i] & 0x4? "priv": "user",
585
                       env->itlb_tte[i] & 0x40? "locked": "unlocked",
586
                       env->itlb_tag[i] & 0x1fffULL);
587
            }
588
        }
589
    }
590
}
591
#endif /* DEBUG_MMU */
592

    
593
#endif /* TARGET_SPARC64 */
594
#endif /* !CONFIG_USER_ONLY */
595

    
596
void memcpy32(target_ulong *dst, const target_ulong *src)
597
{
598
    dst[0] = src[0];
599
    dst[1] = src[1];
600
    dst[2] = src[2];
601
    dst[3] = src[3];
602
    dst[4] = src[4];
603
    dst[5] = src[5];
604
    dst[6] = src[6];
605
    dst[7] = src[7];
606
}
607

    
608
#ifdef TARGET_SPARC64
609
#if !defined(CONFIG_USER_ONLY)
610
#include "qemu-common.h"
611
#include "hw/irq.h"
612
#include "qemu-timer.h"
613
#endif
614

    
615
void do_tick_set_count(void *opaque, uint64_t count)
616
{
617
#if !defined(CONFIG_USER_ONLY)
618
    ptimer_set_count(opaque, -count);
619
#endif
620
}
621

    
622
uint64_t do_tick_get_count(void *opaque)
623
{
624
#if !defined(CONFIG_USER_ONLY)
625
    return -ptimer_get_count(opaque);
626
#else
627
    return 0;
628
#endif
629
}
630

    
631
void do_tick_set_limit(void *opaque, uint64_t limit)
632
{
633
#if !defined(CONFIG_USER_ONLY)
634
    ptimer_set_limit(opaque, -limit, 0);
635
#endif
636
}
637
#endif