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