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/* Xtensa processors have a weak memory model */
  35#define TCG_GUEST_DEFAULT_MO      (0)
  36
  37#define CPUArchState struct CPUXtensaState
  38
  39#include "qemu-common.h"
  40#include "cpu-qom.h"
  41#include "exec/cpu-defs.h"
  42#include "xtensa-isa.h"
  43
  44#define NB_MMU_MODES 4
  45
  46#define TARGET_PHYS_ADDR_SPACE_BITS 32
  47#ifdef CONFIG_USER_ONLY
  48#define TARGET_VIRT_ADDR_SPACE_BITS 30
  49#else
  50#define TARGET_VIRT_ADDR_SPACE_BITS 32
  51#endif
  52#define TARGET_PAGE_BITS 12
  53
  54enum {
  55    /* Additional instructions */
  56    XTENSA_OPTION_CODE_DENSITY,
  57    XTENSA_OPTION_LOOP,
  58    XTENSA_OPTION_EXTENDED_L32R,
  59    XTENSA_OPTION_16_BIT_IMUL,
  60    XTENSA_OPTION_32_BIT_IMUL,
  61    XTENSA_OPTION_32_BIT_IMUL_HIGH,
  62    XTENSA_OPTION_32_BIT_IDIV,
  63    XTENSA_OPTION_MAC16,
  64    XTENSA_OPTION_MISC_OP_NSA,
  65    XTENSA_OPTION_MISC_OP_MINMAX,
  66    XTENSA_OPTION_MISC_OP_SEXT,
  67    XTENSA_OPTION_MISC_OP_CLAMPS,
  68    XTENSA_OPTION_COPROCESSOR,
  69    XTENSA_OPTION_BOOLEAN,
  70    XTENSA_OPTION_FP_COPROCESSOR,
  71    XTENSA_OPTION_MP_SYNCHRO,
  72    XTENSA_OPTION_CONDITIONAL_STORE,
  73    XTENSA_OPTION_ATOMCTL,
  74    XTENSA_OPTION_DEPBITS,
  75
  76    /* Interrupts and exceptions */
  77    XTENSA_OPTION_EXCEPTION,
  78    XTENSA_OPTION_RELOCATABLE_VECTOR,
  79    XTENSA_OPTION_UNALIGNED_EXCEPTION,
  80    XTENSA_OPTION_INTERRUPT,
  81    XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
  82    XTENSA_OPTION_TIMER_INTERRUPT,
  83
  84    /* Local memory */
  85    XTENSA_OPTION_ICACHE,
  86    XTENSA_OPTION_ICACHE_TEST,
  87    XTENSA_OPTION_ICACHE_INDEX_LOCK,
  88    XTENSA_OPTION_DCACHE,
  89    XTENSA_OPTION_DCACHE_TEST,
  90    XTENSA_OPTION_DCACHE_INDEX_LOCK,
  91    XTENSA_OPTION_IRAM,
  92    XTENSA_OPTION_IROM,
  93    XTENSA_OPTION_DRAM,
  94    XTENSA_OPTION_DROM,
  95    XTENSA_OPTION_XLMI,
  96    XTENSA_OPTION_HW_ALIGNMENT,
  97    XTENSA_OPTION_MEMORY_ECC_PARITY,
  98
  99    /* Memory protection and translation */
 100    XTENSA_OPTION_REGION_PROTECTION,
 101    XTENSA_OPTION_REGION_TRANSLATION,
 102    XTENSA_OPTION_MMU,
 103    XTENSA_OPTION_CACHEATTR,
 104
 105    /* Other */
 106    XTENSA_OPTION_WINDOWED_REGISTER,
 107    XTENSA_OPTION_PROCESSOR_INTERFACE,
 108    XTENSA_OPTION_MISC_SR,
 109    XTENSA_OPTION_THREAD_POINTER,
 110    XTENSA_OPTION_PROCESSOR_ID,
 111    XTENSA_OPTION_DEBUG,
 112    XTENSA_OPTION_TRACE_PORT,
 113    XTENSA_OPTION_EXTERN_REGS,
 114};
 115
 116enum {
 117    EXPSTATE = 230,
 118    THREADPTR = 231,
 119    FCR = 232,
 120    FSR = 233,
 121};
 122
 123enum {
 124    LBEG = 0,
 125    LEND = 1,
 126    LCOUNT = 2,
 127    SAR = 3,
 128    BR = 4,
 129    LITBASE = 5,
 130    SCOMPARE1 = 12,
 131    ACCLO = 16,
 132    ACCHI = 17,
 133    MR = 32,
 134    WINDOW_BASE = 72,
 135    WINDOW_START = 73,
 136    PTEVADDR = 83,
 137    MMID = 89,
 138    RASID = 90,
 139    ITLBCFG = 91,
 140    DTLBCFG = 92,
 141    IBREAKENABLE = 96,
 142    MEMCTL = 97,
 143    CACHEATTR = 98,
 144    ATOMCTL = 99,
 145    DDR = 104,
 146    IBREAKA = 128,
 147    DBREAKA = 144,
 148    DBREAKC = 160,
 149    CONFIGID0 = 176,
 150    EPC1 = 177,
 151    DEPC = 192,
 152    EPS2 = 194,
 153    CONFIGID1 = 208,
 154    EXCSAVE1 = 209,
 155    CPENABLE = 224,
 156    INTSET = 226,
 157    INTCLEAR = 227,
 158    INTENABLE = 228,
 159    PS = 230,
 160    VECBASE = 231,
 161    EXCCAUSE = 232,
 162    DEBUGCAUSE = 233,
 163    CCOUNT = 234,
 164    PRID = 235,
 165    ICOUNT = 236,
 166    ICOUNTLEVEL = 237,
 167    EXCVADDR = 238,
 168    CCOMPARE = 240,
 169    MISC = 244,
 170};
 171
 172#define PS_INTLEVEL 0xf
 173#define PS_INTLEVEL_SHIFT 0
 174
 175#define PS_EXCM 0x10
 176#define PS_UM 0x20
 177
 178#define PS_RING 0xc0
 179#define PS_RING_SHIFT 6
 180
 181#define PS_OWB 0xf00
 182#define PS_OWB_SHIFT 8
 183#define PS_OWB_LEN 4
 184
 185#define PS_CALLINC 0x30000
 186#define PS_CALLINC_SHIFT 16
 187#define PS_CALLINC_LEN 2
 188
 189#define PS_WOE 0x40000
 190
 191#define DEBUGCAUSE_IC 0x1
 192#define DEBUGCAUSE_IB 0x2
 193#define DEBUGCAUSE_DB 0x4
 194#define DEBUGCAUSE_BI 0x8
 195#define DEBUGCAUSE_BN 0x10
 196#define DEBUGCAUSE_DI 0x20
 197#define DEBUGCAUSE_DBNUM 0xf00
 198#define DEBUGCAUSE_DBNUM_SHIFT 8
 199
 200#define DBREAKC_SB 0x80000000
 201#define DBREAKC_LB 0x40000000
 202#define DBREAKC_SB_LB (DBREAKC_SB | DBREAKC_LB)
 203#define DBREAKC_MASK 0x3f
 204
 205#define MEMCTL_INIT 0x00800000
 206#define MEMCTL_IUSEWAYS_SHIFT 18
 207#define MEMCTL_IUSEWAYS_LEN 5
 208#define MEMCTL_IUSEWAYS_MASK 0x007c0000
 209#define MEMCTL_DALLOCWAYS_SHIFT 13
 210#define MEMCTL_DALLOCWAYS_LEN 5
 211#define MEMCTL_DALLOCWAYS_MASK 0x0003e000
 212#define MEMCTL_DUSEWAYS_SHIFT 8
 213#define MEMCTL_DUSEWAYS_LEN 5
 214#define MEMCTL_DUSEWAYS_MASK 0x00001f00
 215#define MEMCTL_ISNP 0x4
 216#define MEMCTL_DSNP 0x2
 217#define MEMCTL_IL0EN 0x1
 218
 219#define MAX_INSN_LENGTH 64
 220#define MAX_INSN_SLOTS 32
 221#define MAX_OPCODE_ARGS 16
 222#define MAX_NAREG 64
 223#define MAX_NINTERRUPT 32
 224#define MAX_NLEVEL 6
 225#define MAX_NNMI 1
 226#define MAX_NCCOMPARE 3
 227#define MAX_TLB_WAY_SIZE 8
 228#define MAX_NDBREAK 2
 229#define MAX_NMEMORY 4
 230
 231#define REGION_PAGE_MASK 0xe0000000
 232
 233#define PAGE_CACHE_MASK    0x700
 234#define PAGE_CACHE_SHIFT   8
 235#define PAGE_CACHE_INVALID 0x000
 236#define PAGE_CACHE_BYPASS  0x100
 237#define PAGE_CACHE_WT      0x200
 238#define PAGE_CACHE_WB      0x400
 239#define PAGE_CACHE_ISOLATE 0x600
 240
 241enum {
 242    /* Static vectors */
 243    EXC_RESET0,
 244    EXC_RESET1,
 245    EXC_MEMORY_ERROR,
 246
 247    /* Dynamic vectors */
 248    EXC_WINDOW_OVERFLOW4,
 249    EXC_WINDOW_UNDERFLOW4,
 250    EXC_WINDOW_OVERFLOW8,
 251    EXC_WINDOW_UNDERFLOW8,
 252    EXC_WINDOW_OVERFLOW12,
 253    EXC_WINDOW_UNDERFLOW12,
 254    EXC_IRQ,
 255    EXC_KERNEL,
 256    EXC_USER,
 257    EXC_DOUBLE,
 258    EXC_DEBUG,
 259    EXC_MAX
 260};
 261
 262enum {
 263    ILLEGAL_INSTRUCTION_CAUSE = 0,
 264    SYSCALL_CAUSE,
 265    INSTRUCTION_FETCH_ERROR_CAUSE,
 266    LOAD_STORE_ERROR_CAUSE,
 267    LEVEL1_INTERRUPT_CAUSE,
 268    ALLOCA_CAUSE,
 269    INTEGER_DIVIDE_BY_ZERO_CAUSE,
 270    PRIVILEGED_CAUSE = 8,
 271    LOAD_STORE_ALIGNMENT_CAUSE,
 272
 273    INSTR_PIF_DATA_ERROR_CAUSE = 12,
 274    LOAD_STORE_PIF_DATA_ERROR_CAUSE,
 275    INSTR_PIF_ADDR_ERROR_CAUSE,
 276    LOAD_STORE_PIF_ADDR_ERROR_CAUSE,
 277
 278    INST_TLB_MISS_CAUSE,
 279    INST_TLB_MULTI_HIT_CAUSE,
 280    INST_FETCH_PRIVILEGE_CAUSE,
 281    INST_FETCH_PROHIBITED_CAUSE = 20,
 282    LOAD_STORE_TLB_MISS_CAUSE = 24,
 283    LOAD_STORE_TLB_MULTI_HIT_CAUSE,
 284    LOAD_STORE_PRIVILEGE_CAUSE,
 285    LOAD_PROHIBITED_CAUSE = 28,
 286    STORE_PROHIBITED_CAUSE,
 287
 288    COPROCESSOR0_DISABLED = 32,
 289};
 290
 291typedef enum {
 292    INTTYPE_LEVEL,
 293    INTTYPE_EDGE,
 294    INTTYPE_NMI,
 295    INTTYPE_SOFTWARE,
 296    INTTYPE_TIMER,
 297    INTTYPE_DEBUG,
 298    INTTYPE_WRITE_ERR,
 299    INTTYPE_PROFILING,
 300    INTTYPE_MAX
 301} interrupt_type;
 302
 303struct CPUXtensaState;
 304
 305typedef struct xtensa_tlb_entry {
 306    uint32_t vaddr;
 307    uint32_t paddr;
 308    uint8_t asid;
 309    uint8_t attr;
 310    bool variable;
 311} xtensa_tlb_entry;
 312
 313typedef struct xtensa_tlb {
 314    unsigned nways;
 315    const unsigned way_size[10];
 316    bool varway56;
 317    unsigned nrefillentries;
 318} xtensa_tlb;
 319
 320typedef struct XtensaGdbReg {
 321    int targno;
 322    unsigned flags;
 323    int type;
 324    int group;
 325    unsigned size;
 326} XtensaGdbReg;
 327
 328typedef struct XtensaGdbRegmap {
 329    int num_regs;
 330    int num_core_regs;
 331    /* PC + a + ar + sr + ur */
 332    XtensaGdbReg reg[1 + 16 + 64 + 256 + 256];
 333} XtensaGdbRegmap;
 334
 335typedef struct XtensaCcompareTimer {
 336    struct CPUXtensaState *env;
 337    QEMUTimer *timer;
 338} XtensaCcompareTimer;
 339
 340typedef struct XtensaMemory {
 341    unsigned num;
 342    struct XtensaMemoryRegion {
 343        uint32_t addr;
 344        uint32_t size;
 345    } location[MAX_NMEMORY];
 346} XtensaMemory;
 347
 348typedef struct DisasContext DisasContext;
 349typedef void (*XtensaOpcodeOp)(DisasContext *dc, const uint32_t arg[],
 350                               const uint32_t par[]);
 351typedef bool (*XtensaOpcodeBoolTest)(DisasContext *dc,
 352                                     const uint32_t arg[],
 353                                     const uint32_t par[]);
 354typedef uint32_t (*XtensaOpcodeUintTest)(DisasContext *dc,
 355                                         const uint32_t arg[],
 356                                         const uint32_t par[]);
 357
 358enum {
 359    XTENSA_OP_ILL = 0x1,
 360    XTENSA_OP_PRIVILEGED = 0x2,
 361    XTENSA_OP_SYSCALL = 0x4,
 362    XTENSA_OP_DEBUG_BREAK = 0x8,
 363
 364    XTENSA_OP_OVERFLOW = 0x10,
 365    XTENSA_OP_UNDERFLOW = 0x20,
 366    XTENSA_OP_ALLOCA = 0x40,
 367    XTENSA_OP_COPROCESSOR = 0x80,
 368
 369    XTENSA_OP_DIVIDE_BY_ZERO = 0x100,
 370
 371    XTENSA_OP_CHECK_INTERRUPTS = 0x200,
 372    XTENSA_OP_EXIT_TB_M1 = 0x400,
 373    XTENSA_OP_EXIT_TB_0 = 0x800,
 374};
 375
 376typedef struct XtensaOpcodeOps {
 377    const char *name;
 378    XtensaOpcodeOp translate;
 379    XtensaOpcodeBoolTest test_ill;
 380    XtensaOpcodeUintTest test_overflow;
 381    const uint32_t *par;
 382    uint32_t op_flags;
 383    uint32_t windowed_register_op;
 384    uint32_t coprocessor;
 385} XtensaOpcodeOps;
 386
 387typedef struct XtensaOpcodeTranslators {
 388    unsigned num_opcodes;
 389    const XtensaOpcodeOps *opcode;
 390} XtensaOpcodeTranslators;
 391
 392extern const XtensaOpcodeTranslators xtensa_core_opcodes;
 393extern const XtensaOpcodeTranslators xtensa_fpu2000_opcodes;
 394
 395struct XtensaConfig {
 396    const char *name;
 397    uint64_t options;
 398    XtensaGdbRegmap gdb_regmap;
 399    unsigned nareg;
 400    int excm_level;
 401    int ndepc;
 402    unsigned inst_fetch_width;
 403    uint32_t vecbase;
 404    uint32_t exception_vector[EXC_MAX];
 405    unsigned ninterrupt;
 406    unsigned nlevel;
 407    uint32_t interrupt_vector[MAX_NLEVEL + MAX_NNMI + 1];
 408    uint32_t level_mask[MAX_NLEVEL + MAX_NNMI + 1];
 409    uint32_t inttype_mask[INTTYPE_MAX];
 410    struct {
 411        uint32_t level;
 412        interrupt_type inttype;
 413    } interrupt[MAX_NINTERRUPT];
 414    unsigned nccompare;
 415    uint32_t timerint[MAX_NCCOMPARE];
 416    unsigned nextint;
 417    unsigned extint[MAX_NINTERRUPT];
 418
 419    unsigned debug_level;
 420    unsigned nibreak;
 421    unsigned ndbreak;
 422
 423    unsigned icache_ways;
 424    unsigned dcache_ways;
 425    uint32_t memctl_mask;
 426
 427    XtensaMemory instrom;
 428    XtensaMemory instram;
 429    XtensaMemory datarom;
 430    XtensaMemory dataram;
 431    XtensaMemory sysrom;
 432    XtensaMemory sysram;
 433
 434    uint32_t configid[2];
 435
 436    void *isa_internal;
 437    xtensa_isa isa;
 438    XtensaOpcodeOps **opcode_ops;
 439    const XtensaOpcodeTranslators **opcode_translators;
 440
 441    uint32_t clock_freq_khz;
 442
 443    xtensa_tlb itlb;
 444    xtensa_tlb dtlb;
 445};
 446
 447typedef struct XtensaConfigList {
 448    const XtensaConfig *config;
 449    struct XtensaConfigList *next;
 450} XtensaConfigList;
 451
 452#ifdef HOST_WORDS_BIGENDIAN
 453enum {
 454    FP_F32_HIGH,
 455    FP_F32_LOW,
 456};
 457#else
 458enum {
 459    FP_F32_LOW,
 460    FP_F32_HIGH,
 461};
 462#endif
 463
 464typedef struct CPUXtensaState {
 465    const XtensaConfig *config;
 466    uint32_t regs[16];
 467    uint32_t pc;
 468    uint32_t sregs[256];
 469    uint32_t uregs[256];
 470    uint32_t phys_regs[MAX_NAREG];
 471    union {
 472        float32 f32[2];
 473        float64 f64;
 474    } fregs[16];
 475    float_status fp_status;
 476
 477#ifndef CONFIG_USER_ONLY
 478    xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
 479    xtensa_tlb_entry dtlb[10][MAX_TLB_WAY_SIZE];
 480    unsigned autorefill_idx;
 481    bool runstall;
 482    AddressSpace *address_space_er;
 483    MemoryRegion *system_er;
 484    int pending_irq_level; /* level of last raised IRQ */
 485    void **irq_inputs;
 486    XtensaCcompareTimer ccompare[MAX_NCCOMPARE];
 487    uint64_t time_base;
 488    uint64_t ccount_time;
 489    uint32_t ccount_base;
 490#endif
 491
 492    int exception_taken;
 493    int yield_needed;
 494    unsigned static_vectors;
 495
 496    /* Watchpoints for DBREAK registers */
 497    struct CPUWatchpoint *cpu_watchpoint[MAX_NDBREAK];
 498
 499    CPU_COMMON
 500} CPUXtensaState;
 501
 502/**
 503 * XtensaCPU:
 504 * @env: #CPUXtensaState
 505 *
 506 * An Xtensa CPU.
 507 */
 508struct XtensaCPU {
 509    /*< private >*/
 510    CPUState parent_obj;
 511    /*< public >*/
 512
 513    CPUXtensaState env;
 514};
 515
 516static inline XtensaCPU *xtensa_env_get_cpu(const CPUXtensaState *env)
 517{
 518    return container_of(env, XtensaCPU, env);
 519}
 520
 521#define ENV_GET_CPU(e) CPU(xtensa_env_get_cpu(e))
 522
 523#define ENV_OFFSET offsetof(XtensaCPU, env)
 524
 525
 526int xtensa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, int size,
 527                                int mmu_idx);
 528void xtensa_cpu_do_interrupt(CPUState *cpu);
 529bool xtensa_cpu_exec_interrupt(CPUState *cpu, int interrupt_request);
 530void xtensa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
 531                                      unsigned size, MMUAccessType access_type,
 532                                      int mmu_idx, MemTxAttrs attrs,
 533                                      MemTxResult response, uintptr_t retaddr);
 534void xtensa_cpu_dump_state(CPUState *cpu, FILE *f,
 535                           fprintf_function cpu_fprintf, int flags);
 536hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 537void xtensa_count_regs(const XtensaConfig *config,
 538                       unsigned *n_regs, unsigned *n_core_regs);
 539int xtensa_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 540int xtensa_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 541void xtensa_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
 542                                    MMUAccessType access_type,
 543                                    int mmu_idx, uintptr_t retaddr);
 544
 545#define cpu_signal_handler cpu_xtensa_signal_handler
 546#define cpu_list xtensa_cpu_list
 547
 548#define XTENSA_CPU_TYPE_SUFFIX "-" TYPE_XTENSA_CPU
 549#define XTENSA_CPU_TYPE_NAME(model) model XTENSA_CPU_TYPE_SUFFIX
 550#define CPU_RESOLVING_TYPE TYPE_XTENSA_CPU
 551
 552#ifdef TARGET_WORDS_BIGENDIAN
 553#define XTENSA_DEFAULT_CPU_MODEL "fsf"
 554#define XTENSA_DEFAULT_CPU_NOMMU_MODEL "fsf"
 555#else
 556#define XTENSA_DEFAULT_CPU_MODEL "dc232b"
 557#define XTENSA_DEFAULT_CPU_NOMMU_MODEL "de212"
 558#endif
 559#define XTENSA_DEFAULT_CPU_TYPE \
 560    XTENSA_CPU_TYPE_NAME(XTENSA_DEFAULT_CPU_MODEL)
 561#define XTENSA_DEFAULT_CPU_NOMMU_TYPE \
 562    XTENSA_CPU_TYPE_NAME(XTENSA_DEFAULT_CPU_NOMMU_MODEL)
 563
 564void xtensa_translate_init(void);
 565void xtensa_breakpoint_handler(CPUState *cs);
 566void xtensa_finalize_config(XtensaConfig *config);
 567void xtensa_register_core(XtensaConfigList *node);
 568void xtensa_sim_open_console(Chardev *chr);
 569void check_interrupts(CPUXtensaState *s);
 570void xtensa_irq_init(CPUXtensaState *env);
 571void *xtensa_get_extint(CPUXtensaState *env, unsigned extint);
 572void xtensa_timer_irq(CPUXtensaState *env, uint32_t id, uint32_t active);
 573int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
 574void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
 575void xtensa_sync_window_from_phys(CPUXtensaState *env);
 576void xtensa_sync_phys_from_window(CPUXtensaState *env);
 577void xtensa_rotate_window(CPUXtensaState *env, uint32_t delta);
 578void xtensa_restore_owb(CPUXtensaState *env);
 579void debug_exception_env(CPUXtensaState *new_env, uint32_t cause);
 580
 581static inline void xtensa_select_static_vectors(CPUXtensaState *env,
 582                                                unsigned n)
 583{
 584    assert(n < 2);
 585    env->static_vectors = n;
 586}
 587void xtensa_runstall(CPUXtensaState *env, bool runstall);
 588XtensaOpcodeOps *xtensa_find_opcode_ops(const XtensaOpcodeTranslators *t,
 589                                        const char *opcode);
 590
 591#define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
 592#define XTENSA_OPTION_ALL (~(uint64_t)0)
 593
 594static inline bool xtensa_option_bits_enabled(const XtensaConfig *config,
 595        uint64_t opt)
 596{
 597    return (config->options & opt) != 0;
 598}
 599
 600static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt)
 601{
 602    return xtensa_option_bits_enabled(config, XTENSA_OPTION_BIT(opt));
 603}
 604
 605static inline int xtensa_get_cintlevel(const CPUXtensaState *env)
 606{
 607    int level = (env->sregs[PS] & PS_INTLEVEL) >> PS_INTLEVEL_SHIFT;
 608    if ((env->sregs[PS] & PS_EXCM) && env->config->excm_level > level) {
 609        level = env->config->excm_level;
 610    }
 611    return level;
 612}
 613
 614static inline int xtensa_get_ring(const CPUXtensaState *env)
 615{
 616    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
 617        return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
 618    } else {
 619        return 0;
 620    }
 621}
 622
 623static inline int xtensa_get_cring(const CPUXtensaState *env)
 624{
 625    if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) &&
 626            (env->sregs[PS] & PS_EXCM) == 0) {
 627        return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
 628    } else {
 629        return 0;
 630    }
 631}
 632
 633#ifndef CONFIG_USER_ONLY
 634uint32_t xtensa_tlb_get_addr_mask(const CPUXtensaState *env,
 635                                  bool dtlb, uint32_t way);
 636void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb,
 637        uint32_t *vpn, uint32_t wi, uint32_t *ei);
 638int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb,
 639        uint32_t *pwi, uint32_t *pei, uint8_t *pring);
 640void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
 641        xtensa_tlb_entry *entry, bool dtlb,
 642        unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
 643void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
 644        unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
 645int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb,
 646        uint32_t vaddr, int is_write, int mmu_idx,
 647        uint32_t *paddr, uint32_t *page_size, unsigned *access);
 648void reset_mmu(CPUXtensaState *env);
 649void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUXtensaState *env);
 650
 651static inline MemoryRegion *xtensa_get_er_region(CPUXtensaState *env)
 652{
 653    return env->system_er;
 654}
 655
 656static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env,
 657        bool dtlb, unsigned wi, unsigned ei)
 658{
 659    return dtlb ?
 660        env->dtlb[wi] + ei :
 661        env->itlb[wi] + ei;
 662}
 663#endif
 664
 665static inline uint32_t xtensa_replicate_windowstart(CPUXtensaState *env)
 666{
 667    return env->sregs[WINDOW_START] |
 668        (env->sregs[WINDOW_START] << env->config->nareg / 4);
 669}
 670
 671/* MMU modes definitions */
 672#define MMU_MODE0_SUFFIX _ring0
 673#define MMU_MODE1_SUFFIX _ring1
 674#define MMU_MODE2_SUFFIX _ring2
 675#define MMU_MODE3_SUFFIX _ring3
 676#define MMU_USER_IDX 3
 677
 678static inline int cpu_mmu_index(CPUXtensaState *env, bool ifetch)
 679{
 680    return xtensa_get_cring(env);
 681}
 682
 683#define XTENSA_TBFLAG_RING_MASK 0x3
 684#define XTENSA_TBFLAG_EXCM 0x4
 685#define XTENSA_TBFLAG_LITBASE 0x8
 686#define XTENSA_TBFLAG_DEBUG 0x10
 687#define XTENSA_TBFLAG_ICOUNT 0x20
 688#define XTENSA_TBFLAG_CPENABLE_MASK 0x3fc0
 689#define XTENSA_TBFLAG_CPENABLE_SHIFT 6
 690#define XTENSA_TBFLAG_EXCEPTION 0x4000
 691#define XTENSA_TBFLAG_WINDOW_MASK 0x18000
 692#define XTENSA_TBFLAG_WINDOW_SHIFT 15
 693#define XTENSA_TBFLAG_YIELD 0x20000
 694#define XTENSA_TBFLAG_CWOE 0x40000
 695#define XTENSA_TBFLAG_CALLINC_MASK 0x180000
 696#define XTENSA_TBFLAG_CALLINC_SHIFT 19
 697
 698static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
 699        target_ulong *cs_base, uint32_t *flags)
 700{
 701    CPUState *cs = CPU(xtensa_env_get_cpu(env));
 702
 703    *pc = env->pc;
 704    *cs_base = 0;
 705    *flags = 0;
 706    *flags |= xtensa_get_ring(env);
 707    if (env->sregs[PS] & PS_EXCM) {
 708        *flags |= XTENSA_TBFLAG_EXCM;
 709    }
 710    if (xtensa_option_enabled(env->config, XTENSA_OPTION_EXTENDED_L32R) &&
 711            (env->sregs[LITBASE] & 1)) {
 712        *flags |= XTENSA_TBFLAG_LITBASE;
 713    }
 714    if (xtensa_option_enabled(env->config, XTENSA_OPTION_DEBUG)) {
 715        if (xtensa_get_cintlevel(env) < env->config->debug_level) {
 716            *flags |= XTENSA_TBFLAG_DEBUG;
 717        }
 718        if (xtensa_get_cintlevel(env) < env->sregs[ICOUNTLEVEL]) {
 719            *flags |= XTENSA_TBFLAG_ICOUNT;
 720        }
 721    }
 722    if (xtensa_option_enabled(env->config, XTENSA_OPTION_COPROCESSOR)) {
 723        *flags |= env->sregs[CPENABLE] << XTENSA_TBFLAG_CPENABLE_SHIFT;
 724    }
 725    if (cs->singlestep_enabled && env->exception_taken) {
 726        *flags |= XTENSA_TBFLAG_EXCEPTION;
 727    }
 728    if (xtensa_option_enabled(env->config, XTENSA_OPTION_WINDOWED_REGISTER) &&
 729        (env->sregs[PS] & (PS_WOE | PS_EXCM)) == PS_WOE) {
 730        uint32_t windowstart = xtensa_replicate_windowstart(env) >>
 731            (env->sregs[WINDOW_BASE] + 1);
 732        uint32_t w = ctz32(windowstart | 0x8);
 733
 734        *flags |= (w << XTENSA_TBFLAG_WINDOW_SHIFT) | XTENSA_TBFLAG_CWOE;
 735        *flags |= extract32(env->sregs[PS], PS_CALLINC_SHIFT,
 736                            PS_CALLINC_LEN) << XTENSA_TBFLAG_CALLINC_SHIFT;
 737    } else {
 738        *flags |= 3 << XTENSA_TBFLAG_WINDOW_SHIFT;
 739    }
 740    if (env->yield_needed) {
 741        *flags |= XTENSA_TBFLAG_YIELD;
 742    }
 743}
 744
 745#include "exec/cpu-all.h"
 746
 747#endif
 748