1 /* 2 * OpenRISC virtual CPU header. 3 * 4 * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef OPENRISC_CPU_H 21 #define OPENRISC_CPU_H 22 23 #include "qemu-common.h" 24 #include "exec/cpu-defs.h" 25 #include "qom/cpu.h" 26 27 #define CPUArchState struct CPUOpenRISCState 28 29 /* cpu_openrisc_map_address_* in CPUOpenRISCTLBContext need this decl. */ 30 struct OpenRISCCPU; 31 32 #define TYPE_OPENRISC_CPU "or1k-cpu" 33 34 #define OPENRISC_CPU_CLASS(klass) \ 35 OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU) 36 #define OPENRISC_CPU(obj) \ 37 OBJECT_CHECK(OpenRISCCPU, (obj), TYPE_OPENRISC_CPU) 38 #define OPENRISC_CPU_GET_CLASS(obj) \ 39 OBJECT_GET_CLASS(OpenRISCCPUClass, (obj), TYPE_OPENRISC_CPU) 40 41 /** 42 * OpenRISCCPUClass: 43 * @parent_realize: The parent class' realize handler. 44 * @parent_reset: The parent class' reset handler. 45 * 46 * A OpenRISC CPU model. 47 */ 48 typedef struct OpenRISCCPUClass { 49 /*< private >*/ 50 CPUClass parent_class; 51 /*< public >*/ 52 53 DeviceRealize parent_realize; 54 void (*parent_reset)(CPUState *cpu); 55 } OpenRISCCPUClass; 56 57 #define TARGET_INSN_START_EXTRA_WORDS 1 58 59 enum { 60 MMU_NOMMU_IDX = 0, 61 MMU_SUPERVISOR_IDX = 1, 62 MMU_USER_IDX = 2, 63 }; 64 65 #define SET_FP_CAUSE(reg, v) do {\ 66 (reg) = ((reg) & ~(0x3f << 12)) | \ 67 ((v & 0x3f) << 12);\ 68 } while (0) 69 #define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f) 70 #define UPDATE_FP_FLAGS(reg, v) do {\ 71 (reg) |= ((v & 0x1f) << 2);\ 72 } while (0) 73 74 /* Version Register */ 75 #define SPR_VR 0xFFFF003F 76 77 /* Interrupt */ 78 #define NR_IRQS 32 79 80 /* Unit presece register */ 81 enum { 82 UPR_UP = (1 << 0), 83 UPR_DCP = (1 << 1), 84 UPR_ICP = (1 << 2), 85 UPR_DMP = (1 << 3), 86 UPR_IMP = (1 << 4), 87 UPR_MP = (1 << 5), 88 UPR_DUP = (1 << 6), 89 UPR_PCUR = (1 << 7), 90 UPR_PMP = (1 << 8), 91 UPR_PICP = (1 << 9), 92 UPR_TTP = (1 << 10), 93 UPR_CUP = (255 << 24), 94 }; 95 96 /* CPU configure register */ 97 enum { 98 CPUCFGR_NSGF = (15 << 0), 99 CPUCFGR_CGF = (1 << 4), 100 CPUCFGR_OB32S = (1 << 5), 101 CPUCFGR_OB64S = (1 << 6), 102 CPUCFGR_OF32S = (1 << 7), 103 CPUCFGR_OF64S = (1 << 8), 104 CPUCFGR_OV64S = (1 << 9), 105 /* CPUCFGR_ND = (1 << 10), */ 106 /* CPUCFGR_AVRP = (1 << 11), */ 107 CPUCFGR_EVBARP = (1 << 12), 108 /* CPUCFGR_ISRP = (1 << 13), */ 109 /* CPUCFGR_AECSRP = (1 << 14), */ 110 }; 111 112 /* DMMU configure register */ 113 enum { 114 DMMUCFGR_NTW = (3 << 0), 115 DMMUCFGR_NTS = (7 << 2), 116 DMMUCFGR_NAE = (7 << 5), 117 DMMUCFGR_CRI = (1 << 8), 118 DMMUCFGR_PRI = (1 << 9), 119 DMMUCFGR_TEIRI = (1 << 10), 120 DMMUCFGR_HTR = (1 << 11), 121 }; 122 123 /* IMMU configure register */ 124 enum { 125 IMMUCFGR_NTW = (3 << 0), 126 IMMUCFGR_NTS = (7 << 2), 127 IMMUCFGR_NAE = (7 << 5), 128 IMMUCFGR_CRI = (1 << 8), 129 IMMUCFGR_PRI = (1 << 9), 130 IMMUCFGR_TEIRI = (1 << 10), 131 IMMUCFGR_HTR = (1 << 11), 132 }; 133 134 /* Power management register */ 135 enum { 136 PMR_SDF = (15 << 0), 137 PMR_DME = (1 << 4), 138 PMR_SME = (1 << 5), 139 PMR_DCGE = (1 << 6), 140 PMR_SUME = (1 << 7), 141 }; 142 143 /* Float point control status register */ 144 enum { 145 FPCSR_FPEE = 1, 146 FPCSR_RM = (3 << 1), 147 FPCSR_OVF = (1 << 3), 148 FPCSR_UNF = (1 << 4), 149 FPCSR_SNF = (1 << 5), 150 FPCSR_QNF = (1 << 6), 151 FPCSR_ZF = (1 << 7), 152 FPCSR_IXF = (1 << 8), 153 FPCSR_IVF = (1 << 9), 154 FPCSR_INF = (1 << 10), 155 FPCSR_DZF = (1 << 11), 156 }; 157 158 /* Exceptions indices */ 159 enum { 160 EXCP_RESET = 0x1, 161 EXCP_BUSERR = 0x2, 162 EXCP_DPF = 0x3, 163 EXCP_IPF = 0x4, 164 EXCP_TICK = 0x5, 165 EXCP_ALIGN = 0x6, 166 EXCP_ILLEGAL = 0x7, 167 EXCP_INT = 0x8, 168 EXCP_DTLBMISS = 0x9, 169 EXCP_ITLBMISS = 0xa, 170 EXCP_RANGE = 0xb, 171 EXCP_SYSCALL = 0xc, 172 EXCP_FPE = 0xd, 173 EXCP_TRAP = 0xe, 174 EXCP_NR, 175 }; 176 177 /* Supervisor register */ 178 enum { 179 SR_SM = (1 << 0), 180 SR_TEE = (1 << 1), 181 SR_IEE = (1 << 2), 182 SR_DCE = (1 << 3), 183 SR_ICE = (1 << 4), 184 SR_DME = (1 << 5), 185 SR_IME = (1 << 6), 186 SR_LEE = (1 << 7), 187 SR_CE = (1 << 8), 188 SR_F = (1 << 9), 189 SR_CY = (1 << 10), 190 SR_OV = (1 << 11), 191 SR_OVE = (1 << 12), 192 SR_DSX = (1 << 13), 193 SR_EPH = (1 << 14), 194 SR_FO = (1 << 15), 195 SR_SUMRA = (1 << 16), 196 SR_SCE = (1 << 17), 197 }; 198 199 /* Tick Timer Mode Register */ 200 enum { 201 TTMR_TP = (0xfffffff), 202 TTMR_IP = (1 << 28), 203 TTMR_IE = (1 << 29), 204 TTMR_M = (3 << 30), 205 }; 206 207 /* Timer Mode */ 208 enum { 209 TIMER_NONE = (0 << 30), 210 TIMER_INTR = (1 << 30), 211 TIMER_SHOT = (2 << 30), 212 TIMER_CONT = (3 << 30), 213 }; 214 215 /* TLB size */ 216 enum { 217 TLB_SIZE = 128, 218 TLB_MASK = TLB_SIZE - 1, 219 }; 220 221 /* TLB prot */ 222 enum { 223 URE = (1 << 6), 224 UWE = (1 << 7), 225 SRE = (1 << 8), 226 SWE = (1 << 9), 227 228 SXE = (1 << 6), 229 UXE = (1 << 7), 230 }; 231 232 typedef struct OpenRISCTLBEntry { 233 uint32_t mr; 234 uint32_t tr; 235 } OpenRISCTLBEntry; 236 237 #ifndef CONFIG_USER_ONLY 238 typedef struct CPUOpenRISCTLBContext { 239 OpenRISCTLBEntry itlb[TLB_SIZE]; 240 OpenRISCTLBEntry dtlb[TLB_SIZE]; 241 242 int (*cpu_openrisc_map_address_code)(struct OpenRISCCPU *cpu, 243 hwaddr *physical, 244 int *prot, 245 target_ulong address, int rw); 246 int (*cpu_openrisc_map_address_data)(struct OpenRISCCPU *cpu, 247 hwaddr *physical, 248 int *prot, 249 target_ulong address, int rw); 250 } CPUOpenRISCTLBContext; 251 #endif 252 253 typedef struct CPUOpenRISCState { 254 target_ulong shadow_gpr[16][32]; /* Shadow registers */ 255 256 target_ulong pc; /* Program counter */ 257 target_ulong ppc; /* Prev PC */ 258 target_ulong jmp_pc; /* Jump PC */ 259 260 uint64_t mac; /* Multiply registers MACHI:MACLO */ 261 262 target_ulong epcr; /* Exception PC register */ 263 target_ulong eear; /* Exception EA register */ 264 265 target_ulong sr_f; /* the SR_F bit, values 0, 1. */ 266 target_ulong sr_cy; /* the SR_CY bit, values 0, 1. */ 267 target_long sr_ov; /* the SR_OV bit (in the sign bit only) */ 268 uint32_t sr; /* Supervisor register, without SR_{F,CY,OV} */ 269 uint32_t vr; /* Version register */ 270 uint32_t upr; /* Unit presence register */ 271 uint32_t dmmucfgr; /* DMMU configure register */ 272 uint32_t immucfgr; /* IMMU configure register */ 273 uint32_t esr; /* Exception supervisor register */ 274 uint32_t evbar; /* Exception vector base address register */ 275 uint32_t pmr; /* Power Management Register */ 276 uint32_t fpcsr; /* Float register */ 277 float_status fp_status; 278 279 target_ulong lock_addr; 280 target_ulong lock_value; 281 282 uint32_t dflag; /* In delay slot (boolean) */ 283 284 #ifndef CONFIG_USER_ONLY 285 CPUOpenRISCTLBContext tlb; 286 #endif 287 288 /* Fields up to this point are cleared by a CPU reset */ 289 struct {} end_reset_fields; 290 291 CPU_COMMON 292 293 /* Fields from here on are preserved across CPU reset. */ 294 uint32_t cpucfgr; /* CPU configure register */ 295 296 #ifndef CONFIG_USER_ONLY 297 QEMUTimer *timer; 298 uint32_t ttmr; /* Timer tick mode register */ 299 int is_counting; 300 301 uint32_t picmr; /* Interrupt mask register */ 302 uint32_t picsr; /* Interrupt contrl register*/ 303 #endif 304 void *irq[32]; /* Interrupt irq input */ 305 } CPUOpenRISCState; 306 307 /** 308 * OpenRISCCPU: 309 * @env: #CPUOpenRISCState 310 * 311 * A OpenRISC CPU. 312 */ 313 typedef struct OpenRISCCPU { 314 /*< private >*/ 315 CPUState parent_obj; 316 /*< public >*/ 317 318 CPUOpenRISCState env; 319 320 } OpenRISCCPU; 321 322 static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env) 323 { 324 return container_of(env, OpenRISCCPU, env); 325 } 326 327 #define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e)) 328 329 #define ENV_OFFSET offsetof(OpenRISCCPU, env) 330 331 void cpu_openrisc_list(void); 332 void openrisc_cpu_do_interrupt(CPUState *cpu); 333 bool openrisc_cpu_exec_interrupt(CPUState *cpu, int int_req); 334 void openrisc_cpu_dump_state(CPUState *cpu, FILE *f, int flags); 335 hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); 336 int openrisc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); 337 int openrisc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); 338 void openrisc_translate_init(void); 339 bool openrisc_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 340 MMUAccessType access_type, int mmu_idx, 341 bool probe, uintptr_t retaddr); 342 int cpu_openrisc_signal_handler(int host_signum, void *pinfo, void *puc); 343 int print_insn_or1k(bfd_vma addr, disassemble_info *info); 344 345 #define cpu_list cpu_openrisc_list 346 #define cpu_signal_handler cpu_openrisc_signal_handler 347 348 #ifndef CONFIG_USER_ONLY 349 extern const struct VMStateDescription vmstate_openrisc_cpu; 350 351 /* hw/openrisc_pic.c */ 352 void cpu_openrisc_pic_init(OpenRISCCPU *cpu); 353 354 /* hw/openrisc_timer.c */ 355 void cpu_openrisc_clock_init(OpenRISCCPU *cpu); 356 uint32_t cpu_openrisc_count_get(OpenRISCCPU *cpu); 357 void cpu_openrisc_count_set(OpenRISCCPU *cpu, uint32_t val); 358 void cpu_openrisc_count_update(OpenRISCCPU *cpu); 359 void cpu_openrisc_timer_update(OpenRISCCPU *cpu); 360 void cpu_openrisc_count_start(OpenRISCCPU *cpu); 361 void cpu_openrisc_count_stop(OpenRISCCPU *cpu); 362 #endif 363 364 #define OPENRISC_CPU_TYPE_SUFFIX "-" TYPE_OPENRISC_CPU 365 #define OPENRISC_CPU_TYPE_NAME(model) model OPENRISC_CPU_TYPE_SUFFIX 366 #define CPU_RESOLVING_TYPE TYPE_OPENRISC_CPU 367 368 #include "exec/cpu-all.h" 369 370 #define TB_FLAGS_SM SR_SM 371 #define TB_FLAGS_DME SR_DME 372 #define TB_FLAGS_IME SR_IME 373 #define TB_FLAGS_OVE SR_OVE 374 #define TB_FLAGS_DFLAG 2 /* reuse SR_TEE */ 375 #define TB_FLAGS_R0_0 4 /* reuse SR_IEE */ 376 377 static inline uint32_t cpu_get_gpr(const CPUOpenRISCState *env, int i) 378 { 379 return env->shadow_gpr[0][i]; 380 } 381 382 static inline void cpu_set_gpr(CPUOpenRISCState *env, int i, uint32_t val) 383 { 384 env->shadow_gpr[0][i] = val; 385 } 386 387 static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, 388 target_ulong *pc, 389 target_ulong *cs_base, uint32_t *flags) 390 { 391 *pc = env->pc; 392 *cs_base = 0; 393 *flags = (env->dflag ? TB_FLAGS_DFLAG : 0) 394 | (cpu_get_gpr(env, 0) ? 0 : TB_FLAGS_R0_0) 395 | (env->sr & (SR_SM | SR_DME | SR_IME | SR_OVE)); 396 } 397 398 static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch) 399 { 400 int ret = MMU_NOMMU_IDX; /* mmu is disabled */ 401 402 if (env->sr & (ifetch ? SR_IME : SR_DME)) { 403 /* The mmu is enabled; test supervisor state. */ 404 ret = env->sr & SR_SM ? MMU_SUPERVISOR_IDX : MMU_USER_IDX; 405 } 406 407 return ret; 408 } 409 410 static inline uint32_t cpu_get_sr(const CPUOpenRISCState *env) 411 { 412 return (env->sr 413 + env->sr_f * SR_F 414 + env->sr_cy * SR_CY 415 + (env->sr_ov < 0) * SR_OV); 416 } 417 418 static inline void cpu_set_sr(CPUOpenRISCState *env, uint32_t val) 419 { 420 env->sr_f = (val & SR_F) != 0; 421 env->sr_cy = (val & SR_CY) != 0; 422 env->sr_ov = (val & SR_OV ? -1 : 0); 423 env->sr = (val & ~(SR_F | SR_CY | SR_OV)) | SR_FO; 424 } 425 426 #define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_INT_0 427 428 #endif /* OPENRISC_CPU_H */ 429