Statistics
| Branch: | Revision:

root / target-mips / translate_init.c @ c9c1a064

History | View | Annotate | Download (10 kB)

1 33d68b5f ths
/*
2 33d68b5f ths
 *  MIPS emulation for qemu: CPU initialisation routines.
3 33d68b5f ths
 *
4 33d68b5f ths
 *  Copyright (c) 2004-2005 Jocelyn Mayer
5 33d68b5f ths
 *  Copyright (c) 2007 Herve Poussineau
6 33d68b5f ths
 *
7 33d68b5f ths
 * This library is free software; you can redistribute it and/or
8 33d68b5f ths
 * modify it under the terms of the GNU Lesser General Public
9 33d68b5f ths
 * License as published by the Free Software Foundation; either
10 33d68b5f ths
 * version 2 of the License, or (at your option) any later version.
11 33d68b5f ths
 *
12 33d68b5f ths
 * This library is distributed in the hope that it will be useful,
13 33d68b5f ths
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 33d68b5f ths
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 33d68b5f ths
 * Lesser General Public License for more details.
16 33d68b5f ths
 *
17 33d68b5f ths
 * You should have received a copy of the GNU Lesser General Public
18 33d68b5f ths
 * License along with this library; if not, write to the Free Software
19 33d68b5f ths
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 33d68b5f ths
 */
21 33d68b5f ths
22 3953d786 ths
/* CPU / CPU family specific config register values. */
23 3953d786 ths
24 3953d786 ths
/* Have config1, is MIPS32R1, uses TLB, no virtual icache,
25 3953d786 ths
   uncached coherency */
26 3953d786 ths
#define MIPS_CONFIG0                                              \
27 3953d786 ths
  ((1 << CP0C0_M) | (0x0 << CP0C0_K23) | (0x0 << CP0C0_KU) |      \
28 3953d786 ths
   (0x0 << CP0C0_AT) | (0x0 << CP0C0_AR) | (0x1 << CP0C0_MT) |    \
29 3953d786 ths
   (0x2 << CP0C0_K0))
30 3953d786 ths
31 fcb4a419 ths
/* Have config2, 64 sets Icache, 16 bytes Icache line,
32 3953d786 ths
   2-way Icache, 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache,
33 3953d786 ths
   no coprocessor2 attached, no MDMX support attached,
34 3953d786 ths
   no performance counters, watch registers present,
35 3953d786 ths
   no code compression, EJTAG present, no FPU */
36 3953d786 ths
#define MIPS_CONFIG1                                              \
37 fcb4a419 ths
((1 << CP0C1_M) |                                                 \
38 3953d786 ths
 (0x0 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x1 << CP0C1_IA) |      \
39 3953d786 ths
 (0x0 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x1 << CP0C1_DA) |      \
40 3953d786 ths
 (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) |            \
41 3953d786 ths
 (1 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP) |            \
42 3953d786 ths
 (0 << CP0C1_FP))
43 3953d786 ths
44 3953d786 ths
/* Have config3, no tertiary/secondary caches implemented */
45 3953d786 ths
#define MIPS_CONFIG2                                              \
46 3953d786 ths
((1 << CP0C2_M))
47 3953d786 ths
48 3953d786 ths
/* No config4, no DSP ASE, no large physaddr,
49 3953d786 ths
   no external interrupt controller, no vectored interupts,
50 3953d786 ths
   no 1kb pages, no MT ASE, no SmartMIPS ASE, no trace logic */
51 3953d786 ths
#define MIPS_CONFIG3                                              \
52 3953d786 ths
((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) |          \
53 3953d786 ths
 (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) |        \
54 3953d786 ths
 (0 << CP0C3_MT) | (0 << CP0C3_SM) | (0 << CP0C3_TL))
55 3953d786 ths
56 3953d786 ths
/* Define a implementation number of 1.
57 3953d786 ths
   Define a major version 1, minor version 0. */
