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