~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to target-arm/helper.c

Tags: upstream-0.9.0+20070816
ImportĀ upstreamĀ versionĀ 0.9.0+20070816

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
#include "cpu.h"
6
6
#include "exec-all.h"
7
7
 
 
8
static inline void set_feature(CPUARMState *env, int feature)
 
9
{
 
10
    env->features |= 1u << feature;
 
11
}
 
12
 
 
13
static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
 
14
{
 
15
    env->cp15.c0_cpuid = id;
 
16
    switch (id) {
 
17
    case ARM_CPUID_ARM926:
 
18
        set_feature(env, ARM_FEATURE_VFP);
 
19
        env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
 
20
        env->cp15.c0_cachetype = 0x1dd20d2;
 
21
        env->cp15.c1_sys = 0x00090078;
 
22
        break;
 
23
    case ARM_CPUID_ARM946:
 
24
        set_feature(env, ARM_FEATURE_MPU);
 
25
        env->cp15.c0_cachetype = 0x0f004006;
 
26
        env->cp15.c1_sys = 0x00000078;
 
27
        break;
 
28
    case ARM_CPUID_ARM1026:
 
29
        set_feature(env, ARM_FEATURE_VFP);
 
30
        set_feature(env, ARM_FEATURE_AUXCR);
 
31
        env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
 
32
        env->cp15.c0_cachetype = 0x1dd20d2;
 
33
        env->cp15.c1_sys = 0x00090078;
 
34
        break;
 
35
    case ARM_CPUID_TI915T:
 
36
    case ARM_CPUID_TI925T:
 
37
        set_feature(env, ARM_FEATURE_OMAPCP);
 
38
        env->cp15.c0_cpuid = ARM_CPUID_TI925T; /* Depends on wiring.  */
 
39
        env->cp15.c0_cachetype = 0x5109149;
 
40
        env->cp15.c1_sys = 0x00000070;
 
41
        env->cp15.c15_i_max = 0x000;
 
42
        env->cp15.c15_i_min = 0xff0;
 
43
        break;
 
44
    case ARM_CPUID_PXA250:
 
45
    case ARM_CPUID_PXA255:
 
46
    case ARM_CPUID_PXA260:
 
47
    case ARM_CPUID_PXA261:
 
48
    case ARM_CPUID_PXA262:
 
49
        set_feature(env, ARM_FEATURE_XSCALE);
 
50
        /* JTAG_ID is ((id << 28) | 0x09265013) */
 
51
        env->cp15.c0_cachetype = 0xd172172;
 
52
        env->cp15.c1_sys = 0x00000078;
 
53
        break;
 
54
    case ARM_CPUID_PXA270_A0:
 
55
    case ARM_CPUID_PXA270_A1:
 
56
    case ARM_CPUID_PXA270_B0:
 
57
    case ARM_CPUID_PXA270_B1:
 
58
    case ARM_CPUID_PXA270_C0:
 
59
    case ARM_CPUID_PXA270_C5:
 
60
        set_feature(env, ARM_FEATURE_XSCALE);
 
61
        /* JTAG_ID is ((id << 28) | 0x09265013) */
 
62
        set_feature(env, ARM_FEATURE_IWMMXT);
 
63
        env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
 
64
        env->cp15.c0_cachetype = 0xd172172;
 
65
        env->cp15.c1_sys = 0x00000078;
 
66
        break;
 
67
    default:
 
68
        cpu_abort(env, "Bad CPU ID: %x\n", id);
 
69
        break;
 
70
    }
 
71
}
 
72
 
8
73
void cpu_reset(CPUARMState *env)
9
74
{
 
75
    uint32_t id;
 
76
    id = env->cp15.c0_cpuid;
 
77
    memset(env, 0, offsetof(CPUARMState, breakpoints));
 
78
    if (id)
 
79
        cpu_reset_model_id(env, id);
10
80
#if defined (CONFIG_USER_ONLY)
11
81
    env->uncached_cpsr = ARM_CPU_MODE_USR;
12
82
    env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
16
86
    env->vfp.xregs[ARM_VFP_FPEXC] = 0;
17
87
#endif
18
88
    env->regs[15] = 0;
 
89
    tlb_flush(env, 1);
19
90
}
20
91
 