58 5a5012ec ths
#define MIPS_FCR0 ((0 << FCR0_S) | (0x1 << FCR0_PRID) | (0x10 << FCR0_REV))
59 3953d786 ths
60 3953d786 ths
61 33d68b5f ths
struct mips_def_t {
62 33d68b5f ths
    const unsigned char *name;
63 33d68b5f ths
    int32_t CP0_PRid;
64 33d68b5f ths
    int32_t CP0_Config0;
65 33d68b5f ths
    int32_t CP0_Config1;
66 3953d786 ths
    int32_t CP0_Config2;
67 3953d786 ths
    int32_t CP0_Config3;
68 34ee2ede ths
    int32_t CP0_Config6;
69 34ee2ede ths
    int32_t CP0_Config7;
70 2f644545 ths
    int32_t SYNCI_Step;
71 2f644545 ths
    int32_t CCRes;
72 5a5012ec ths
    int32_t Status_rw_bitmask;
73 3953d786 ths
    int32_t CP1_fcr0;
74 33d68b5f ths
};
75 33d68b5f ths
76 33d68b5f ths
/*****************************************************************************/
77 33d68b5f ths
/* MIPS CPU definitions */
78 33d68b5f ths
static mips_def_t mips_defs[] =
79 33d68b5f ths
{
80 60aa19ab ths
#ifndef TARGET_MIPS64
81 33d68b5f ths
    {
82 33d68b5f ths
        .name = "4Kc",
83 33d68b5f ths
        .CP0_PRid = 0x00018000,
84 33d68b5f ths
        .CP0_Config0 = MIPS_CONFIG0,
85 fcb4a419 ths
        .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU),
86 3953d786 ths
        .CP0_Config2 = MIPS_CONFIG2,
87 3953d786 ths
        .CP0_Config3 = MIPS_CONFIG3,
88 2f644545 ths
        .SYNCI_Step = 32,
89 2f644545 ths
        .CCRes = 2,
90 5a5012ec ths
        .Status_rw_bitmask = 0x3278FF17,
91 33d68b5f ths
    },
92 33d68b5f ths
    {
93 34ee2ede ths
        .name = "4KEcR1",
94 33d68b5f ths
        .CP0_PRid = 0x00018400,
95 34ee2ede ths
        .CP0_Config0 = MIPS_CONFIG0,
96 fcb4a419 ths
        .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU),
97 34ee2ede ths
        .CP0_Config2 = MIPS_CONFIG2,
98 34ee2ede ths
        .CP0_Config3 = MIPS_CONFIG3,
99 2f644545 ths
        .SYNCI_Step = 32,
100 2f644545 ths
        .CCRes = 2,
101 4759513b ths
        .Status_rw_bitmask = 0x3278FF17,
102 34ee2ede ths
    },
103 34ee2ede ths
    {
104 34ee2ede ths
        .name = "4KEc",
105 34ee2ede ths
        .CP0_PRid = 0x00019000,
106 34ee2ede ths
        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR),
107 fcb4a419 ths
        .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU),
108 34ee2ede ths
        .CP0_Config2 = MIPS_CONFIG2,
109 34ee2ede ths
        .CP0_Config3 = MIPS_CONFIG3,
110 2f644545 ths
        .SYNCI_Step = 32,
111 2f644545 ths
        .CCRes = 2,
112 5a5012ec ths
        .Status_rw_bitmask = 0x3278FF17,
113 34ee2ede ths
    },
114 34ee2ede ths
    {
115 34ee2ede ths
        .name = "24Kc",
116 34ee2ede ths
        .CP0_PRid = 0x00019300,
117 33d68b5f ths
        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR),
118 fcb4a419 ths
        .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU),
119 3953d786 ths
        .CP0_Config2 = MIPS_CONFIG2,
120 3953d786 ths
        .CP0_Config3 = MIPS_CONFIG3,
121 2f644545 ths
        .SYNCI_Step = 32,
122 2f644545 ths
        .CCRes = 2,
123 5a5012ec ths
        .Status_rw_bitmask = 0x3278FF17,
124 33d68b5f ths
    },
125 33d68b5f ths
    {
126 33d68b5f ths
        .name = "24Kf",
127 33d68b5f ths
        .CP0_PRid = 0x00019300,
128 33d68b5f ths
        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR),
129 fcb4a419 ths
        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU),
130 3953d786 ths
        .CP0_Config2 = MIPS_CONFIG2,
131 3953d786 ths
        .CP0_Config3 = MIPS_CONFIG3,
132 2f644545 ths
        .SYNCI_Step = 32,
133 2f644545 ths
        .CCRes = 2,
134 5a5012ec ths
        .Status_rw_bitmask = 0x3678FF17,
135 5a5012ec ths
        .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
136 5a5012ec ths
                    (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
137 33d68b5f ths
    },
138 33d68b5f ths
#else
139 33d68b5f ths
    {
140 33d68b5f ths
        .name = "R4000",
141 33d68b5f ths
        .CP0_PRid = 0x00000400,
142 33d68b5f ths
        .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT),
143 fcb4a419 ths
        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (47 << CP0C1_MMU),
144 3953d786 ths
        .CP0_Config2 = MIPS_CONFIG2,
145 3953d786 ths
        .CP0_Config3 = MIPS_CONFIG3,
146 2f644545 ths
        .SYNCI_Step = 16,
147 2f644545 ths
        .CCRes = 2,
148 5a5012ec ths
        .Status_rw_bitmask = 0x3678FFFF,
