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