21
92
CPUARMState *cpu_arm_init(void)
27
98
        return NULL;
28
99
    cpu_exec_init(env);
29
100
    cpu_reset(env);
30
 
    tlb_flush(env, 1);
31
101
    return env;
32
102
}
33
103
 
34
 
static inline void set_feature(CPUARMState *env, int feature)
 
104
struct arm_cpu_t {
 
105
    uint32_t id;
 
106
    const char *name;
 
107
};
 
108
 
 
109
static const struct arm_cpu_t arm_cpu_names[] = {
 
110
    { ARM_CPUID_ARM926, "arm926"},
 
111
    { ARM_CPUID_ARM946, "arm946"},
 
112
    { ARM_CPUID_ARM1026, "arm1026"},
 
113
    { ARM_CPUID_TI925T, "ti925t" },
 
114
    { ARM_CPUID_PXA250, "pxa250" },
 
115
    { ARM_CPUID_PXA255, "pxa255" },
 
116
    { ARM_CPUID_PXA260, "pxa260" },
 
117
    { ARM_CPUID_PXA261, "pxa261" },
 
118
    { ARM_CPUID_PXA262, "pxa262" },
 
119
    { ARM_CPUID_PXA270, "pxa270" },
 
120
    { ARM_CPUID_PXA270_A0, "pxa270-a0" },
 
121
    { ARM_CPUID_PXA270_A1, "pxa270-a1" },
 
122
    { ARM_CPUID_PXA270_B0, "pxa270-b0" },
 
123
    { ARM_CPUID_PXA270_B1, "pxa270-b1" },
 
124
    { ARM_CPUID_PXA270_C0, "pxa270-c0" },
 
125
    { ARM_CPUID_PXA270_C5, "pxa270-c5" },
 
126
    { 0, NULL}
 
127
};
 
128
 
 
129
void arm_cpu_list(void)
35
130
{
36
 
    env->features |= 1u << feature;
 
131
    int i;
 
132
 
 
133
    printf ("Available CPUs:\n");
 
134
    for (i = 0; arm_cpu_names[i].name; i++) {
 
135
        printf("  %s\n", arm_cpu_names[i].name);
 
136
    }
37
137
}
38
138
 
39
 
void cpu_arm_set_model(CPUARMState *env, uint32_t id)
 
139
void cpu_arm_set_model(CPUARMState *env, const char *name)
40
140
{
41
 
    env->cp15.c0_cpuid = id;
42
 
    switch (id) {
43
 
    case ARM_CPUID_ARM926:
44
 
        set_feature(env, ARM_FEATURE_VFP);
45
 
        env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
46
 
        break;
47
 
    case ARM_CPUID_ARM1026:
48
 
        set_feature(env, ARM_FEATURE_VFP);
49
 
        set_feature(env, ARM_FEATURE_AUXCR);
50
 
        env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
51
 
        break;
52
 
    default:
53
 
        cpu_abort(env, "Bad CPU ID: %x\n", id);
54
 
        break;
55
 
    }
 
141
    int i;
 
142
    uint32_t id;
 
143
 
 
144
    id = 0;
 
145
    i = 0;
 
146
    for (i = 0; arm_cpu_names[i].name; i++) {
 
147
        if (strcmp(name, arm_cpu_names[i].name) == 0) {
 
148
            id = arm_cpu_names[i].id;
 
149
            break;
 
150
        }
 
151
    }
 
152
    if (!id) {
 
153
        cpu_abort(env, "Unknown CPU '%s'", name);
 
154
        return;
 
155
    }
 
156
    cpu_reset_model_id(env, id);
56
157
}
57
158
 
58
159
void cpu_arm_close(CPUARMState *env)
80
181
    return 1;
81
182
}
82
183
 
83
 
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 
184
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
84
185
{
85
186
    return addr;
86
187
}
87
188
 
