qemu/target/xtensa/cpu.h
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
   3 * All rights reserved.
   4 *
   5 * Redistribution and use in source and binary forms, with or without
   6 * modification, are permitted provided that the following conditions are met:
   7 *     * Redistributions of source code must retain the above copyright
   8 *       notice, this list of conditions and the following disclaimer.
   9 *     * Redistributions in binary form must reproduce the above copyright
  10 *       notice, this list of conditions and the following disclaimer in the
  11 *       documentation and/or other materials provided with the distribution.
  12 *     * Neither the name of the Open Source and Linux Lab nor the
  13 *       names of its contributors may be used to endorse or promote products
  14 *       derived from this software without specific prior written permission.
  15 *
  16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26 */
  27
  28#ifndef XTENSA_CPU_H
  29#define XTENSA_CPU_H
  30
  31#define ALIGNED_ONLY
  32#define TARGET_LONG_BITS 32
  33
  34#define CPUArchState struct CPUXtensaState
  35
  36#include "qemu-common.h"
  37#include "cpu-qom.h"
  38#include "exec/cpu-defs.h"
  39#include "fpu/softfloat.h"
  40
  41#define NB_MMU_MODES 4
  42
  43#define TARGET_PHYS_ADDR_SPACE_BITS 32
  44#define TARGET_VIRT_ADDR_SPACE_BITS 32
  45#define TARGET_PAGE_BITS 12
  46
  47enum {
  48    /* Additional instructions */
  49    XTENSA_OPTION_CODE_DENSITY,
  50    XTENSA_OPTION_LOOP,
  51    XTENSA_OPTION_EXTENDED_L32R,
  52    XTENSA_OPTION_16_BIT_IMUL,
  53    XTENSA_OPTION_32_BIT_IMUL,
  54    XTENSA_OPTION_32_BIT_IMUL_HIGH,
  55    XTENSA_OPTION_32_BIT_IDIV,
  56    XTENSA_OPTION_MAC16,
  57    XTENSA_OPTION_MISC_OP_NSA,
  58    XTENSA_OPTION_MISC_OP_MINMAX,
  59    XTENSA_OPTION_MISC_OP_SEXT,
  60    XTENSA_OPTION_MISC_OP_CLAMPS,
  61    XTENSA_OPTION_COPROCESSOR,
  62    XTENSA_OPTION_BOOLEAN,
  63    XTENSA_OPTION_FP_COPROCESSOR,
  64    XTENSA_OPTION_MP_SYNCHRO,
  65    XTENSA_OPTION_CONDITIONAL_STORE,
  66    XTENSA_OPTION_ATOMCTL,
  67    XTENSA_OPTION_DEPBITS,
  68
  69    /* Interrupts and exceptions */
  70    XTENSA_OPTION_EXCEPTION,
  71    XTENSA_OPTION_RELOCATABLE_VECTOR,
  72    XTENSA_OPTION_UNALIGNED_EXCEPTION,
  73    XTENSA_OPTION_INTERRUPT,
  74    XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
  75    XTENSA_OPTION_TIMER_INTERRUPT,
  76
  77    /* Local memory */
  78    XTENSA_OPTION_ICACHE,
  79    XTENSA_OPTION_ICACHE_TEST,
  80    XTENSA_OPTION_ICACHE_INDEX_LOCK,
  81    XTENSA_OPTION_DCACHE,
  82    XTENSA_OPTION_DCACHE_TEST,
  83    XTENSA_OPTION_DCACHE_INDEX_LOCK,
  84    XTENSA_OPTION_IRAM,
  85    XTENSA_OPTION_IROM,
  86    XTENSA_OPTION_DRAM,
  87    XTENSA_OPTION_DROM,
  88    XTENSA_OPTION_XLMI,
  89    XTENSA_OPTION_HW_ALIGNMENT,
  90    XTENSA_OPTION_MEMORY_ECC_PARITY,
  91
  92    /* Memory protection and translation */
  93    XTENSA_OPTION_REGION_PROTECTION,
  94    XTENSA_OPTION_REGION_TRANSLATION,
  95    XTENSA_OPTION_MMU,
  96    XTENSA_OPTION_CACHEATTR,
  97
  98    /* Other */
  99    XTENSA_OPTION_WINDOWED_REGISTER,
 100    XTENSA_OPTION_PROCESSOR_INTERFACE,
 101    XTENSA_OPTION_MISC_SR,
 102    XTENSA_OPTION_THREAD_POINTER,
 103    XTENSA_OPTION_PROCESSOR_ID,
 104    XTENSA_OPTION_DEBUG,
 105    XTENSA_OPTION_TRACE_PORT,
 106    XTENSA_OPTION_EXTERN_REGS,
 107};
 108
 109enum {
 110    THREADPTR = 231,
 111    FCR = 232,
 112    FSR = 233,
 113};
 114
 115enum {
 116    LBEG = 0,
 117    LEND = 1,
 118    LCOUNT = 2,
 119    SAR = 3,
 120    BR = 4,
 121    LITBASE = 5,
 122    SCOMPARE1 = 12,
 123    ACCLO = 16,
 124    ACCHI = 17,
 125    MR = 32,
 126    WINDOW_BASE = 72,
 127    WINDOW_START = 73,
 128    PTEVADDR = 83,
 129    RASID = 90,
 130    ITLBCFG = 91,
 131    DTLBCFG = 92,
 132    IBREAKENABLE = 96,
 133    MEMCTL = 97,
 134    CACHEATTR = 98,
 135    ATOMCTL = 99,
 136    IBREAKA = 128,
 137    DBREAKA = 144,
 138    DBREAKC = 160,
 139    CONFIGID0 = 176,
 140    EPC1 = 177,
 141    DEPC = 192,
 142    EPS2 = 194,
 143    CONFIGID1 = 208,
 144    EXCSAVE1 = 209,
 145    CPENABLE = 224,
 146    INTSET = 226,
 147    INTCLEAR = 227,
 148    INTENABLE = 228,
 149    PS = 230,
 150    VECBASE = 231,
 151    EXCCAUSE = 232,
 152    DEBUGCAUSE = 233,
 153    CCOUNT = 234,
 154    PRID = 235,
 155    ICOUNT = 236,
 156    ICOUNTLEVEL = 237,
 157    EXCVADDR = 238,
 158    CCOMPARE = 240,
 159    MISC = 244,
 160};
 161
 162#define PS_INTLEVEL 0xf
 163#define PS_INTLEVEL_SHIFT 0
 164
 165#define PS_EXCM 0x10
 166#define PS_UM 0x20
 167
 168#define PS_RING 0xc0
 169#define PS_RING_SHIFT 6
 170
 171#define PS_OWB 0xf00
 172#define PS_OWB_SHIFT 8
 173
 174#define PS_CALLINC 0x30000
 175#define PS_CALLINC_SHIFT 16
 176#define PS_CALLINC_LEN 2
 177
 178#define PS_WOE 0x40000
 179
 180#define DEBUGCAUSE_IC 0x1
 181#define DEBUGCAUSE_IB 0x2
 182#define DEBUGCAUSE_DB 0x4
 183#define DEBUGCAUSE_BI 0x8
 184#define DEBUGCAUSE_BN 0x10
 185#define DEBUGCAUSE_DI 0x20
 186#define DEBUGCAUSE_DBNUM 0xf00
 187#define DEBUGCAUSE_DBNUM_SHIFT 8
 188
 189#define DBREAKC_SB 0x80000000
 190#define DBREAKC_LB 0x40000000
 191#define DBREAKC_SB_LB (DBREAKC_SB | DBREAKC_LB)
 192#define DBREAKC_MASK 0x3f
 193
 194#define MEMCTL_INIT 0x00800000
 195#define MEMCTL_IUSEWAYS_SHIFT 18
 196#define MEMCTL_IUSEWAYS_LEN 5
 197#define MEMCTL_IUSEWAYS_MASK 0x007c0000
 198#define MEMCTL_DALLOCWAYS_SHIFT 13
 199#define MEMCTL_DALLOCWAYS_LEN 5
 200#define MEMCTL_DALLOCWAYS_MASK 0x0003e000
 201#define MEMCTL_DUSEWAYS_SHIFT 8
 202#define MEMCTL_DUSEWAYS_LEN 5
 203#define MEMCTL_DUSEWAYS_MASK 0x00001f00
 204#define MEMCTL_ISNP 0x4
 205#define MEMCTL_DSNP 0x2
 206#define MEMCTL_IL0EN 0x1
 207
 208#define MAX_NAREG 64
 209#define MAX_NINTERRUPT 32
 210#define MAX_NLEVEL 6
 211#define MAX_NNMI 1
 212#define MAX_NCCOMPARE 3
 213#define MAX_TLB_WAY_SIZE 8
 214#define MAX_NDBREAK 2
 215#define MAX_NMEMORY 4
 216
 217#define REGION_PAGE_MASK 0xe0000000
 218
 219#define PAGE_CACHE_MASK    0x700
 220#define PAGE_CACHE_SHIFT   8
 221#define PAGE_CACHE_INVALID 0x000
 222#define PAGE_CACHE_BYPASS  0x100
 223#define PAGE_CACHE_WT      0x200
 224#define PAGE_CACHE_WB      0x400
 225#define PAGE_CACHE_ISOLATE 0x600
 226
 227enum {
 228    /* Static vectors */
 229    EXC_RESET0,
 230    EXC_RESET1,
 231    EXC_MEMORY_ERROR,
 232
 233    /* Dynamic vectors */
 234    EXC_WINDOW_OVERFLOW4,
 235    EXC_WINDOW_UNDERFLOW4,
 236    EXC_WINDOW_OVERFLOW8,
 237    EXC_WINDOW_UNDERFLOW8,
 238    EXC_WINDOW_OVERFLOW12,
 239    EXC_WINDOW_UNDERFLOW12,
 240    EXC_IRQ,
 241    EXC_KERNEL,
 242    EXC_USER,
 243    EXC_DOUBLE,
 244    EXC_DEBUG,
 245    EXC_MAX
 246};
 247
 248enum {
 249    ILLEGAL_INSTRUCTION_CAUSE = 0,
 250    SYSCALL_CAUSE,
 251    INSTRUCTION_FETCH_ERROR_CAUSE,
 252    LOAD_STORE_ERROR_CAUSE,
 253    LEVEL1_INTERRUPT_CAUSE,
 254    ALLOCA_CAUSE,
 255    INTEGER_DIVIDE_BY_ZERO_CAUSE,
 256    PRIVILEGED_CAUSE = 8,
 257    LOAD_STORE_ALIGNMENT_CAUSE,
 258
 259    INSTR_PIF_DATA_ERROR_CAUSE = 12,
 260    LOAD_STORE_PIF_DATA_ERROR_CAUSE,
 261    INSTR_PIF_ADDR_ERROR_CAUSE,
 262    LOAD_STORE_PIF_ADDR_ERROR_CAUSE,
 263
 264    INST_TLB_MISS_CAUSE,
 265    INST_TLB_MULTI_HIT_CAUSE,
 266    INST_FETCH_PRIVILEGE_CAUSE,
 267    INST_FETCH_PROHIBITED_CAUSE = 20,
 268    LOAD_STORE_TLB_MISS_CAUSE = 24,
 269    LOAD_STORE_TLB_MULTI_HIT_CAUSE,
 270    LOAD_STORE_PRIVILEGE_CAUSE,
 271    LOAD_PROHIBITED_CAUSE = 28,
 272    STORE_PROHIBITED_CAUSE,
 273
 274    COPROCESSOR0_DISABLED = 32,
 275};
 276
 277typedef enum {
 278    INTTYPE_LEVEL,
 279    INTTYPE_EDGE,
 280    INTTYPE_NMI,
 281    INTTYPE_SOFTWARE,
 282    INTTYPE_TIMER,
 283    INTTYPE_DEBUG,
 284    INTTYPE_WRITE_ERR,
 285    INTTYPE_PROFILING,
 286    INTTYPE_MAX
 287} interrupt_type;
 288
 289struct CPUXtensaState;
 290
 291typedef struct xtensa_tlb_entry {
 292    uint32_t vaddr;
 293    uint32_t paddr;
 294    uint8_t asid;
 295    uint8_t attr;
 296    bool variable;
 297} xtensa_tlb_entry;
 298
 299typedef struct xtensa_tlb {
 300    unsigned nways;
 301    const unsigned way_size[10];
 302    bool varway56;
 303    unsigned nrefillentries;
 304} xtensa_tlb;
 305
 306typedef struct XtensaGdbReg {
 307    int targno;
 308    int type;
 309    int group;
 310    unsigned size;
 311} XtensaGdbReg;
 312
 313typedef struct XtensaGdbRegmap {
 314    int num_regs;
 315    int num_core_regs;
 316    /* PC + a + ar + sr + ur */
 317    XtensaGdbReg reg[1 + 16 + 64 + 256 + 256];
 318} XtensaGdbRegmap;
 319
 320typedef struct XtensaCcompareTimer {
 321    struct CPUXtensaState *env;
 322    QEMUTimer *timer;
 323} XtensaCcompareTimer;
 324
 325typedef struct XtensaMemory {
 326    unsigned num;
 327    struct XtensaMemoryRegion {
 328        uint32_t addr;
 329        uint32_t size;
 330    } location[MAX_NMEMORY];
 331} XtensaMemory;
 332
 333struct XtensaConfig {
 334    const char *name;
 335    uint64_t options;
 336    XtensaGdbRegmap gdb_regmap;
 337    unsigned nareg;
 338    int excm_level;
 339    int ndepc;
 340    uint32_t vecbase;
 341    uint32_t exception_vector[EXC_MAX];
 342    unsigned ninterrupt;
 343    unsigned nlevel;
 344    uint32_t interrupt_vector[MAX_NLEVEL + MAX_NNMI + 1];
 345    uint32_t level_mask[MAX_NLEVEL + MAX_NNMI + 1];
 346    uint32_t inttype_mask[INTTYPE_MAX];
 347    struct {
 348        uint32_t level;
 349        interrupt_type inttype;
 350    } interrupt[MAX_NINTERRUPT];
 351    unsigned nccompare;
 352    uint32_t timerint[MAX_NCCOMPARE];
 353    unsigned nextint;
 354    unsigned extint[MAX_NINTERRUPT];
 355
 356    unsigned debug_level;
 357    unsigned nibreak;
 358    unsigned ndbreak;
 359
 360    unsigned icache_ways;
 361    unsigned dcache_ways;
 362    uint32_t memctl_mask;
 363
 364    XtensaMemory instrom;
 365    XtensaMemory instram;
 366    XtensaMemory datarom;
 367    XtensaMemory dataram;
 368    XtensaMemory sysrom;
 369    XtensaMemory sysram;
 370
 371    uint32_t configid[2];
 372
 373    uint32_t clock_freq_khz;
 374
 375    xtensa_tlb itlb;
 376    xtensa_tlb dtlb;
 377};
 378
 379typedef struct XtensaConfigList {
 380    const XtensaConfig *config;
 381    struct XtensaConfigList *next;
 382} XtensaConfigList;
 383
 384#ifdef HOST_WORDS_BIGENDIAN
 385enum {
 386    FP_F32_HIGH,
 387    FP_F32_LOW,
 388};
 389#else
 390enum {
 391    FP_F32_LOW,
 392    FP_F32_HIGH,
 393};
 394#endif
 395
 396typedef struct CPUXtensaState {
 397    const XtensaConfig *config;
 398    uint32_t regs[16];
 399    uint32_t pc;
 400    uint32_t sregs[256];
 401    uint32_t uregs[256];
 402    uint32_t phys_regs[MAX_NAREG];
 403    union {
 404        float32 f32[2];
 405        float64 f64;
 406    } fregs[16];
 407    float_status fp_status;
 408
 409    xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
 410    xtensa_tlb_entry dtlb[10][MAX_TLB_WAY_SIZE];
 411    unsigned autorefill_idx;
 412    bool runstall;
 413    AddressSpace *address_space_er;
 414    MemoryRegion *system_er;
 415    int pending_irq_level; /* level of last raised IRQ */
 416    void **irq_inputs;
 417    XtensaCcompareTimer ccompare[MAX_NCCOMPARE];
 418    uint64_t time_base;
 419    uint64_t ccount_time;
 420    uint32_t ccount_base;
 421
 422    int exception_taken;
 423    int yield_needed;
 424    unsigned static_vectors;
 425
 426    /* Watchpoints for DBREAK registers */
 427    struct CPUWatchpoint *cpu_watchpoint[MAX_NDBREAK];
 428
 429    CPU_COMMON
 430} CPUXtensaState;
 431
 432/**
 433 * XtensaCPU:
 434 * @env: #CPUXtensaState
 435 *
 436 * An Xtensa CPU.
 437 */
 438struct XtensaCPU {
 439    /*< private >*/
 440    CPUState parent_obj;
 441    /*< public >*/
 442
 443    CPUXtensaState env;
 444};
 445
 446static inline XtensaCPU *xtensa_env_get_cpu(const CPUXtensaState *env)
 447{
 448    return container_of(env, XtensaCPU, env);
 449}
 450
 451#define ENV_GET_CPU(e) CPU(xtensa_env_get_cpu(e))
 452
 453#define ENV_OFFSET offsetof(XtensaCPU, env)
 454
 455void xtensa_cpu_do_interrupt(CPUState *cpu);
 456bool xtensa_cpu_exec_interrupt(CPUState *cpu, int interrupt_request);
 457void xtensa_cpu_do_unassigned_access(CPUState *cpu, hwaddr addr,
 458                                     bool is_write, bool is_exec, int opaque,
 459                                     unsigned size);
 460void xtensa_cpu_dump_state(CPUState *cpu, FILE *f,
 461                           fprintf_function cpu_fprintf, int flags);
 462hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 463int xtensa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 464int xtensa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 465void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
 466                                    MMUAccessType access_type,
 467                                    int mmu_idx, uintptr_t retaddr);
 468
 469#define cpu_signal_handler cpu_xtensa_signal_handler
 470#define cpu_list xtensa_cpu_list
 471
 472#define XTENSA_CPU_TYPE_SUFFIX "-" TYPE_XTENSA_CPU
 473#define XTENSA_CPU_TYPE_NAME(model) model XTENSA_CPU_TYPE_SUFFIX
 474
 475#ifdef TARGET_WORDS_BIGENDIAN
 476#define XTENSA_DEFAULT_CPU_MODEL "fsf"
 477#else
 478#define XTENSA_DEFAULT_CPU_MODEL "dc232b"
 479#endif
 480#define XTENSA_DEFAULT_CPU_TYPE XTENSA_CPU_TYPE_NAME(XTENSA_DEFAULT_CPU_MODEL)
 481
 482#define cpu_init(cpu_model) cpu_generic_init(TYPE_XTENSA_CPU, cpu_model)
 483
 484void xtensa_translate_init(void);
 485void xtensa_breakpoint_handler(CPUState *cs);
 486void xtensa_finalize_config(XtensaConfig *config);
 487void xtensa_register_core(XtensaConfigList *node);
 488void xtensa_sim_open_console(Chardev *chr);
 489void check_interrupts(CPUXtensaState *s);
 490void xtensa_irq_init(CPUXtensaState *env);
 491void *xtensa_get_extint(CPUXtensaState *env, unsigned extint);
 492void xtensa_timer_irq(CPUXtensaState *env, uint32_t id, uint32_t active);
 493int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
 494void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 495void xtensa_sync_window_from_phys(CPUXtensaState *env);
 496void xtensa_sync_phys_from_window(CPUXtensaState *env);
 497uint32_t xtensa_tlb_get_addr_mask(const CPUXtensaState *env, bool dtlb, uint32_t way);
 498void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb,
 499        uint32_t *vpn, uint32_t wi, uint32_t *ei);
 500int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb,
 501        uint32_t *pwi, uint32_t *pei, uint8_t *pring);
 502void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
 503        xtensa_tlb_entry *entry, bool dtlb,
 504        unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
 505void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
 506        unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
 507int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb,
 508        uint32_t vaddr, int is_write, int mmu_idx,
 509        uint32_t *paddr, uint32_t *page_size, unsigned *access);
 510void reset_mmu(CPUXtensaState *env);
 511void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUXtensaState *env);
 512void debug_exception_env(CPUXtensaState *new_env, uint32_t cause);
 513static inline MemoryRegion *xtensa_get_er_region(CPUXtensaState *env)
 514{
 515    return env->system_er;
 516}
 517
 518static inline void xtensa_select_static_vectors(CPUXtensaState *env,
 519                                                unsigned n)
 520{
 521    assert(n < 2);
 522    env->static_vectors = n;
 523}
 524void xtensa_runstall(CPUXtensaState *env, bool runstall);
 525
 526#define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
 527#define XTENSA_OPTION_ALL (~(uint64_t)0)
 528
 529static inline bool xtensa_option_bits_enabled(const XtensaConfig *config,
 530        uint64_t opt)
 531{
 532    return (config->options & opt) != 0;
 533}
 534
 535static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt)
 536{
 537    return xtensa_option_bits_enabled(config, XTENSA_OPTION_BIT(opt));
 538}
 539
 540static inline int xtensa_get_cintlevel(const CPUXtensaState *env)
 541{
 542    int level = (env->sregs[PS] & PS_INTLEVEL) >> PS_INTLEVEL_SHIFT;
 543    if ((env->sregs[PS] & PS_EXCM) && env->config->excm_level > level) {
 544        level = env->config->excm_level;
 545    }
 546    return level;
 547}
 548
 549static inline int xtensa_get_ring(const CPUXtensaState *env)
 550{
 551    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
 552        return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
 553    } else {
 554        return 0;
 555    }
 556}
 557
 558static inline int xtensa_get_cring(const CPUXtensaState *env)
 559{
 560    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) &&
 561            (env->sregs[PS] & PS_EXCM) == 0) {
 562        return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
 563    } else {
 564        return 0;
 565    }
 566}
 567
 568static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env,
 569        bool dtlb, unsigned wi, unsigned ei)
 570{
 571    return dtlb ?
 572        env->dtlb[wi] + ei :
 573        env->itlb[wi] + ei;
 574}
 575
 576static inline uint32_t xtensa_replicate_windowstart(CPUXtensaState *env)
 577{
 578    return env->sregs[WINDOW_START] |
 579        (env->sregs[WINDOW_START] << env->config->nareg / 4);
 580}
 581
 582/* MMU modes definitions */
 583#define MMU_MODE0_SUFFIX _ring0
 584#define MMU_MODE1_SUFFIX _ring1
 585#define MMU_MODE2_SUFFIX _ring2
 586#define MMU_MODE3_SUFFIX _ring3
 587
 588static inline int cpu_mmu_index(CPUXtensaState *env, bool ifetch)
 589{
 590    return xtensa_get_cring(env);
 591}
 592
 593#define XTENSA_TBFLAG_RING_MASK 0x3
 594#define XTENSA_TBFLAG_EXCM 0x4
 595#define XTENSA_TBFLAG_LITBASE 0x8
 596#define XTENSA_TBFLAG_DEBUG 0x10
 597#define XTENSA_TBFLAG_ICOUNT 0x20
 598#define XTENSA_TBFLAG_CPENABLE_MASK 0x3fc0
 599#define XTENSA_TBFLAG_CPENABLE_SHIFT 6
 600#define XTENSA_TBFLAG_EXCEPTION 0x4000
 601#define XTENSA_TBFLAG_WINDOW_MASK 0x18000
 602#define XTENSA_TBFLAG_WINDOW_SHIFT 15
 603#define XTENSA_TBFLAG_YIELD 0x20000
 604
 605static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
 606        target_ulong *cs_base, uint32_t *flags)
 607{
 608    CPUState *cs = CPU(xtensa_env_get_cpu(env));
 609
 610    *pc = env->pc;
 611    *cs_base = 0;
 612    *flags = 0;
 613    *flags |= xtensa_get_ring(env);
 614    if (env->sregs[PS] & PS_EXCM) {
 615        *flags |= XTENSA_TBFLAG_EXCM;
 616    }
 617    if (xtensa_option_enabled(env->config, XTENSA_OPTION_EXTENDED_L32R) &&
 618            (env->sregs[LITBASE] & 1)) {
 619        *flags |= XTENSA_TBFLAG_LITBASE;
 620    }
 621    if (xtensa_option_enabled(env->config, XTENSA_OPTION_DEBUG)) {
 622        if (xtensa_get_cintlevel(env) < env->config->debug_level) {
 623            *flags |= XTENSA_TBFLAG_DEBUG;
 624        }
 625        if (xtensa_get_cintlevel(env) < env->sregs[ICOUNTLEVEL]) {
 626            *flags |= XTENSA_TBFLAG_ICOUNT;
 627        }
 628    }
 629    if (xtensa_option_enabled(env->config, XTENSA_OPTION_COPROCESSOR)) {
 630        *flags |= env->sregs[CPENABLE] << XTENSA_TBFLAG_CPENABLE_SHIFT;
 631    }
 632    if (cs->singlestep_enabled && env->exception_taken) {
 633        *flags |= XTENSA_TBFLAG_EXCEPTION;
 634    }
 635    if (xtensa_option_enabled(env->config, XTENSA_OPTION_WINDOWED_REGISTER) &&
 636        (env->sregs[PS] & (PS_WOE | PS_EXCM)) == PS_WOE) {
 637        uint32_t windowstart = xtensa_replicate_windowstart(env) >>
 638            (env->sregs[WINDOW_BASE] + 1);
 639        uint32_t w = ctz32(windowstart | 0x8);
 640
 641        *flags |= w << XTENSA_TBFLAG_WINDOW_SHIFT;
 642    } else {
 643        *flags |= 3 << XTENSA_TBFLAG_WINDOW_SHIFT;
 644    }
 645    if (env->yield_needed) {
 646        *flags |= XTENSA_TBFLAG_YIELD;
 647    }
 648}
 649
 650#include "exec/cpu-all.h"
 651
 652#endif
 653