]>
Commit | Line | Data |
---|---|---|
4dd044c6 JL |
1 | /* |
2 | * OpenRISC system instructions helper routines | |
3 | * | |
4 | * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> | |
5 | * Zhizhou Zhang <etouzh@gmail.com> | |
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 | |
779fc6ad | 10 | * version 2.1 of the License, or (at your option) any later version. |
4dd044c6 JL |
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 | ||
ed2decc6 | 21 | #include "qemu/osdep.h" |
4dd044c6 | 22 | #include "cpu.h" |
63c91552 | 23 | #include "exec/exec-all.h" |
2ef6175a | 24 | #include "exec/helper-proto.h" |
f4d1414a | 25 | #include "exception.h" |
8c949951 | 26 | #include "sysemu/sysemu.h" |
5cc8767d LX |
27 | #ifndef CONFIG_USER_ONLY |
28 | #include "hw/boards.h" | |
29 | #endif | |
4dd044c6 JL |
30 | |
31 | #define TO_SPR(group, number) (((group) << 11) + (number)) | |
32 | ||
c28fa81f | 33 | void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) |
4dd044c6 JL |
34 | { |
35 | #ifndef CONFIG_USER_ONLY | |
5ee2b02e RH |
36 | OpenRISCCPU *cpu = env_archcpu(env); |
37 | CPUState *cs = env_cpu(env); | |
fffde669 | 38 | target_ulong mr; |
24c32852 | 39 | int idx; |
a465772e | 40 | #endif |
4dd044c6 JL |
41 | |
42 | switch (spr) { | |
a465772e | 43 | #ifndef CONFIG_USER_ONLY |
356a2db3 TA |
44 | case TO_SPR(0, 11): /* EVBAR */ |
45 | env->evbar = rb; | |
46 | break; | |
47 | ||
4dd044c6 | 48 | case TO_SPR(0, 16): /* NPC */ |
afd46fca | 49 | cpu_restore_state(cs, GETPC(), true); |
24c32852 RH |
50 | /* ??? Mirror or1ksim in not trashing delayed branch state |
51 | when "jumping" to the current instruction. */ | |
52 | if (env->pc != rb) { | |
53 | env->pc = rb; | |
a01deb36 | 54 | env->dflag = 0; |
24c32852 RH |
55 | cpu_loop_exit(cs); |
56 | } | |
4dd044c6 JL |
57 | break; |
58 | ||
59 | case TO_SPR(0, 17): /* SR */ | |
84775c43 | 60 | cpu_set_sr(env, rb); |
4dd044c6 JL |
61 | break; |
62 | ||
4dd044c6 JL |
63 | case TO_SPR(0, 32): /* EPCR */ |
64 | env->epcr = rb; | |
65 | break; | |
66 | ||
67 | case TO_SPR(0, 48): /* EEAR */ | |
68 | env->eear = rb; | |
69 | break; | |
70 | ||
71 | case TO_SPR(0, 64): /* ESR */ | |
72 | env->esr = rb; | |
73 | break; | |
d89e71e8 SH |
74 | |
75 | case TO_SPR(0, 1024) ... TO_SPR(0, 1024 + (16 * 32)): /* Shadow GPRs */ | |
76 | idx = (spr - 1024); | |
77 | env->shadow_gpr[idx / 32][idx % 32] = rb; | |
c3513c83 | 78 | break; |
d89e71e8 | 79 | |
56c3a141 | 80 | case TO_SPR(1, 512) ... TO_SPR(1, 512 + TLB_SIZE - 1): /* DTLBW0MR 0-127 */ |
4dd044c6 | 81 | idx = spr - TO_SPR(1, 512); |
fffde669 RH |
82 | mr = env->tlb.dtlb[idx].mr; |
83 | if (mr & 1) { | |
84 | tlb_flush_page(cs, mr & TARGET_PAGE_MASK); | |
85 | } | |
86 | if (rb & 1) { | |
87 | tlb_flush_page(cs, rb & TARGET_PAGE_MASK); | |
4dd044c6 | 88 | } |
2acaa233 | 89 | env->tlb.dtlb[idx].mr = rb; |
4dd044c6 | 90 | break; |
56c3a141 | 91 | case TO_SPR(1, 640) ... TO_SPR(1, 640 + TLB_SIZE - 1): /* DTLBW0TR 0-127 */ |
4dd044c6 | 92 | idx = spr - TO_SPR(1, 640); |
2acaa233 | 93 | env->tlb.dtlb[idx].tr = rb; |
4dd044c6 JL |
94 | break; |
95 | case TO_SPR(1, 768) ... TO_SPR(1, 895): /* DTLBW1MR 0-127 */ | |
96 | case TO_SPR(1, 896) ... TO_SPR(1, 1023): /* DTLBW1TR 0-127 */ | |
97 | case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */ | |
98 | case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */ | |
99 | case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */ | |
100 | case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */ | |
101 | break; | |
fffde669 | 102 | |
56c3a141 | 103 | case TO_SPR(2, 512) ... TO_SPR(2, 512 + TLB_SIZE - 1): /* ITLBW0MR 0-127 */ |
4dd044c6 | 104 | idx = spr - TO_SPR(2, 512); |
fffde669 RH |
105 | mr = env->tlb.itlb[idx].mr; |
106 | if (mr & 1) { | |
107 | tlb_flush_page(cs, mr & TARGET_PAGE_MASK); | |
108 | } | |
109 | if (rb & 1) { | |
110 | tlb_flush_page(cs, rb & TARGET_PAGE_MASK); | |
4dd044c6 | 111 | } |
2acaa233 | 112 | env->tlb.itlb[idx].mr = rb; |
4dd044c6 | 113 | break; |
56c3a141 | 114 | case TO_SPR(2, 640) ... TO_SPR(2, 640 + TLB_SIZE - 1): /* ITLBW0TR 0-127 */ |
4dd044c6 | 115 | idx = spr - TO_SPR(2, 640); |
2acaa233 | 116 | env->tlb.itlb[idx].tr = rb; |
4dd044c6 JL |
117 | break; |
118 | case TO_SPR(2, 768) ... TO_SPR(2, 895): /* ITLBW1MR 0-127 */ | |
119 | case TO_SPR(2, 896) ... TO_SPR(2, 1023): /* ITLBW1TR 0-127 */ | |
120 | case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */ | |
121 | case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 0-127 */ | |
122 | case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */ | |
123 | case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */ | |
124 | break; | |
fffde669 | 125 | |
6f7332ba RH |
126 | case TO_SPR(5, 1): /* MACLO */ |
127 | env->mac = deposit64(env->mac, 0, 32, rb); | |
128 | break; | |
129 | case TO_SPR(5, 2): /* MACHI */ | |
130 | env->mac = deposit64(env->mac, 32, 32, rb); | |
131 | break; | |
f4d1414a SH |
132 | case TO_SPR(8, 0): /* PMR */ |
133 | env->pmr = rb; | |
134 | if (env->pmr & PMR_DME || env->pmr & PMR_SME) { | |
afd46fca | 135 | cpu_restore_state(cs, GETPC(), true); |
f4d1414a SH |
136 | env->pc += 4; |
137 | cs->halted = 1; | |
138 | raise_exception(cpu, EXCP_HALTED); | |
139 | } | |
140 | break; | |
4dd044c6 | 141 | case TO_SPR(9, 0): /* PICMR */ |
dfc84745 | 142 | env->picmr = rb; |
4dd044c6 JL |
143 | break; |
144 | case TO_SPR(9, 2): /* PICSR */ | |
145 | env->picsr &= ~rb; | |
146 | break; | |
147 | case TO_SPR(10, 0): /* TTMR */ | |
148 | { | |
d5155217 SM |
149 | if ((env->ttmr & TTMR_M) ^ (rb & TTMR_M)) { |
150 | switch (rb & TTMR_M) { | |
151 | case TIMER_NONE: | |
152 | cpu_openrisc_count_stop(cpu); | |
153 | break; | |
154 | case TIMER_INTR: | |
155 | case TIMER_SHOT: | |
156 | case TIMER_CONT: | |
157 | cpu_openrisc_count_start(cpu); | |
158 | break; | |
159 | default: | |
160 | break; | |
161 | } | |
162 | } | |
163 | ||
4dd044c6 JL |
164 | int ip = env->ttmr & TTMR_IP; |
165 | ||
166 | if (rb & TTMR_IP) { /* Keep IP bit. */ | |
d5155217 | 167 | env->ttmr = (rb & ~TTMR_IP) | ip; |
4dd044c6 JL |
168 | } else { /* Clear IP bit. */ |
169 | env->ttmr = rb & ~TTMR_IP; | |
259186a7 | 170 | cs->interrupt_request &= ~CPU_INTERRUPT_TIMER; |
4dd044c6 JL |
171 | } |
172 | ||
d5155217 | 173 | cpu_openrisc_timer_update(cpu); |
4dd044c6 JL |
174 | } |
175 | break; | |
176 | ||
177 | case TO_SPR(10, 1): /* TTCR */ | |
6b4bbd6a | 178 | cpu_openrisc_count_set(cpu, rb); |
4dd044c6 JL |
179 | if (env->ttmr & TIMER_NONE) { |
180 | return; | |
181 | } | |
d5155217 | 182 | cpu_openrisc_timer_update(cpu); |
4dd044c6 | 183 | break; |
a465772e RH |
184 | #endif |
185 | ||
186 | case TO_SPR(0, 20): /* FPCSR */ | |
187 | cpu_set_fpcsr(env, rb); | |
4dd044c6 JL |
188 | break; |
189 | } | |
4dd044c6 JL |
190 | } |
191 | ||
c28fa81f RH |
192 | target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd, |
193 | target_ulong spr) | |
4dd044c6 JL |
194 | { |
195 | #ifndef CONFIG_USER_ONLY | |
5cc8767d | 196 | MachineState *ms = MACHINE(qdev_get_machine()); |
5ee2b02e RH |
197 | OpenRISCCPU *cpu = env_archcpu(env); |
198 | CPUState *cs = env_cpu(env); | |
4dd044c6 | 199 | int idx; |
a465772e | 200 | #endif |
4dd044c6 | 201 | |
4dd044c6 | 202 | switch (spr) { |
a465772e | 203 | #ifndef CONFIG_USER_ONLY |
4dd044c6 | 204 | case TO_SPR(0, 0): /* VR */ |
b72e3ff6 | 205 | return env->vr; |
4dd044c6 JL |
206 | |
207 | case TO_SPR(0, 1): /* UPR */ | |
c7efab4f | 208 | return env->upr; |
4dd044c6 JL |
209 | |
210 | case TO_SPR(0, 2): /* CPUCFGR */ | |
211 | return env->cpucfgr; | |
212 | ||
213 | case TO_SPR(0, 3): /* DMMUCFGR */ | |
c7efab4f | 214 | return env->dmmucfgr; |
4dd044c6 JL |
215 | |
216 | case TO_SPR(0, 4): /* IMMUCFGR */ | |
217 | return env->immucfgr; | |
218 | ||
8bebf7d1 RH |
219 | case TO_SPR(0, 9): /* VR2 */ |
220 | return env->vr2; | |
221 | ||
222 | case TO_SPR(0, 10): /* AVR */ | |
223 | return env->avr; | |
224 | ||
356a2db3 TA |
225 | case TO_SPR(0, 11): /* EVBAR */ |
226 | return env->evbar; | |
227 | ||
24c32852 | 228 | case TO_SPR(0, 16): /* NPC (equals PC) */ |
afd46fca | 229 | cpu_restore_state(cs, GETPC(), false); |
24c32852 | 230 | return env->pc; |
4dd044c6 JL |
231 | |
232 | case TO_SPR(0, 17): /* SR */ | |
84775c43 | 233 | return cpu_get_sr(env); |
4dd044c6 JL |
234 | |
235 | case TO_SPR(0, 18): /* PPC */ | |
afd46fca | 236 | cpu_restore_state(cs, GETPC(), false); |
4dd044c6 JL |
237 | return env->ppc; |
238 | ||
239 | case TO_SPR(0, 32): /* EPCR */ | |
240 | return env->epcr; | |
241 | ||
242 | case TO_SPR(0, 48): /* EEAR */ | |
243 | return env->eear; | |
244 | ||
245 | case TO_SPR(0, 64): /* ESR */ | |
246 | return env->esr; | |
247 | ||
ef3f5b9e | 248 | case TO_SPR(0, 128): /* COREID */ |
8c949951 | 249 | return cpu->parent_obj.cpu_index; |
ef3f5b9e SH |
250 | |
251 | case TO_SPR(0, 129): /* NUMCORES */ | |
5cc8767d | 252 | return ms->smp.max_cpus; |
ef3f5b9e | 253 | |
d89e71e8 SH |
254 | case TO_SPR(0, 1024) ... TO_SPR(0, 1024 + (16 * 32)): /* Shadow GPRs */ |
255 | idx = (spr - 1024); | |
256 | return env->shadow_gpr[idx / 32][idx % 32]; | |
257 | ||
56c3a141 | 258 | case TO_SPR(1, 512) ... TO_SPR(1, 512 + TLB_SIZE - 1): /* DTLBW0MR 0-127 */ |
4dd044c6 | 259 | idx = spr - TO_SPR(1, 512); |
2acaa233 | 260 | return env->tlb.dtlb[idx].mr; |
4dd044c6 | 261 | |
56c3a141 | 262 | case TO_SPR(1, 640) ... TO_SPR(1, 640 + TLB_SIZE - 1): /* DTLBW0TR 0-127 */ |
4dd044c6 | 263 | idx = spr - TO_SPR(1, 640); |
2acaa233 | 264 | return env->tlb.dtlb[idx].tr; |
4dd044c6 JL |
265 | |
266 | case TO_SPR(1, 768) ... TO_SPR(1, 895): /* DTLBW1MR 0-127 */ | |
267 | case TO_SPR(1, 896) ... TO_SPR(1, 1023): /* DTLBW1TR 0-127 */ | |
268 | case TO_SPR(1, 1024) ... TO_SPR(1, 1151): /* DTLBW2MR 0-127 */ | |
269 | case TO_SPR(1, 1152) ... TO_SPR(1, 1279): /* DTLBW2TR 0-127 */ | |
270 | case TO_SPR(1, 1280) ... TO_SPR(1, 1407): /* DTLBW3MR 0-127 */ | |
271 | case TO_SPR(1, 1408) ... TO_SPR(1, 1535): /* DTLBW3TR 0-127 */ | |
272 | break; | |
273 | ||
56c3a141 | 274 | case TO_SPR(2, 512) ... TO_SPR(2, 512 + TLB_SIZE - 1): /* ITLBW0MR 0-127 */ |
4dd044c6 | 275 | idx = spr - TO_SPR(2, 512); |
2acaa233 | 276 | return env->tlb.itlb[idx].mr; |
4dd044c6 | 277 | |
56c3a141 | 278 | case TO_SPR(2, 640) ... TO_SPR(2, 640 + TLB_SIZE - 1): /* ITLBW0TR 0-127 */ |
4dd044c6 | 279 | idx = spr - TO_SPR(2, 640); |
2acaa233 | 280 | return env->tlb.itlb[idx].tr; |
4dd044c6 JL |
281 | |
282 | case TO_SPR(2, 768) ... TO_SPR(2, 895): /* ITLBW1MR 0-127 */ | |
283 | case TO_SPR(2, 896) ... TO_SPR(2, 1023): /* ITLBW1TR 0-127 */ | |
284 | case TO_SPR(2, 1024) ... TO_SPR(2, 1151): /* ITLBW2MR 0-127 */ | |
285 | case TO_SPR(2, 1152) ... TO_SPR(2, 1279): /* ITLBW2TR 0-127 */ | |
286 | case TO_SPR(2, 1280) ... TO_SPR(2, 1407): /* ITLBW3MR 0-127 */ | |
287 | case TO_SPR(2, 1408) ... TO_SPR(2, 1535): /* ITLBW3TR 0-127 */ | |
288 | break; | |
289 | ||
6f7332ba RH |
290 | case TO_SPR(5, 1): /* MACLO */ |
291 | return (uint32_t)env->mac; | |
292 | break; | |
293 | case TO_SPR(5, 2): /* MACHI */ | |
294 | return env->mac >> 32; | |
295 | break; | |
296 | ||
f4d1414a SH |
297 | case TO_SPR(8, 0): /* PMR */ |
298 | return env->pmr; | |
299 | ||
4dd044c6 JL |
300 | case TO_SPR(9, 0): /* PICMR */ |
301 | return env->picmr; | |
302 | ||
303 | case TO_SPR(9, 2): /* PICSR */ | |
304 | return env->picsr; | |
305 | ||
306 | case TO_SPR(10, 0): /* TTMR */ | |
307 | return env->ttmr; | |
308 | ||
309 | case TO_SPR(10, 1): /* TTCR */ | |
310 | cpu_openrisc_count_update(cpu); | |
6b4bbd6a | 311 | return cpu_openrisc_count_get(cpu); |
a465772e | 312 | #endif |
4dd044c6 | 313 | |
a465772e RH |
314 | case TO_SPR(0, 20): /* FPCSR */ |
315 | return env->fpcsr; | |
4dd044c6 | 316 | } |
4dd044c6 | 317 | |
4dd044c6 JL |
318 | /* for rd is passed in, if rd unchanged, just keep it back. */ |
319 | return rd; | |
320 | } |