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