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