149 c9c1a064 ths
        /* XXX: The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */
150 c9c1a064 ths
        .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
151 c9c1a064 ths
    },
152 c9c1a064 ths
    {
153 c9c1a064 ths
        .name = "5Kc",
154 c9c1a064 ths
        .CP0_PRid = 0x00018100,
155 c9c1a064 ths
        .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT),
156 c9c1a064 ths
        .CP0_Config1 = MIPS_CONFIG1 | (31 << CP0C1_MMU) |
157 c9c1a064 ths
                    (1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
158 c9c1a064 ths
                    (1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
159 c9c1a064 ths
                    (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
160 c9c1a064 ths
        .CP0_Config2 = MIPS_CONFIG2,
161 c9c1a064 ths
        .CP0_Config3 = MIPS_CONFIG3,
162 c9c1a064 ths
        .SYNCI_Step = 32,
163 c9c1a064 ths
        .CCRes = 2,
164 c9c1a064 ths
        .Status_rw_bitmask = 0x3278FFFF,
165 c9c1a064 ths
    },
166 c9c1a064 ths
    {
167 c9c1a064 ths
        .name = "5Kf",
168 c9c1a064 ths
        .CP0_PRid = 0x00018100,
169 c9c1a064 ths
        .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT),
170 c9c1a064 ths
        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (31 << CP0C1_MMU) |
171 c9c1a064 ths
                    (1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
172 c9c1a064 ths
                    (1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
173 c9c1a064 ths
                    (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
174 c9c1a064 ths
        .CP0_Config2 = MIPS_CONFIG2,
175 c9c1a064 ths
        .CP0_Config3 = MIPS_CONFIG3,
176 c9c1a064 ths
        .SYNCI_Step = 32,
177 c9c1a064 ths
        .CCRes = 2,
178 c9c1a064 ths
        .Status_rw_bitmask = 0x3678FFFF,
179 c9c1a064 ths
        /* XXX: The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */
180 c9c1a064 ths
        .CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) |
181 c9c1a064 ths
                    (0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
182 c9c1a064 ths
    },
183 c9c1a064 ths
    {
184 c9c1a064 ths
        .name = "20Kc",
185 c9c1a064 ths
        .CP0_PRid = 0x00018200,
186 c9c1a064 ths
        .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) | (1 << CP0C0_VI),
187 c9c1a064 ths
        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (47 << CP0C1_MMU) |
188 c9c1a064 ths
                    (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
189 c9c1a064 ths
                    (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
190 c9c1a064 ths
                    (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
191 c9c1a064 ths
        .CP0_Config2 = MIPS_CONFIG2,
192 c9c1a064 ths
        .CP0_Config3 = MIPS_CONFIG3,
193 c9c1a064 ths
        .SYNCI_Step = 32,
194 c9c1a064 ths
        .CCRes = 2,
195 c9c1a064 ths
        .Status_rw_bitmask = 0x36FBFFFF,
196 c9c1a064 ths
        /* XXX: The 20Kc has F64 / L / W but doesn't use the fcr0 bits. */
197 c9c1a064 ths
        .CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) |
198 5a5012ec ths
                    (1 << FCR0_D) | (1 << FCR0_S) |
199 c9c1a064 ths
                    (0x82 << FCR0_PRID) | (0x0 << FCR0_REV),
200 33d68b5f ths
    },
201 33d68b5f ths
#endif
202 33d68b5f ths
};
203 33d68b5f ths
204 33d68b5f ths
int mips_find_by_name (const unsigned char *name, mips_def_t **def)
205 33d68b5f ths
{
206 33d68b5f ths
    int i, ret;
207 33d68b5f ths
208 33d68b5f ths
    ret = -1;
209 33d68b5f ths
    *def = NULL;
210 33d68b5f ths
    for (i = 0; i < sizeof(mips_defs) / sizeof(mips_defs[0]); i++) {
211 33d68b5f ths
        if (strcasecmp(name, mips_defs[i].name) == 0) {
212 33d68b5f ths
            *def = &mips_defs[i];
213 33d68b5f ths
            ret = 0;
214 33d68b5f ths
            break;
215 33d68b5f ths
        }
216 33d68b5f ths
    }
217 33d68b5f ths
218 33d68b5f ths
    return ret;
219 33d68b5f ths
}
220 33d68b5f ths
221 33d68b5f ths
void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
222 33d68b5f ths
{
223 33d68b5f ths
    int i;
224 33d68b5f ths
225 33d68b5f ths
    for (i = 0; i < sizeof(mips_defs) / sizeof(mips_defs[0]); i++) {
226 33d68b5f ths
        (*cpu_fprintf)(f, "MIPS '%s'\n",
227 33d68b5f ths
                       mips_defs[i].name);
228 33d68b5f ths
    }
229 33d68b5f ths
}
230 33d68b5f ths
231 29929e34 ths
#ifndef CONFIG_USER_ONLY
232 29929e34 ths
static void no_mmu_init (CPUMIPSState *env, mips_def_t *def)
233 29929e34 ths
{
234 29929e34 ths
    env->nb_tlb = 1;
235 29929e34 ths
    env->map_address = &no_mmu_map_address;
236 29929e34 ths
}
237 29929e34 ths
238 29929e34 ths
static void fixed_mmu_init (CPUMIPSState *env, mips_def_t *def)
239 29929e34 ths
{
240 29929e34 ths
    env->nb_tlb = 1;
241 29929e34 ths
    env->map_address = &fixed_mmu_map_address;
242 29929e34 ths
}
243 29929e34 ths
244 29929e34 ths
static void r4k_mmu_init (CPUMIPSState *env, mips_def_t *def)
245 29929e34 ths
{
246 29929e34 ths
    env->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63);
247 29929e34 ths
    env->map_address = &r4k_map_address;
248 29929e34 ths
    env->do_tlbwi = r4k_do_tlbwi;
249 29929e34 ths
    env->do_tlbwr = r4k_do_tlbwr;
250 29929e34 ths
    env->do_tlbp = r4k_do_tlbp;
251 29929e34 ths
    env->do_tlbr = r4k_do_tlbr;
252 29929e34 ths
}
253 29929e34 ths
#endif /* CONFIG_USER_ONLY */
254 29929e34 ths
255 33d68b5f ths
int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
256 33d68b5f ths
{
257 33d68b5f ths
    if (!def)
258 51b2772f ths
        def = env->cpu_model;
259 51b2772f ths
    if (!def)
260 33d68b5f ths
        cpu_abort(env, "Unable to find MIPS CPU definition\n");
261 51b2772f ths
    env->cpu_model = def;
262 33d68b5f ths
    env->CP0_PRid = def->CP0_PRid;
263 33d68b5f ths
    env->CP0_Config0 = def->CP0_Config0;
264 51b2772f ths
#ifdef TARGET_WORDS_BIGENDIAN
265 51b2772f ths
    env->CP0_Config0 |= (1 << CP0C0_BE);
266 3953d786 ths
#endif
267 33d68b5f ths
    env->CP0_Config1 = def->CP0_Config1;
268 3953d786 ths
    env->CP0_Config2 = def->CP0_Config2;
269 3953d786 ths
    env->CP0_Config3 = def->CP0_Config3;
270 34ee2ede ths
    env->CP0_Config6 = def->CP0_Config6;
271 34ee2ede ths
    env->CP0_Config7 = def->CP0_Config7;
272 2f644545 ths
    env->SYNCI_Step = def->SYNCI_Step;
273 2f644545 ths
    env->CCRes = def->CCRes;
274 5a5012ec ths
    env->Status_rw_bitmask = def->Status_rw_bitmask;
275 3953d786 ths
    env->fcr0 = def->CP1_fcr0;
276 a7037b29 ths
#ifdef CONFIG_USER_ONLY
277 a7037b29 ths
    if (env->CP0_Config1 & (1 << CP0C1_FP))
278 a7037b29 ths
        env->hflags |= MIPS_HFLAG_FPU;
279 a7037b29 ths
    if (env->fcr0 & (1 << FCR0_F64))
280 a7037b29 ths
        env->hflags |= MIPS_HFLAG_F64;
281 a7037b29 ths
#else
282 29929e34 ths
    switch ((env->CP0_Config0 >> CP0C0_MT) & 3) {
283 29929e34 ths
        case 0:
284 29929e34 ths
            no_mmu_init(env, def);
285 29929e34 ths
            break;
286 29929e34 ths
        case 1:
287 29929e34 ths
            r4k_mmu_init(env, def);
288 29929e34 ths
            break;
289 29929e34 ths
        case 3:
290 29929e34 ths
            fixed_mmu_init(env, def);
291 29929e34 ths
            break;
292 29929e34 ths
        default:
293 29929e34 ths
            /* Older CPUs like the R3000 may need nonstandard handling here. */
294 29929e34 ths
            cpu_abort(env, "MMU type not supported\n");
295 29929e34 ths
    }
296 fcb4a419 ths
    env->CP0_Random = env->nb_tlb - 1;
297 fcb4a419 ths
    env->tlb_in_use = env->nb_tlb;
298 29929e34 ths
#endif /* CONFIG_USER_ONLY */
299 33d68b5f ths
    return 0;
300 33d68b5f ths
}