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