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