88
189
/* These should probably raise undefined insn exceptions.  */
 
190
void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
 
191
{
 
192
    int op1 = (insn >> 8) & 0xf;
 
193
    cpu_abort(env, "cp%i insn %08x\n", op1, insn);
 
194
    return;
 
195
}
 
196
 
 
197
uint32_t helper_get_cp(CPUState *env, uint32_t insn)
 
198
{
 
199
    int op1 = (insn >> 8) & 0xf;
 
200
    cpu_abort(env, "cp%i insn %08x\n", op1, insn);
 
201
    return 0;
 
202
}
 
203
 
89
204
void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
90
205
{
91
206
    cpu_abort(env, "cp15 insn %08x\n", insn);
297
412
        address += env->cp15.c13_fcse;
298
413
 
299
414
    if ((env->cp15.c1_sys & 1) == 0) {
300
 
        /* MMU diusabled.  */
 
415
        /* MMU/MPU disabled.  */
301
416
        *phys_ptr = address;
302
417
        *prot = PAGE_READ | PAGE_WRITE;
 
418
    } else if (arm_feature(env, ARM_FEATURE_MPU)) {
 
419
        int n;
 
420
        uint32_t mask;
 
421
        uint32_t base;
 
422
 
 
423
        *phys_ptr = address;
 
424
        for (n = 7; n >= 0; n--) {
 
425
            base = env->cp15.c6_region[n];
 
426
            if ((base & 1) == 0)
 
427
                continue;
 
428
            mask = 1 << ((base >> 1) & 0x1f);
 
429
            /* Keep this shift separate from the above to avoid an
 
430
               (undefined) << 32.  */
 
431
            mask = (mask << 1) - 1;
 
432
            if (((base ^ address) & ~mask) == 0)
 
433
                break;
 
434
        }
 
435
        if (n < 0)
 
436
            return 2;
 
437
 
 
438
        if (access_type == 2) {
 
439
            mask = env->cp15.c5_insn;
 
440
        } else {
 
441
            mask = env->cp15.c5_data;
 
442
        }
 
443
        mask = (mask >> (n * 4)) & 0xf;
 
444
        switch (mask) {
 
445
        case 0:
 
446
            return 1;
 
447
        case 1:
 
448
            if (is_user)
 
449
              return 1;
 
450
            *prot = PAGE_READ | PAGE_WRITE;
 
451
            break;
 
452
        case 2:
 
453
            *prot = PAGE_READ;
 
454
            if (!is_user)
 
455
                *prot |= PAGE_WRITE;
 
456
            break;
 
457
        case 3:
 
458
            *prot = PAGE_READ | PAGE_WRITE;
 
459
            break;
 
460
        case 5:
 
461
            if (is_user)
 
462
                return 1;
 
463
            *prot = PAGE_READ;
 
464
            break;
 
465
        case 6:
 
466
            *prot = PAGE_READ;
 
467
            break;
 
468
        default:
 
469
            /* Bad permission.  */
 
470
            return 1;
 
471
        }
303
472
    } else {
304
473
        /* Pagetable walk.  */
305
474
        /* Lookup l1 descriptor.  */
306
 
        table = (env->cp15.c2 & 0xffffc000) | ((address >> 18) & 0x3ffc);
 
475
        table = (env->cp15.c2_base & 0xffffc000) | ((address >> 18) & 0x3ffc);
307
476
        desc = ldl_phys(table);
308
477
        type = (desc & 3);
309
478
        domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
326
495
            code = 13;
327
496
        } else {
328
497
            /* Lookup l2 entry.  */
329
 
            table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
 
498
            if (type == 1) {
 
499
                /* Coarse pagetable.  */
 
500
                table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
 
501
            } else {
 
502
                /* Fine pagetable.  */
 
503
                table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
 
504
            }
330
505
            desc = ldl_phys(table);
331
506
            switch (desc & 3) {
332
507
            case 0: /* Page translation fault.  */
342
517
                break;
343
518
            case 3: /* 1k page.  */
344
519
                if (type == 1) {
345
 
                    /* Page translation fault.  */
346
 
                    code = 7;
347
 
                    goto do_fault;
348
 
                }
349
 
                phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
 
520
                    if (arm_feature(env, ARM_FEATURE_XSCALE))
 
521
                        phys_addr = (desc & 0xfffff000) | (address & 0xfff);
 
522
                    else {
 
523
                        /* Page translation fault.  */
 
524
                        code = 7;
 
525
                        goto do_fault;
 
526
                    }
 
527
                } else
 
528
                    phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
350
529
                ap = (desc >> 4) & 3;
351
530
                break;
352
531
            default:
395
574
    return 1;
396
575
}
397
576
 
398
 
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
 
577
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
399
578
{
400
579
    uint32_t phys_addr;
401
580
    int prot;
409
588
    return phys_addr;
410
589
}
411
590
 
 
591
void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
 
592
{
 
593
    int cp_num = (insn >> 8) & 0xf;
 
594
    int cp_info = (insn >> 5) & 7;
 
595
    int src = (insn >> 16) & 0xf;
 
596
    int operand = insn & 0xf;
 
597
 
 
598
    if (env->cp[cp_num].cp_write)
 
599
        env->cp[cp_num].cp_write(env->cp[cp_num].opaque,
 
600
                                 cp_info, src, operand, val);
 
601
}
 
602
 
 
603
uint32_t helper_get_cp(CPUState *env, uint32_t insn)
 
604
{
 
605
    int cp_num = (insn >> 8) & 0xf;
 
606
    int cp_info = (insn >> 5) & 7;
 
607
    int dest = (insn >> 16) & 0xf;
 
608
    int operand = insn & 0xf;
 
609
 
 
610
    if (env->cp[cp_num].cp_read)
 
611
        return env->cp[cp_num].cp_read(env->cp[cp_num].opaque,
 
612
                                       cp_info, dest, operand);
 
613
    return 0;
 
614
}
 
615
 
 
616
/* Return basic MPU access permission bits.  */
 
617
static uint32_t simple_mpu_ap_bits(uint32_t val)
 
618
{
 
619
    uint32_t ret;
 
620
    uint32_t mask;
 
621
    int i;
 
622
    ret = 0;
 
623
    mask = 3;
 
624
    for (i = 0; i < 16; i += 2) {
 
625
        ret |= (val >> i) & mask;
 
626
        mask <<= 2;
 
627
    }
 
628
    return ret;
 
629
}
 
630
 
 
631
/* Pad basic MPU access permission bits to extended format.  */
 
632
static uint32_t extended_mpu_ap_bits(uint32_t val)
 
633
{
 
634
    uint32_t ret;
 
635
    uint32_t mask;
 
636
    int i;
 
637
    ret = 0;
 
638
    mask = 3;
 
639
    for (i = 0; i < 16; i += 2) {
 
640
        ret |= (val & mask) << i;
 
641
        mask <<= 2;
 
642
    }
 
643
    return ret;
 
644
}
 
645
 
412
646
void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
413
647
{
414
648
    uint32_t op2;
 
649
    uint32_t crm;
415
650
 
416
651
    op2 = (insn >> 5) & 7;
 
652
    crm = insn & 0xf;
417
653
    switch ((insn >> 16) & 0xf) {
418
654
    case 0: /* ID codes.  */
 
655
        if (arm_feature(env, ARM_FEATURE_XSCALE))
 
656
            break;
 
657
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
 
658
            break;
419
659
        goto bad_reg;
420
660
    case 1: /* System configuration.  */
 
661
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
 
662
            op2 = 0;
421
663
        switch (op2) {
422
664
        case 0:
423
 
            env->cp15.c1_sys = val;
 
665
            if (!arm_feature(env, ARM_FEATURE_XSCALE) || crm == 0)
 
666
                env->cp15.c1_sys = val;
424
667
            /* ??? Lots of these bits are not implemented.  */
425
668
            /* This may enable/disable the MMU, so do a TLB flush.  */
426
669
            tlb_flush(env, 1);
427
670
            break;
 
671
        case 1:
 
672
            if (arm_feature(env, ARM_FEATURE_XSCALE)) {
 
673
                env->cp15.c1_xscaleauxcr = val;
 
674
                break;
 
675
            }
 
676
            goto bad_reg;
428
677
        case 2:
 
678
            if (arm_feature(env, ARM_FEATURE_XSCALE))
 
679
                goto bad_reg;
429
680
            env->cp15.c1_coproc = val;
430
681
            /* ??? Is this safe when called from within a TB?  */
431
682
            tb_flush(env);
 
683
            break;
432
684
        default:
433
685
            goto bad_reg;
434
686
        }
435
687
        break;
436
 
    case 2: /* MMU Page table control.  */
437
 
        env->cp15.c2 = val;
 
688
    case 2: /* MMU Page table control / MPU cache control.  */
 
689
        if (arm_feature(env, ARM_FEATURE_MPU)) {
 
690
            switch (op2) {
 
691
            case 0:
 
692
                env->cp15.c2_data = val;
 
693
                break;
 
694
            case 1:
 
695
                env->cp15.c2_insn = val;
 
696
                break;
 
697
            default:
 
698
                goto bad_reg;
 
699
            }
 
700
        } else {
 
701
            env->cp15.c2_base = val;
 
702
        }
438
703
        break;
439
 
    case 3: /* MMU Domain access control.  */
 
704
    case 3: /* MMU Domain access control / MPU write buffer control.  */
440
705
        env->cp15.c3 = val;
441
706
        break;
442
707
    case 4: /* Reserved.  */
443
708
        goto bad_reg;
444
 
    case 5: /* MMU Fault status.  */
 
709
    case 5: /* MMU Fault status / MPU access permission.  */
 
710
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
 
711
            op2 = 0;
445
712
        switch (op2) {
446
713
        case 0:
 
714
            if (arm_feature(env, ARM_FEATURE_MPU))
 
715
                val = extended_mpu_ap_bits(val);
447
716
            env->cp15.c5_data = val;
448
717
            break;
449
718
        case 1:
 
719
            if (arm_feature(env, ARM_FEATURE_MPU))
 
720
                val = extended_mpu_ap_bits(val);
 
721
            env->cp15.c5_insn = val;
 
722
            break;
 
723
        case 2:
 
724
            if (!arm_feature(env, ARM_FEATURE_MPU))
 
725
                goto bad_reg;
 
726
            env->cp15.c5_data = val;
 
727
            break;
 
728
        case 3:
 
729
            if (!arm_feature(env, ARM_FEATURE_MPU))
 
730
                goto bad_reg;
450
731
            env->cp15.c5_insn = val;
451
732
            break;
452
733
        default:
453
734
            goto bad_reg;
454
735
        }
455
736
        break;
456
 
    case 6: /* MMU Fault address.  */
457
 
        switch (op2) {
458
 
        case 0:
459
 
            env->cp15.c6_data = val;
460
 
            break;
461
 
        case 1:
462
 
            env->cp15.c6_insn = val;
463
 
            break;
464
 
        default:
465
 
            goto bad_reg;
 
737
    case 6: /* MMU Fault address / MPU base/size.  */
 
738
        if (arm_feature(env, ARM_FEATURE_MPU)) {
 
739
            if (crm >= 8)
 
740
                goto bad_reg;
 
741
            env->cp15.c6_region[crm] = val;
 
742
        } else {
 
743
            if (arm_feature(env, ARM_FEATURE_OMAPCP))
 
744
                op2 = 0;
 
745
            switch (op2) {
 
746
            case 0:
 
747
                env->cp15.c6_data = val;
 
748
                break;
 
749
            case 1:
 
750
                env->cp15.c6_insn = val;
 
751
                break;
 
752
            default:
 
753
                goto bad_reg;
 
754
            }
466
755
        }
467
756
        break;
468
757
    case 7: /* Cache control.  */
 
758
        env->cp15.c15_i_max = 0x000;
 
759
        env->cp15.c15_i_min = 0xff0;
469
760
        /* No cache, so nothing to do.  */
470
761
        break;
471
762
    case 8: /* MMU TLB control.  */
491
782
            goto bad_reg;
492
783
        }
493
784
        break;
494
 
    case 9: /* Cache lockdown.  */
495
 
        switch (op2) {
496
 
        case 0:
497
 
            env->cp15.c9_data = val;
498
 
            break;
499
 
        case 1:
500
 
            env->cp15.c9_insn = val;
501
 
            break;
 
785
    case 9:
 
786
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
 
787
            break;
 
788
        switch (crm) {
 
789
        case 0: /* Cache lockdown.  */
 
790
            switch (op2) {
 
791
            case 0:
 
792
                env->cp15.c9_data = val;
 
793
                break;
 
794
            case 1:
 
795
                env->cp15.c9_insn = val;
 
796
                break;
 
797
            default:
 
798
                goto bad_reg;
 
799
            }
 
800
            break;
 
801
        case 1: /* TCM memory region registers.  */
 
802
            /* Not implemented.  */
 
803
            goto bad_reg;
502
804
        default:
503
805
            goto bad_reg;
504
806
        }
506
808
    case 10: /* MMU TLB lockdown.  */
507
809
        /* ??? TLB lockdown not implemented.  */
508
810
        break;
509
 
    case 11: /* TCM DMA control.  */
510
811
    case 12: /* Reserved.  */
511
812
        goto bad_reg;
512
813
    case 13: /* Process ID.  */
513
814
        switch (op2) {
514
815
        case 0:
 
816
            if (!arm_feature(env, ARM_FEATURE_MPU))
 
817
                goto bad_reg;
515
818
            /* Unlike real hardware the qemu TLB uses virtual addresses,
516
819
               not modified virtual addresses, so this causes a TLB flush.
517
820
             */
521
824
            break;
522
825
        case 1:
523
826
            /* This changes the ASID, so do a TLB flush.  */
524
 
            if (env->cp15.c13_context != val)
 
827
            if (env->cp15.c13_context != val
 
828
                && !arm_feature(env, ARM_FEATURE_MPU))
525
829
              tlb_flush(env, 0);
526
830
            env->cp15.c13_context = val;
527
831
            break;
532
836
    case 14: /* Reserved.  */
533
837
        goto bad_reg;
534
838
    case 15: /* Implementation specific.  */
535
 
        /* ??? Internal registers not implemented.  */
 
839
        if (arm_feature(env, ARM_FEATURE_XSCALE)) {
 
840
            if (op2 == 0 && crm == 1) {
 
841
                if (env->cp15.c15_cpar != (val & 0x3fff)) {
 
842
                    /* Changes cp0 to cp13 behavior, so needs a TB flush.  */
 
843
                    tb_flush(env);
 
844
                    env->cp15.c15_cpar = val & 0x3fff;
 
845
                }
 
846
                break;
 
847
            }
 
848
            goto bad_reg;
 
849
        }
 
850
        if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
 
851
            switch (crm) {
 
852
            case 0:
 
853
                break;
 
854
            case 1: /* Set TI925T configuration.  */
 
855
                env->cp15.c15_ticonfig = val & 0xe7;
 
856
                env->cp15.c0_cpuid = (val & (1 << 5)) ? /* OS_TYPE bit */
 
857
                        ARM_CPUID_TI915T : ARM_CPUID_TI925T;
 
858
                break;
 
859
            case 2: /* Set I_max.  */
 
860
                env->cp15.c15_i_max = val;
 
861
                break;
 
862
            case 3: /* Set I_min.  */
 
863
                env->cp15.c15_i_min = val;
 
864
                break;
 
865
            case 4: /* Set thread-ID.  */
 
866
                env->cp15.c15_threadid = val & 0xffff;
 
867
                break;
 
868
            case 8: /* Wait-for-interrupt (deprecated).  */
 
869
                cpu_interrupt(env, CPU_INTERRUPT_HALT);
 
870
                break;
 
871
            default:
 
872
                goto bad_reg;
 
873
            }
 
874
        }
536
875
        break;
537
876
    }
538
877
    return;
539
878
bad_reg:
540
879
    /* ??? For debugging only.  Should raise illegal instruction exception.  */
541
 
    cpu_abort(env, "Unimplemented cp15 register read\n");
 
880
    cpu_abort(env, "Unimplemented cp15 register write\n");
542
881
}
543
882
 
544
883
uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
545
884
{
546
885
    uint32_t op2;
 
886
    uint32_t crm;
547
887
 
548
888
    op2 = (insn >> 5) & 7;
 
889
    crm = insn & 0xf;
549
890
    switch ((insn >> 16) & 0xf) {
550
891
    case 0: /* ID codes.  */
551
892
        switch (op2) {
552
893
        default: /* Device ID.  */
553
894
            return env->cp15.c0_cpuid;
554
895
        case 1: /* Cache Type.  */
555
 
            return 0x1dd20d2;
 
896
            return env->cp15.c0_cachetype;
556
897
        case 2: /* TCM status.  */
 
898
            if (arm_feature(env, ARM_FEATURE_XSCALE))
 
899
                goto bad_reg;
557
900
            return 0;
558
901
        }
559
902
    case 1: /* System configuration.  */
 
903
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
 
904
            op2 = 0;
560
905
        switch (op2) {
561
906
        case 0: /* Control register.  */
562
907
            return env->cp15.c1_sys;
563
908
        case 1: /* Auxiliary control register.  */
564
909
            if (arm_feature(env, ARM_FEATURE_AUXCR))
565
910
                return 1;
 
911
            if (arm_feature(env, ARM_FEATURE_XSCALE))
 
912
                return env->cp15.c1_xscaleauxcr;
566
913
            goto bad_reg;
567
914
        case 2: /* Coprocessor access register.  */
 
915
            if (arm_feature(env, ARM_FEATURE_XSCALE))
 
916
                goto bad_reg;
568
917
            return env->cp15.c1_coproc;
569
918
        default:
570
919
            goto bad_reg;
571
920
        }
572
 
    case 2: /* MMU Page table control.  */
573
 
        return env->cp15.c2;
574
 
    case 3: /* MMU Domain access control.  */
 
921
    case 2: /* MMU Page table control / MPU cache control.  */
 
922
        if (arm_feature(env, ARM_FEATURE_MPU)) {
 
923
            switch (op2) {
 
924
            case 0:
 
925
                return env->cp15.c2_data;
 
926
                break;
 
927
            case 1:
 
928
                return env->cp15.c2_insn;
 
929
                break;
 
930
            default:
 
931
                goto bad_reg;
 
932
            }
 
933
        } else {
 
934
            return env->cp15.c2_base;
 
935
        }
 
936
    case 3: /* MMU Domain access control / MPU write buffer control.  */
575
937
        return env->cp15.c3;
576
938
    case 4: /* Reserved.  */
577
939
        goto bad_reg;
578
 
    case 5: /* MMU Fault status.  */
 
940
    case 5: /* MMU Fault status / MPU access permission.  */
 
941
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
 
942
            op2 = 0;
579
943
        switch (op2) {
580
944
        case 0:
 
945
            if (arm_feature(env, ARM_FEATURE_MPU))
 
946
                return simple_mpu_ap_bits(env->cp15.c5_data);
581
947
            return env->cp15.c5_data;
582
948
        case 1:
 
949
            if (arm_feature(env, ARM_FEATURE_MPU))
 
950
                return simple_mpu_ap_bits(env->cp15.c5_data);
 
951
            return env->cp15.c5_insn;
 
952
        case 2:
 
953
            if (!arm_feature(env, ARM_FEATURE_MPU))
 
954
                goto bad_reg;
 
955
            return env->cp15.c5_data;
 
956
        case 3:
 
957
            if (!arm_feature(env, ARM_FEATURE_MPU))
 
958
                goto bad_reg;
583
959
            return env->cp15.c5_insn;
584
960
        default:
585
961
            goto bad_reg;
586
962
        }
587
 
    case 6: /* MMU Fault address.  */
588
 
        switch (op2) {
589
 
        case 0:
590
 
            return env->cp15.c6_data;
591
 
        case 1:
592
 
            /* Arm9 doesn't have an IFAR, but implementing it anyway shouldn't
593
 
               do any harm.  */
594
 
            return env->cp15.c6_insn;
595
 
        default:
596
 
            goto bad_reg;
 
963
    case 6: /* MMU Fault address / MPU base/size.  */
 
964
        if (arm_feature(env, ARM_FEATURE_MPU)) {
 
965
            int n;
 
966
            n = (insn & 0xf);
 
967
            if (n >= 8)
 
968
                goto bad_reg;
 
969
            return env->cp15.c6_region[n];
 
970
        } else {
 
971
            if (arm_feature(env, ARM_FEATURE_OMAPCP))
 
972
                op2 = 0;
 
973
            switch (op2) {
 
974
            case 0:
 
975
                return env->cp15.c6_data;
 
976
            case 1:
 
977
                /* Arm9 doesn't have an IFAR, but implementing it anyway
 
978
                   shouldn't do any harm.  */
 
979
                return env->cp15.c6_insn;
 
980
            default:
 
981
                goto bad_reg;
 
982
            }
597
983
        }
598
984
    case 7: /* Cache control.  */
599
985
        /* ??? This is for test, clean and invaidate operations that set the
600
 
           Z flag.  We can't represent N = Z = 1, so it also clears clears
 
986
           Z flag.  We can't represent N = Z = 1, so it also clears
601
987
           the N flag.  Oh well.  */
602
988
        env->NZF = 0;
603
989
        return 0;
604
990
    case 8: /* MMU TLB control.  */
605
991
        goto bad_reg;
606
992
    case 9: /* Cache lockdown.  */
 
993
        if (arm_feature(env, ARM_FEATURE_OMAPCP))
 
994
            return 0;
607
995
        switch (op2) {
608
996
        case 0:
609
997
            return env->cp15.c9_data;
630
1018
    case 14: /* Reserved.  */
631
1019
        goto bad_reg;
632
1020
    case 15: /* Implementation specific.  */
633
 
        /* ??? Internal registers not implemented.  */
 
1021
        if (arm_feature(env, ARM_FEATURE_XSCALE)) {
 
1022
            if (op2 == 0 && crm == 1)
 
1023
                return env->cp15.c15_cpar;
 
1024
 
 
1025
            goto bad_reg;
 
1026
        }
 
1027
        if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
 
1028
            switch (crm) {
 
1029
            case 0:
 
1030
                return 0;
 
1031
            case 1: /* Read TI925T configuration.  */
 
1032
                return env->cp15.c15_ticonfig;
 
1033
            case 2: /* Read I_max.  */
 
1034
                return env->cp15.c15_i_max;
 
1035
            case 3: /* Read I_min.  */
 
1036
                return env->cp15.c15_i_min;
 
1037
            case 4: /* Read thread-ID.  */
 
1038
                return env->cp15.c15_threadid;
 
1039
            case 8: /* TI925T_status */
 
1040
                return 0;
 
1041
            }
 
1042
            goto bad_reg;
 
1043
        }
634
1044
        return 0;
635
1045
    }
636
1046
bad_reg:
639
1049
    return 0;
640
1050
}
641
1051
 
 
1052
void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 
1053
                ARMReadCPFunc *cp_read, ARMWriteCPFunc *cp_write,
 
1054
                void *opaque)
 
1055
{
 
1056
    if (cpnum < 0 || cpnum > 14) {
 
1057
        cpu_abort(env, "Bad coprocessor number: %i\n", cpnum);
 
1058
        return;
 
1059
    }
 
1060
 
 
1061
    env->cp[cpnum].cp_read = cp_read;
 
1062
    env->cp[cpnum].cp_write = cp_write;
 
1063
    env->cp[cpnum].opaque = opaque;
 
1064
}
 
1065
 
642
1066
#endif