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