linux-user: fix ppc target_stat64 st_blocks layout
[qemu] / target-mips / translate_init.c
1 /*
2  *  MIPS emulation for qemu: CPU initialisation routines.
3  *
4  *  Copyright (c) 2004-2005 Jocelyn Mayer
5  *  Copyright (c) 2007 Herve Poussineau
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /* CPU / CPU family specific config register values. */
22
23 /* Have config1, uncached coherency */
24 #define MIPS_CONFIG0                                              \
25   ((1 << CP0C0_M) | (0x2 << CP0C0_K0))
26
27 /* Have config2, no coprocessor2 attached, no MDMX support attached,
28    no performance counters, watch registers present,
29    no code compression, EJTAG present, no FPU */
30 #define MIPS_CONFIG1                                              \
31 ((1 << CP0C1_M) |                                                 \
32  (0 << CP0C1_C2) | (0 << CP0C1_MD) | (0 << CP0C1_PC) |            \
33  (1 << CP0C1_WR) | (0 << CP0C1_CA) | (1 << CP0C1_EP) |            \
34  (0 << CP0C1_FP))
35
36 /* Have config3, no tertiary/secondary caches implemented */
37 #define MIPS_CONFIG2                                              \
38 ((1 << CP0C2_M))
39
40 /* No config4, no DSP ASE, no large physaddr (PABITS),
41    no external interrupt controller, no vectored interupts,
42    no 1kb pages, no SmartMIPS ASE, no trace logic */
43 #define MIPS_CONFIG3                                              \
44 ((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) |          \
45  (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) |        \
46  (0 << CP0C3_SM) | (0 << CP0C3_TL))
47
48 /* Define a implementation number of 1.
49    Define a major version 1, minor version 0. */
50 #define MIPS_FCR0 ((0 << FCR0_S) | (0x1 << FCR0_PRID) | (0x10 << FCR0_REV))
51
52 /* MMU types, the first four entries have the same layout as the
53    CP0C0_MT field.  */
54 enum mips_mmu_types {
55     MMU_TYPE_NONE,
56     MMU_TYPE_R4000,
57     MMU_TYPE_RESERVED,
58     MMU_TYPE_FMT,
59     MMU_TYPE_R3000,
60     MMU_TYPE_R6000,
61     MMU_TYPE_R8000
62 };
63
64 struct mips_def_t {
65     const char *name;
66     int32_t CP0_PRid;
67     int32_t CP0_Config0;
68     int32_t CP0_Config1;
69     int32_t CP0_Config2;
70     int32_t CP0_Config3;
71     int32_t CP0_Config6;
72     int32_t CP0_Config7;
73     int32_t SYNCI_Step;
74     int32_t CCRes;
75     int32_t CP0_Status_rw_bitmask;
76     int32_t CP0_TCStatus_rw_bitmask;
77     int32_t CP0_SRSCtl;
78     int32_t CP1_fcr0;
79     int32_t SEGBITS;
80     int32_t PABITS;
81     int32_t CP0_SRSConf0_rw_bitmask;
82     int32_t CP0_SRSConf0;
83     int32_t CP0_SRSConf1_rw_bitmask;
84     int32_t CP0_SRSConf1;
85     int32_t CP0_SRSConf2_rw_bitmask;
86     int32_t CP0_SRSConf2;
87     int32_t CP0_SRSConf3_rw_bitmask;
88     int32_t CP0_SRSConf3;
89     int32_t CP0_SRSConf4_rw_bitmask;
90     int32_t CP0_SRSConf4;
91     int insn_flags;
92     enum mips_mmu_types mmu_type;
93 };
94
95 /*****************************************************************************/
96 /* MIPS CPU definitions */
97 static const mips_def_t mips_defs[] =
98 {
99     {
100         .name = "4Kc",
101         .CP0_PRid = 0x00018000,
102         .CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_R4000 << CP0C0_MT),
103         .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
104                        (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
105                        (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
106         .CP0_Config2 = MIPS_CONFIG2,
107         .CP0_Config3 = MIPS_CONFIG3,
108         .SYNCI_Step = 32,
109         .CCRes = 2,
110         .CP0_Status_rw_bitmask = 0x1278FF17,
111         .SEGBITS = 32,
112         .PABITS = 32,
113         .insn_flags = CPU_MIPS32 | ASE_MIPS16,
114         .mmu_type = MMU_TYPE_R4000,
115     },
116     {
117         .name = "4Km",
118         .CP0_PRid = 0x00018300,
119         /* Config1 implemented, fixed mapping MMU,
120            no virtual icache, uncached coherency. */
121         .CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_FMT << CP0C0_MT),
122         .CP0_Config1 = MIPS_CONFIG1 |
123                        (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
124                        (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
125         .CP0_Config2 = MIPS_CONFIG2,
126         .CP0_Config3 = MIPS_CONFIG3,
127         .SYNCI_Step = 32,
128         .CCRes = 2,
129         .CP0_Status_rw_bitmask = 0x1258FF17,
130         .SEGBITS = 32,
131         .PABITS = 32,
132         .insn_flags = CPU_MIPS32 | ASE_MIPS16,
133         .mmu_type = MMU_TYPE_FMT,
134     },
135     {
136         .name = "4KEcR1",
137         .CP0_PRid = 0x00018400,
138         .CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_R4000 << CP0C0_MT),
139         .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
140                        (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
141                        (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
142         .CP0_Config2 = MIPS_CONFIG2,
143         .CP0_Config3 = MIPS_CONFIG3,
144         .SYNCI_Step = 32,
145         .CCRes = 2,
146         .CP0_Status_rw_bitmask = 0x1278FF17,
147         .SEGBITS = 32,
148         .PABITS = 32,
149         .insn_flags = CPU_MIPS32 | ASE_MIPS16,
150         .mmu_type = MMU_TYPE_R4000,
151     },
152     {
153         .name = "4KEmR1",
154         .CP0_PRid = 0x00018500,
155         .CP0_Config0 = MIPS_CONFIG0 | (MMU_TYPE_FMT << CP0C0_MT),
156         .CP0_Config1 = MIPS_CONFIG1 |
157                        (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
158                        (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
159         .CP0_Config2 = MIPS_CONFIG2,
160         .CP0_Config3 = MIPS_CONFIG3,
161         .SYNCI_Step = 32,
162         .CCRes = 2,
163         .CP0_Status_rw_bitmask = 0x1258FF17,
164         .SEGBITS = 32,
165         .PABITS = 32,
166         .insn_flags = CPU_MIPS32 | ASE_MIPS16,
167         .mmu_type = MMU_TYPE_FMT,
168     },
169     {
170         .name = "4KEc",
171         .CP0_PRid = 0x00019000,
172         .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
173                     (MMU_TYPE_R4000 << CP0C0_MT),
174         .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
175                        (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
176                        (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
177         .CP0_Config2 = MIPS_CONFIG2,
178         .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
179         .SYNCI_Step = 32,
180         .CCRes = 2,
181         .CP0_Status_rw_bitmask = 0x1278FF17,
182         .SEGBITS = 32,
183         .PABITS = 32,
184         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
185         .mmu_type = MMU_TYPE_R4000,
186     },
187     {
188         .name = "4KEm",
189         .CP0_PRid = 0x00019100,
190         .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
191                        (MMU_TYPE_FMT << CP0C0_MT),
192         .CP0_Config1 = MIPS_CONFIG1 |
193                        (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
194                        (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
195         .CP0_Config2 = MIPS_CONFIG2,
196         .CP0_Config3 = MIPS_CONFIG3,
197         .SYNCI_Step = 32,
198         .CCRes = 2,
199         .CP0_Status_rw_bitmask = 0x1258FF17,
200         .SEGBITS = 32,
201         .PABITS = 32,
202         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
203         .mmu_type = MMU_TYPE_FMT,
204     },
205     {
206         .name = "24Kc",
207         .CP0_PRid = 0x00019300,
208         .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
209                        (MMU_TYPE_R4000 << CP0C0_MT),
210         .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
211                        (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
212                        (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
213         .CP0_Config2 = MIPS_CONFIG2,
214         .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
215         .SYNCI_Step = 32,
216         .CCRes = 2,
217         /* No DSP implemented. */
218         .CP0_Status_rw_bitmask = 0x1278FF1F,
219         .SEGBITS = 32,
220         .PABITS = 32,
221         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
222         .mmu_type = MMU_TYPE_R4000,
223     },
224     {
225         .name = "24Kf",
226         .CP0_PRid = 0x00019300,
227         .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
228                     (MMU_TYPE_R4000 << CP0C0_MT),
229         .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
230                        (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
231                        (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
232         .CP0_Config2 = MIPS_CONFIG2,
233         .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
234         .SYNCI_Step = 32,
235         .CCRes = 2,
236         /* No DSP implemented. */
237         .CP0_Status_rw_bitmask = 0x3678FF1F,
238         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
239                     (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
240         .SEGBITS = 32,
241         .PABITS = 32,
242         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
243         .mmu_type = MMU_TYPE_R4000,
244     },
245     {
246         .name = "34Kf",
247         .CP0_PRid = 0x00019500,
248         .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
249                        (MMU_TYPE_R4000 << CP0C0_MT),
250         .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
251                        (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
252                        (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
253         .CP0_Config2 = MIPS_CONFIG2,
254         .CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt) | (1 << CP0C3_MT),
255         .SYNCI_Step = 32,
256         .CCRes = 2,
257         /* No DSP implemented. */
258         .CP0_Status_rw_bitmask = 0x3678FF1F,
259         /* No DSP implemented. */
260         .CP0_TCStatus_rw_bitmask = (0 << CP0TCSt_TCU3) | (0 << CP0TCSt_TCU2) |
261                     (1 << CP0TCSt_TCU1) | (1 << CP0TCSt_TCU0) |
262                     (0 << CP0TCSt_TMX) | (1 << CP0TCSt_DT) |
263                     (1 << CP0TCSt_DA) | (1 << CP0TCSt_A) |
264                     (0x3 << CP0TCSt_TKSU) | (1 << CP0TCSt_IXMT) |
265                     (0xff << CP0TCSt_TASID),
266         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
267                     (1 << FCR0_D) | (1 << FCR0_S) | (0x95 << FCR0_PRID),
268         .CP0_SRSCtl = (0xf << CP0SRSCtl_HSS),
269         .CP0_SRSConf0_rw_bitmask = 0x3fffffff,
270         .CP0_SRSConf0 = (1 << CP0SRSC0_M) | (0x3fe << CP0SRSC0_SRS3) |
271                     (0x3fe << CP0SRSC0_SRS2) | (0x3fe << CP0SRSC0_SRS1),
272         .CP0_SRSConf1_rw_bitmask = 0x3fffffff,
273         .CP0_SRSConf1 = (1 << CP0SRSC1_M) | (0x3fe << CP0SRSC1_SRS6) |
274                     (0x3fe << CP0SRSC1_SRS5) | (0x3fe << CP0SRSC1_SRS4),
275         .CP0_SRSConf2_rw_bitmask = 0x3fffffff,
276         .CP0_SRSConf2 = (1 << CP0SRSC2_M) | (0x3fe << CP0SRSC2_SRS9) |
277                     (0x3fe << CP0SRSC2_SRS8) | (0x3fe << CP0SRSC2_SRS7),
278         .CP0_SRSConf3_rw_bitmask = 0x3fffffff,
279         .CP0_SRSConf3 = (1 << CP0SRSC3_M) | (0x3fe << CP0SRSC3_SRS12) |
280                     (0x3fe << CP0SRSC3_SRS11) | (0x3fe << CP0SRSC3_SRS10),
281         .CP0_SRSConf4_rw_bitmask = 0x3fffffff,
282         .CP0_SRSConf4 = (0x3fe << CP0SRSC4_SRS15) |
283                     (0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13),
284         .SEGBITS = 32,
285         .PABITS = 32,
286         .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT,
287         .mmu_type = MMU_TYPE_R4000,
288     },
289 #if defined(TARGET_MIPS64)
290     {
291         .name = "R4000",
292         .CP0_PRid = 0x00000400,
293         /* No L2 cache, icache size 8k, dcache size 8k, uncached coherency. */
294         .CP0_Config0 = (1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << CP0C0_K0),
295         /* Note: Config1 is only used internally, the R4000 has only Config0. */
296         .CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
297         .SYNCI_Step = 16,
298         .CCRes = 2,
299         .CP0_Status_rw_bitmask = 0x3678FFFF,
300         /* The R4000 has a full 64bit FPU but doesn't use the fcr0 bits. */
301         .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
302         .SEGBITS = 40,
303         .PABITS = 36,
304         .insn_flags = CPU_MIPS3,
305         .mmu_type = MMU_TYPE_R4000,
306     },
307     {
308         .name = "VR5432",
309         .CP0_PRid = 0x00005400,
310         /* No L2 cache, icache size 8k, dcache size 8k, uncached coherency. */
311         .CP0_Config0 = (1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << CP0C0_K0),
312         .CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
313         .SYNCI_Step = 16,
314         .CCRes = 2,
315         .CP0_Status_rw_bitmask = 0x3678FFFF,
316         /* The VR5432 has a full 64bit FPU but doesn't use the fcr0 bits. */
317         .CP1_fcr0 = (0x54 << FCR0_PRID) | (0x0 << FCR0_REV),
318         .SEGBITS = 40,
319         .PABITS = 32,
320         .insn_flags = CPU_VR54XX,
321         .mmu_type = MMU_TYPE_R4000,
322     },
323     {
324         .name = "5Kc",
325         .CP0_PRid = 0x00018100,
326         .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) |
327                        (MMU_TYPE_R4000 << CP0C0_MT),
328         .CP0_Config1 = MIPS_CONFIG1 | (31 << CP0C1_MMU) |
329                        (1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
330                        (1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
331                        (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
332         .CP0_Config2 = MIPS_CONFIG2,
333         .CP0_Config3 = MIPS_CONFIG3,
334         .SYNCI_Step = 32,
335         .CCRes = 2,
336         .CP0_Status_rw_bitmask = 0x32F8FFFF,
337         .SEGBITS = 42,
338         .PABITS = 36,
339         .insn_flags = CPU_MIPS64,
340         .mmu_type = MMU_TYPE_R4000,
341     },
342     {
343         .name = "5Kf",
344         .CP0_PRid = 0x00018100,
345         .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) |
346                        (MMU_TYPE_R4000 << CP0C0_MT),
347         .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (31 << CP0C1_MMU) |
348                        (1 << CP0C1_IS) | (4 << CP0C1_IL) | (1 << CP0C1_IA) |
349                        (1 << CP0C1_DS) | (4 << CP0C1_DL) | (1 << CP0C1_DA) |
350                        (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
351         .CP0_Config2 = MIPS_CONFIG2,
352         .CP0_Config3 = MIPS_CONFIG3,
353         .SYNCI_Step = 32,
354         .CCRes = 2,
355         .CP0_Status_rw_bitmask = 0x36F8FFFF,
356         /* The 5Kf has F64 / L / W but doesn't use the fcr0 bits. */
357         .CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) |
358                     (0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
359         .SEGBITS = 42,
360         .PABITS = 36,
361         .insn_flags = CPU_MIPS64,
362         .mmu_type = MMU_TYPE_R4000,
363     },
364     {
365         .name = "20Kc",
366         /* We emulate a later version of the 20Kc, earlier ones had a broken
367            WAIT instruction. */
368         .CP0_PRid = 0x000182a0,
369         .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT) |
370                     (MMU_TYPE_R4000 << CP0C0_MT) | (1 << CP0C0_VI),
371         .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (47 << CP0C1_MMU) |
372                        (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
373                        (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
374                        (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
375         .CP0_Config2 = MIPS_CONFIG2,
376         .CP0_Config3 = MIPS_CONFIG3,
377         .SYNCI_Step = 32,
378         .CCRes = 1,
379         .CP0_Status_rw_bitmask = 0x36FBFFFF,
380         /* The 20Kc has F64 / L / W but doesn't use the fcr0 bits. */
381         .CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) |
382                     (1 << FCR0_D) | (1 << FCR0_S) |
383                     (0x82 << FCR0_PRID) | (0x0 << FCR0_REV),
384         .SEGBITS = 40,
385         .PABITS = 36,
386         .insn_flags = CPU_MIPS64 | ASE_MIPS3D,
387         .mmu_type = MMU_TYPE_R4000,
388     },
389     {
390         /* A generic CPU providing MIPS64 Release 2 features.
391            FIXME: Eventually this should be replaced by a real CPU model. */
392         .name = "MIPS64R2-generic",
393         .CP0_PRid = 0x00010000,
394         .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
395                        (MMU_TYPE_R4000 << CP0C0_MT),
396         .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
397                        (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
398                        (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
399                        (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
400         .CP0_Config2 = MIPS_CONFIG2,
401         .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_LPA),
402         .SYNCI_Step = 32,
403         .CCRes = 2,
404         .CP0_Status_rw_bitmask = 0x36FBFFFF,
405         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_3D) | (1 << FCR0_PS) |
406                     (1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
407                     (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
408         .SEGBITS = 42,
409         /* The architectural limit is 59, but we have hardcoded 36 bit
410            in some places...
411         .PABITS = 59, */ /* the architectural limit */
412         .PABITS = 36,
413         .insn_flags = CPU_MIPS64R2 | ASE_MIPS3D,
414         .mmu_type = MMU_TYPE_R4000,
415     },
416 #endif
417 };
418
419 static const mips_def_t *cpu_mips_find_by_name (const char *name)
420 {
421     int i;
422
423     for (i = 0; i < ARRAY_SIZE(mips_defs); i++) {
424         if (strcasecmp(name, mips_defs[i].name) == 0) {
425             return &mips_defs[i];
426         }
427     }
428     return NULL;
429 }
430
431 void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
432 {
433     int i;
434
435     for (i = 0; i < ARRAY_SIZE(mips_defs); i++) {
436         (*cpu_fprintf)(f, "MIPS '%s'\n",
437                        mips_defs[i].name);
438     }
439 }
440
441 #ifndef CONFIG_USER_ONLY
442 static void no_mmu_init (CPUMIPSState *env, const mips_def_t *def)
443 {
444     env->tlb->nb_tlb = 1;
445     env->tlb->map_address = &no_mmu_map_address;
446 }
447
448 static void fixed_mmu_init (CPUMIPSState *env, const mips_def_t *def)
449 {
450     env->tlb->nb_tlb = 1;
451     env->tlb->map_address = &fixed_mmu_map_address;
452 }
453
454 static void r4k_mmu_init (CPUMIPSState *env, const mips_def_t *def)
455 {
456     env->tlb->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63);
457     env->tlb->map_address = &r4k_map_address;
458     env->tlb->helper_tlbwi = r4k_helper_tlbwi;
459     env->tlb->helper_tlbwr = r4k_helper_tlbwr;
460     env->tlb->helper_tlbp = r4k_helper_tlbp;
461     env->tlb->helper_tlbr = r4k_helper_tlbr;
462 }
463
464 static void mmu_init (CPUMIPSState *env, const mips_def_t *def)
465 {
466     env->tlb = qemu_mallocz(sizeof(CPUMIPSTLBContext));
467
468     switch (def->mmu_type) {
469         case MMU_TYPE_NONE:
470             no_mmu_init(env, def);
471             break;
472         case MMU_TYPE_R4000:
473             r4k_mmu_init(env, def);
474             break;
475         case MMU_TYPE_FMT:
476             fixed_mmu_init(env, def);
477             break;
478         case MMU_TYPE_R3000:
479         case MMU_TYPE_R6000:
480         case MMU_TYPE_R8000:
481         default:
482             cpu_abort(env, "MMU type not supported\n");
483     }
484     env->CP0_Random = env->tlb->nb_tlb - 1;
485     env->tlb->tlb_in_use = env->tlb->nb_tlb;
486 }
487 #endif /* CONFIG_USER_ONLY */
488
489 static void fpu_init (CPUMIPSState *env, const mips_def_t *def)
490 {
491     int i;
492
493     for (i = 0; i < MIPS_FPU_MAX; i++)
494         env->fpus[i].fcr0 = def->CP1_fcr0;
495
496     memcpy(&env->active_fpu, &env->fpus[0], sizeof(env->active_fpu));
497 #if defined(CONFIG_USER_ONLY)
498     if (env->CP0_Config1 & (1 << CP0C1_FP))
499         env->hflags |= MIPS_HFLAG_FPU;
500 #ifdef TARGET_MIPS64
501     if (env->active_fpu.fcr0 & (1 << FCR0_F64))
502         env->hflags |= MIPS_HFLAG_F64;
503 #endif
504 #endif
505 }
506
507 static void mvp_init (CPUMIPSState *env, const mips_def_t *def)
508 {
509     env->mvp = qemu_mallocz(sizeof(CPUMIPSMVPContext));
510
511     /* MVPConf1 implemented, TLB sharable, no gating storage support,
512        programmable cache partitioning implemented, number of allocatable
513        and sharable TLB entries, MVP has allocatable TCs, 2 VPEs
514        implemented, 5 TCs implemented. */
515     env->mvp->CP0_MVPConf0 = (1 << CP0MVPC0_M) | (1 << CP0MVPC0_TLBS) |
516                              (0 << CP0MVPC0_GS) | (1 << CP0MVPC0_PCP) |
517 // TODO: actually do 2 VPEs.
518 //                             (1 << CP0MVPC0_TCA) | (0x1 << CP0MVPC0_PVPE) |
519 //                             (0x04 << CP0MVPC0_PTC);
520                              (1 << CP0MVPC0_TCA) | (0x0 << CP0MVPC0_PVPE) |
521                              (0x04 << CP0MVPC0_PTC);
522 #if !defined(CONFIG_USER_ONLY)
523     /* Usermode has no TLB support */
524     env->mvp->CP0_MVPConf0 |= (env->tlb->nb_tlb << CP0MVPC0_PTLBE);
525 #endif
526
527     /* Allocatable CP1 have media extensions, allocatable CP1 have FP support,
528        no UDI implemented, no CP2 implemented, 1 CP1 implemented. */
529     env->mvp->CP0_MVPConf1 = (1 << CP0MVPC1_CIM) | (1 << CP0MVPC1_CIF) |
530                              (0x0 << CP0MVPC1_PCX) | (0x0 << CP0MVPC1_PCP2) |
531                              (0x1 << CP0MVPC1_PCP1);
532 }
533
534 static int cpu_mips_register (CPUMIPSState *env, const mips_def_t *def)
535 {
536     env->CP0_PRid = def->CP0_PRid;
537     env->CP0_Config0 = def->CP0_Config0;
538 #ifdef TARGET_WORDS_BIGENDIAN
539     env->CP0_Config0 |= (1 << CP0C0_BE);
540 #endif
541     env->CP0_Config1 = def->CP0_Config1;
542     env->CP0_Config2 = def->CP0_Config2;
543     env->CP0_Config3 = def->CP0_Config3;
544     env->CP0_Config6 = def->CP0_Config6;
545     env->CP0_Config7 = def->CP0_Config7;
546     env->SYNCI_Step = def->SYNCI_Step;
547     env->CCRes = def->CCRes;
548     env->CP0_Status_rw_bitmask = def->CP0_Status_rw_bitmask;
549     env->CP0_TCStatus_rw_bitmask = def->CP0_TCStatus_rw_bitmask;
550     env->CP0_SRSCtl = def->CP0_SRSCtl;
551     env->current_tc = 0;
552     env->SEGBITS = def->SEGBITS;
553     env->SEGMask = (target_ulong)((1ULL << def->SEGBITS) - 1);
554 #if defined(TARGET_MIPS64)
555     if (def->insn_flags & ISA_MIPS3) {
556         env->hflags |= MIPS_HFLAG_64;
557         env->SEGMask |= 3ULL << 62;
558     }
559 #endif
560     env->PABITS = def->PABITS;
561     env->PAMask = (target_ulong)((1ULL << def->PABITS) - 1);
562     env->CP0_SRSConf0_rw_bitmask = def->CP0_SRSConf0_rw_bitmask;
563     env->CP0_SRSConf0 = def->CP0_SRSConf0;
564     env->CP0_SRSConf1_rw_bitmask = def->CP0_SRSConf1_rw_bitmask;
565     env->CP0_SRSConf1 = def->CP0_SRSConf1;
566     env->CP0_SRSConf2_rw_bitmask = def->CP0_SRSConf2_rw_bitmask;
567     env->CP0_SRSConf2 = def->CP0_SRSConf2;
568     env->CP0_SRSConf3_rw_bitmask = def->CP0_SRSConf3_rw_bitmask;
569     env->CP0_SRSConf3 = def->CP0_SRSConf3;
570     env->CP0_SRSConf4_rw_bitmask = def->CP0_SRSConf4_rw_bitmask;
571     env->CP0_SRSConf4 = def->CP0_SRSConf4;
572     env->insn_flags = def->insn_flags;
573
574 #ifndef CONFIG_USER_ONLY
575     mmu_init(env, def);
576 #endif
577     fpu_init(env, def);
578     mvp_init(env, def);
579     return 0;
580 }