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