qemu/target/mips/internal.h
<<
>>
Prefs
   1/* mips internal definitions and helpers
   2 *
   3 * This work is licensed under the terms of the GNU GPL, version 2 or later.
   4 * See the COPYING file in the top-level directory.
   5 */
   6
   7#ifndef MIPS_INTERNAL_H
   8#define MIPS_INTERNAL_H
   9
  10
  11/* MMU types, the first four entries have the same layout as the
  12   CP0C0_MT field.  */
  13enum mips_mmu_types {
  14    MMU_TYPE_NONE,
  15    MMU_TYPE_R4000,
  16    MMU_TYPE_RESERVED,
  17    MMU_TYPE_FMT,
  18    MMU_TYPE_R3000,
  19    MMU_TYPE_R6000,
  20    MMU_TYPE_R8000
  21};
  22
  23struct mips_def_t {
  24    const char *name;
  25    int32_t CP0_PRid;
  26    int32_t CP0_Config0;
  27    int32_t CP0_Config1;
  28    int32_t CP0_Config2;
  29    int32_t CP0_Config3;
  30    int32_t CP0_Config4;
  31    int32_t CP0_Config4_rw_bitmask;
  32    int32_t CP0_Config5;
  33    int32_t CP0_Config5_rw_bitmask;
  34    int32_t CP0_Config6;
  35    int32_t CP0_Config7;
  36    target_ulong CP0_LLAddr_rw_bitmask;
  37    int CP0_LLAddr_shift;
  38    int32_t SYNCI_Step;
  39    int32_t CCRes;
  40    int32_t CP0_Status_rw_bitmask;
  41    int32_t CP0_TCStatus_rw_bitmask;
  42    int32_t CP0_SRSCtl;
  43    int32_t CP1_fcr0;
  44    int32_t CP1_fcr31_rw_bitmask;
  45    int32_t CP1_fcr31;
  46    int32_t MSAIR;
  47    int32_t SEGBITS;
  48    int32_t PABITS;
  49    int32_t CP0_SRSConf0_rw_bitmask;
  50    int32_t CP0_SRSConf0;
  51    int32_t CP0_SRSConf1_rw_bitmask;
  52    int32_t CP0_SRSConf1;
  53    int32_t CP0_SRSConf2_rw_bitmask;
  54    int32_t CP0_SRSConf2;
  55    int32_t CP0_SRSConf3_rw_bitmask;
  56    int32_t CP0_SRSConf3;
  57    int32_t CP0_SRSConf4_rw_bitmask;
  58    int32_t CP0_SRSConf4;
  59    int32_t CP0_PageGrain_rw_bitmask;
  60    int32_t CP0_PageGrain;
  61    target_ulong CP0_EBaseWG_rw_bitmask;
  62    uint64_t insn_flags;
  63    enum mips_mmu_types mmu_type;
  64    int32_t SAARP;
  65};
  66
  67extern const struct mips_def_t mips_defs[];
  68extern const int mips_defs_number;
  69
  70enum CPUMIPSMSADataFormat {
  71    DF_BYTE = 0,
  72    DF_HALF,
  73    DF_WORD,
  74    DF_DOUBLE
  75};
  76
  77void mips_cpu_do_interrupt(CPUState *cpu);
  78bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req);
  79void mips_cpu_dump_state(CPUState *cpu, FILE *f, int flags);
  80hwaddr mips_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
  81int mips_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
  82int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
  83void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
  84                                  MMUAccessType access_type,
  85                                  int mmu_idx, uintptr_t retaddr);
  86
  87#if !defined(CONFIG_USER_ONLY)
  88
  89typedef struct r4k_tlb_t r4k_tlb_t;
  90struct r4k_tlb_t {
  91    target_ulong VPN;
  92    uint32_t PageMask;
  93    uint16_t ASID;
  94    unsigned int G:1;
  95    unsigned int C0:3;
  96    unsigned int C1:3;
  97    unsigned int V0:1;
  98    unsigned int V1:1;
  99    unsigned int D0:1;
 100    unsigned int D1:1;
 101    unsigned int XI0:1;
 102    unsigned int XI1:1;
 103    unsigned int RI0:1;
 104    unsigned int RI1:1;
 105    unsigned int EHINV:1;
 106    uint64_t PFN[2];
 107};
 108
 109struct CPUMIPSTLBContext {
 110    uint32_t nb_tlb;
 111    uint32_t tlb_in_use;
 112    int (*map_address)(struct CPUMIPSState *env, hwaddr *physical, int *prot,
 113                       target_ulong address, int rw, int access_type);
 114    void (*helper_tlbwi)(struct CPUMIPSState *env);
 115    void (*helper_tlbwr)(struct CPUMIPSState *env);
 116    void (*helper_tlbp)(struct CPUMIPSState *env);
 117    void (*helper_tlbr)(struct CPUMIPSState *env);
 118    void (*helper_tlbinv)(struct CPUMIPSState *env);
 119    void (*helper_tlbinvf)(struct CPUMIPSState *env);
 120    union {
 121        struct {
 122            r4k_tlb_t tlb[MIPS_TLB_MAX];
 123        } r4k;
 124    } mmu;
 125};
 126
 127int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
 128                       target_ulong address, int rw, int access_type);
 129int fixed_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
 130                          target_ulong address, int rw, int access_type);
 131int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
 132                    target_ulong address, int rw, int access_type);
 133void r4k_helper_tlbwi(CPUMIPSState *env);
 134void r4k_helper_tlbwr(CPUMIPSState *env);
 135void r4k_helper_tlbp(CPUMIPSState *env);
 136void r4k_helper_tlbr(CPUMIPSState *env);
 137void r4k_helper_tlbinv(CPUMIPSState *env);
 138void r4k_helper_tlbinvf(CPUMIPSState *env);
 139void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra);
 140
 141void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
 142                                bool is_write, bool is_exec, int unused,
 143                                unsigned size);
 144hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address,
 145                                  int rw);
 146#endif
 147
 148#define cpu_signal_handler cpu_mips_signal_handler
 149
 150#ifndef CONFIG_USER_ONLY
 151extern const struct VMStateDescription vmstate_mips_cpu;
 152#endif
 153
 154static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env)
 155{
 156    return (env->CP0_Status & (1 << CP0St_IE)) &&
 157        !(env->CP0_Status & (1 << CP0St_EXL)) &&
 158        !(env->CP0_Status & (1 << CP0St_ERL)) &&
 159        !(env->hflags & MIPS_HFLAG_DM) &&
 160        /* Note that the TCStatus IXMT field is initialized to zero,
 161           and only MT capable cores can set it to one. So we don't
 162           need to check for MT capabilities here.  */
 163        !(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT));
 164}
 165
 166/* Check if there is pending and not masked out interrupt */
 167static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env)
 168{
 169    int32_t pending;
 170    int32_t status;
 171    bool r;
 172
 173    pending = env->CP0_Cause & CP0Ca_IP_mask;
 174    status = env->CP0_Status & CP0Ca_IP_mask;
 175
 176    if (env->CP0_Config3 & (1 << CP0C3_VEIC)) {
 177        /* A MIPS configured with a vectorizing external interrupt controller
 178           will feed a vector into the Cause pending lines. The core treats
 179           the status lines as a vector level, not as indiviual masks.  */
 180        r = pending > status;
 181    } else {
 182        /* A MIPS configured with compatibility or VInt (Vectored Interrupts)
 183           treats the pending lines as individual interrupt lines, the status
 184           lines are individual masks.  */
 185        r = (pending & status) != 0;
 186    }
 187    return r;
 188}
 189
 190void mips_tcg_init(void);
 191
 192/* TODO QOM'ify CPU reset and remove */
 193void cpu_state_reset(CPUMIPSState *s);
 194void cpu_mips_realize_env(CPUMIPSState *env);
 195
 196/* cp0_timer.c */
 197uint32_t cpu_mips_get_random(CPUMIPSState *env);
 198uint32_t cpu_mips_get_count(CPUMIPSState *env);
 199void cpu_mips_store_count(CPUMIPSState *env, uint32_t value);
 200void cpu_mips_store_compare(CPUMIPSState *env, uint32_t value);
 201void cpu_mips_start_count(CPUMIPSState *env);
 202void cpu_mips_stop_count(CPUMIPSState *env);
 203
 204/* helper.c */
 205bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 206                       MMUAccessType access_type, int mmu_idx,
 207                       bool probe, uintptr_t retaddr);
 208
 209/* op_helper.c */
 210uint32_t float_class_s(uint32_t arg, float_status *fst);
 211uint64_t float_class_d(uint64_t arg, float_status *fst);
 212
 213extern unsigned int ieee_rm[];
 214int ieee_ex_to_mips(int xcpt);
 215void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask);
 216
 217static inline void restore_rounding_mode(CPUMIPSState *env)
 218{
 219    set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3],
 220                            &env->active_fpu.fp_status);
 221}
 222
 223static inline void restore_flush_mode(CPUMIPSState *env)
 224{
 225    set_flush_to_zero((env->active_fpu.fcr31 & (1 << FCR31_FS)) != 0,
 226                      &env->active_fpu.fp_status);
 227}
 228
 229static inline void restore_fp_status(CPUMIPSState *env)
 230{
 231    restore_rounding_mode(env);
 232    restore_flush_mode(env);
 233    restore_snan_bit_mode(env);
 234}
 235
 236static inline void restore_msa_fp_status(CPUMIPSState *env)
 237{
 238    float_status *status = &env->active_tc.msa_fp_status;
 239    int rounding_mode = (env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR_RM;
 240    bool flush_to_zero = (env->active_tc.msacsr & MSACSR_FS_MASK) != 0;
 241
 242    set_float_rounding_mode(ieee_rm[rounding_mode], status);
 243    set_flush_to_zero(flush_to_zero, status);
 244    set_flush_inputs_to_zero(flush_to_zero, status);
 245}
 246
 247static inline void restore_pamask(CPUMIPSState *env)
 248{
 249    if (env->hflags & MIPS_HFLAG_ELPA) {
 250        env->PAMask = (1ULL << env->PABITS) - 1;
 251    } else {
 252        env->PAMask = PAMASK_BASE;
 253    }
 254}
 255
 256static inline int mips_vpe_active(CPUMIPSState *env)
 257{
 258    int active = 1;
 259
 260    /* Check that the VPE is enabled.  */
 261    if (!(env->mvp->CP0_MVPControl & (1 << CP0MVPCo_EVP))) {
 262        active = 0;
 263    }
 264    /* Check that the VPE is activated.  */
 265    if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))) {
 266        active = 0;
 267    }
 268
 269    /* Now verify that there are active thread contexts in the VPE.
 270
 271       This assumes the CPU model will internally reschedule threads
 272       if the active one goes to sleep. If there are no threads available
 273       the active one will be in a sleeping state, and we can turn off
 274       the entire VPE.  */
 275    if (!(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_A))) {
 276        /* TC is not activated.  */
 277        active = 0;
 278    }
 279    if (env->active_tc.CP0_TCHalt & 1) {
 280        /* TC is in halt state.  */
 281        active = 0;
 282    }
 283
 284    return active;
 285}
 286
 287static inline int mips_vp_active(CPUMIPSState *env)
 288{
 289    CPUState *other_cs = first_cpu;
 290
 291    /* Check if the VP disabled other VPs (which means the VP is enabled) */
 292    if ((env->CP0_VPControl >> CP0VPCtl_DIS) & 1) {
 293        return 1;
 294    }
 295
 296    /* Check if the virtual processor is disabled due to a DVP */
 297    CPU_FOREACH(other_cs) {
 298        MIPSCPU *other_cpu = MIPS_CPU(other_cs);
 299        if ((&other_cpu->env != env) &&
 300            ((other_cpu->env.CP0_VPControl >> CP0VPCtl_DIS) & 1)) {
 301            return 0;
 302        }
 303    }
 304    return 1;
 305}
 306
 307static inline void compute_hflags(CPUMIPSState *env)
 308{
 309    env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
 310                     MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
 311                     MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSP_R2 |
 312                     MIPS_HFLAG_DSP_R3 | MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA |
 313                     MIPS_HFLAG_FRE | MIPS_HFLAG_ELPA | MIPS_HFLAG_ERL);
 314    if (env->CP0_Status & (1 << CP0St_ERL)) {
 315        env->hflags |= MIPS_HFLAG_ERL;
 316    }
 317    if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
 318        !(env->CP0_Status & (1 << CP0St_ERL)) &&
 319        !(env->hflags & MIPS_HFLAG_DM)) {
 320        env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU;
 321    }
 322#if defined(TARGET_MIPS64)
 323    if ((env->insn_flags & ISA_MIPS3) &&
 324        (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) ||
 325         (env->CP0_Status & (1 << CP0St_PX)) ||
 326         (env->CP0_Status & (1 << CP0St_UX)))) {
 327        env->hflags |= MIPS_HFLAG_64;
 328    }
 329
 330    if (!(env->insn_flags & ISA_MIPS3)) {
 331        env->hflags |= MIPS_HFLAG_AWRAP;
 332    } else if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
 333               !(env->CP0_Status & (1 << CP0St_UX))) {
 334        env->hflags |= MIPS_HFLAG_AWRAP;
 335    } else if (env->insn_flags & ISA_MIPS64R6) {
 336        /* Address wrapping for Supervisor and Kernel is specified in R6 */
 337        if ((((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_SM) &&
 338             !(env->CP0_Status & (1 << CP0St_SX))) ||
 339            (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_KM) &&
 340             !(env->CP0_Status & (1 << CP0St_KX)))) {
 341            env->hflags |= MIPS_HFLAG_AWRAP;
 342        }
 343    }
 344#endif
 345    if (((env->CP0_Status & (1 << CP0St_CU0)) &&
 346         !(env->insn_flags & ISA_MIPS32R6)) ||
 347        !(env->hflags & MIPS_HFLAG_KSU)) {
 348        env->hflags |= MIPS_HFLAG_CP0;
 349    }
 350    if (env->CP0_Status & (1 << CP0St_CU1)) {
 351        env->hflags |= MIPS_HFLAG_FPU;
 352    }
 353    if (env->CP0_Status & (1 << CP0St_FR)) {
 354        env->hflags |= MIPS_HFLAG_F64;
 355    }
 356    if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_KM) &&
 357        (env->CP0_Config5 & (1 << CP0C5_SBRI))) {
 358        env->hflags |= MIPS_HFLAG_SBRI;
 359    }
 360    if (env->insn_flags & ASE_DSP_R3) {
 361        /*
 362         * Our cpu supports DSP R3 ASE, so enable
 363         * access to DSP R3 resources.
 364         */
 365        if (env->CP0_Status & (1 << CP0St_MX)) {
 366            env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSP_R2 |
 367                           MIPS_HFLAG_DSP_R3;
 368        }
 369    } else if (env->insn_flags & ASE_DSP_R2) {
 370        /*
 371         * Our cpu supports DSP R2 ASE, so enable
 372         * access to DSP R2 resources.
 373         */
 374        if (env->CP0_Status & (1 << CP0St_MX)) {
 375            env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSP_R2;
 376        }
 377
 378    } else if (env->insn_flags & ASE_DSP) {
 379        /*
 380         * Our cpu supports DSP ASE, so enable
 381         * access to DSP resources.
 382         */
 383        if (env->CP0_Status & (1 << CP0St_MX)) {
 384            env->hflags |= MIPS_HFLAG_DSP;
 385        }
 386
 387    }
 388    if (env->insn_flags & ISA_MIPS32R2) {
 389        if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
 390            env->hflags |= MIPS_HFLAG_COP1X;
 391        }
 392    } else if (env->insn_flags & ISA_MIPS32) {
 393        if (env->hflags & MIPS_HFLAG_64) {
 394            env->hflags |= MIPS_HFLAG_COP1X;
 395        }
 396    } else if (env->insn_flags & ISA_MIPS4) {
 397        /* All supported MIPS IV CPUs use the XX (CU3) to enable
 398           and disable the MIPS IV extensions to the MIPS III ISA.
 399           Some other MIPS IV CPUs ignore the bit, so the check here
 400           would be too restrictive for them.  */
 401        if (env->CP0_Status & (1U << CP0St_CU3)) {
 402            env->hflags |= MIPS_HFLAG_COP1X;
 403        }
 404    }
 405    if (env->insn_flags & ASE_MSA) {
 406        if (env->CP0_Config5 & (1 << CP0C5_MSAEn)) {
 407            env->hflags |= MIPS_HFLAG_MSA;
 408        }
 409    }
 410    if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) {
 411        if (env->CP0_Config5 & (1 << CP0C5_FRE)) {
 412            env->hflags |= MIPS_HFLAG_FRE;
 413        }
 414    }
 415    if (env->CP0_Config3 & (1 << CP0C3_LPA)) {
 416        if (env->CP0_PageGrain & (1 << CP0PG_ELPA)) {
 417            env->hflags |= MIPS_HFLAG_ELPA;
 418        }
 419    }
 420}
 421
 422void cpu_mips_tlb_flush(CPUMIPSState *env);
 423void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc);
 424void cpu_mips_store_status(CPUMIPSState *env, target_ulong val);
 425void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val);
 426
 427void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, uint32_t exception,
 428                                          int error_code, uintptr_t pc);
 429
 430static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env,
 431                                                    uint32_t exception,
 432                                                    uintptr_t pc)
 433{
 434    do_raise_exception_err(env, exception, 0, pc);
 435}
 436
 437#endif
 438