File:  [Qemu by Fabrice Bellard] / qemu / target-xtensa / cpu.h
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:54:04 2018 UTC (2 years, 6 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1101, HEAD
qemu 1.1.1

    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 CPU_XTENSA_H
   29: #define CPU_XTENSA_H
   30: 
   31: #define TARGET_LONG_BITS 32
   32: #define ELF_MACHINE EM_XTENSA
   33: 
   34: #define CPUArchState struct CPUXtensaState
   35: 
   36: #include "config.h"
   37: #include "qemu-common.h"
   38: #include "cpu-defs.h"
   39: 
   40: #define TARGET_HAS_ICE 1
   41: 
   42: #define NB_MMU_MODES 4
   43: 
   44: #define TARGET_PHYS_ADDR_SPACE_BITS 32
   45: #define TARGET_VIRT_ADDR_SPACE_BITS 32
   46: #define TARGET_PAGE_BITS 12
   47: 
   48: enum {
   49:     /* Additional instructions */
   50:     XTENSA_OPTION_CODE_DENSITY,
   51:     XTENSA_OPTION_LOOP,
   52:     XTENSA_OPTION_EXTENDED_L32R,
   53:     XTENSA_OPTION_16_BIT_IMUL,
   54:     XTENSA_OPTION_32_BIT_IMUL,
   55:     XTENSA_OPTION_32_BIT_IMUL_HIGH,
   56:     XTENSA_OPTION_32_BIT_IDIV,
   57:     XTENSA_OPTION_MAC16,
   58:     XTENSA_OPTION_MISC_OP_NSA,
   59:     XTENSA_OPTION_MISC_OP_MINMAX,
   60:     XTENSA_OPTION_MISC_OP_SEXT,
   61:     XTENSA_OPTION_MISC_OP_CLAMPS,
   62:     XTENSA_OPTION_COPROCESSOR,
   63:     XTENSA_OPTION_BOOLEAN,
   64:     XTENSA_OPTION_FP_COPROCESSOR,
   65:     XTENSA_OPTION_MP_SYNCHRO,
   66:     XTENSA_OPTION_CONDITIONAL_STORE,
   67: 
   68:     /* Interrupts and exceptions */
   69:     XTENSA_OPTION_EXCEPTION,
   70:     XTENSA_OPTION_RELOCATABLE_VECTOR,
   71:     XTENSA_OPTION_UNALIGNED_EXCEPTION,
   72:     XTENSA_OPTION_INTERRUPT,
   73:     XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT,
   74:     XTENSA_OPTION_TIMER_INTERRUPT,
   75: 
   76:     /* Local memory */
   77:     XTENSA_OPTION_ICACHE,
   78:     XTENSA_OPTION_ICACHE_TEST,
   79:     XTENSA_OPTION_ICACHE_INDEX_LOCK,
   80:     XTENSA_OPTION_DCACHE,
   81:     XTENSA_OPTION_DCACHE_TEST,
   82:     XTENSA_OPTION_DCACHE_INDEX_LOCK,
   83:     XTENSA_OPTION_IRAM,
   84:     XTENSA_OPTION_IROM,
   85:     XTENSA_OPTION_DRAM,
   86:     XTENSA_OPTION_DROM,
   87:     XTENSA_OPTION_XLMI,
   88:     XTENSA_OPTION_HW_ALIGNMENT,
   89:     XTENSA_OPTION_MEMORY_ECC_PARITY,
   90: 
   91:     /* Memory protection and translation */
   92:     XTENSA_OPTION_REGION_PROTECTION,
   93:     XTENSA_OPTION_REGION_TRANSLATION,
   94:     XTENSA_OPTION_MMU,
   95: 
   96:     /* Other */
   97:     XTENSA_OPTION_WINDOWED_REGISTER,
   98:     XTENSA_OPTION_PROCESSOR_INTERFACE,
   99:     XTENSA_OPTION_MISC_SR,
  100:     XTENSA_OPTION_THREAD_POINTER,
  101:     XTENSA_OPTION_PROCESSOR_ID,
  102:     XTENSA_OPTION_DEBUG,
  103:     XTENSA_OPTION_TRACE_PORT,
  104: };
  105: 
  106: enum {
  107:     THREADPTR = 231,
  108:     FCR = 232,
  109:     FSR = 233,
  110: };
  111: 
  112: enum {
  113:     LBEG = 0,
  114:     LEND = 1,
  115:     LCOUNT = 2,
  116:     SAR = 3,
  117:     BR = 4,
  118:     LITBASE = 5,
  119:     SCOMPARE1 = 12,
  120:     ACCLO = 16,
  121:     ACCHI = 17,
  122:     MR = 32,
  123:     WINDOW_BASE = 72,
  124:     WINDOW_START = 73,
  125:     PTEVADDR = 83,
  126:     RASID = 90,
  127:     ITLBCFG = 91,
  128:     DTLBCFG = 92,
  129:     IBREAKENABLE = 96,
  130:     IBREAKA = 128,
  131:     DBREAKA = 144,
  132:     DBREAKC = 160,
  133:     EPC1 = 177,
  134:     DEPC = 192,
  135:     EPS2 = 194,
  136:     EXCSAVE1 = 209,
  137:     CPENABLE = 224,
  138:     INTSET = 226,
  139:     INTCLEAR = 227,
  140:     INTENABLE = 228,
  141:     PS = 230,
  142:     VECBASE = 231,
  143:     EXCCAUSE = 232,
  144:     DEBUGCAUSE = 233,
  145:     CCOUNT = 234,
  146:     PRID = 235,
  147:     ICOUNT = 236,
  148:     ICOUNTLEVEL = 237,
  149:     EXCVADDR = 238,
  150:     CCOMPARE = 240,
  151: };
  152: 
  153: #define PS_INTLEVEL 0xf
  154: #define PS_INTLEVEL_SHIFT 0
  155: 
  156: #define PS_EXCM 0x10
  157: #define PS_UM 0x20
  158: 
  159: #define PS_RING 0xc0
  160: #define PS_RING_SHIFT 6
  161: 
  162: #define PS_OWB 0xf00
  163: #define PS_OWB_SHIFT 8
  164: 
  165: #define PS_CALLINC 0x30000
  166: #define PS_CALLINC_SHIFT 16
  167: #define PS_CALLINC_LEN 2
  168: 
  169: #define PS_WOE 0x40000
  170: 
  171: #define DEBUGCAUSE_IC 0x1
  172: #define DEBUGCAUSE_IB 0x2
  173: #define DEBUGCAUSE_DB 0x4
  174: #define DEBUGCAUSE_BI 0x8
  175: #define DEBUGCAUSE_BN 0x10
  176: #define DEBUGCAUSE_DI 0x20
  177: #define DEBUGCAUSE_DBNUM 0xf00
  178: #define DEBUGCAUSE_DBNUM_SHIFT 8
  179: 
  180: #define DBREAKC_SB 0x80000000
  181: #define DBREAKC_LB 0x40000000
  182: #define DBREAKC_SB_LB (DBREAKC_SB | DBREAKC_LB)
  183: #define DBREAKC_MASK 0x3f
  184: 
  185: #define MAX_NAREG 64
  186: #define MAX_NINTERRUPT 32
  187: #define MAX_NLEVEL 6
  188: #define MAX_NNMI 1
  189: #define MAX_NCCOMPARE 3
  190: #define MAX_TLB_WAY_SIZE 8
  191: #define MAX_NDBREAK 2
  192: 
  193: #define REGION_PAGE_MASK 0xe0000000
  194: 
  195: enum {
  196:     /* Static vectors */
  197:     EXC_RESET,
  198:     EXC_MEMORY_ERROR,
  199: 
  200:     /* Dynamic vectors */
  201:     EXC_WINDOW_OVERFLOW4,
  202:     EXC_WINDOW_UNDERFLOW4,
  203:     EXC_WINDOW_OVERFLOW8,
  204:     EXC_WINDOW_UNDERFLOW8,
  205:     EXC_WINDOW_OVERFLOW12,
  206:     EXC_WINDOW_UNDERFLOW12,
  207:     EXC_IRQ,
  208:     EXC_KERNEL,
  209:     EXC_USER,
  210:     EXC_DOUBLE,
  211:     EXC_DEBUG,
  212:     EXC_MAX
  213: };
  214: 
  215: enum {
  216:     ILLEGAL_INSTRUCTION_CAUSE = 0,
  217:     SYSCALL_CAUSE,
  218:     INSTRUCTION_FETCH_ERROR_CAUSE,
  219:     LOAD_STORE_ERROR_CAUSE,
  220:     LEVEL1_INTERRUPT_CAUSE,
  221:     ALLOCA_CAUSE,
  222:     INTEGER_DIVIDE_BY_ZERO_CAUSE,
  223:     PRIVILEGED_CAUSE = 8,
  224:     LOAD_STORE_ALIGNMENT_CAUSE,
  225: 
  226:     INSTR_PIF_DATA_ERROR_CAUSE = 12,
  227:     LOAD_STORE_PIF_DATA_ERROR_CAUSE,
  228:     INSTR_PIF_ADDR_ERROR_CAUSE,
  229:     LOAD_STORE_PIF_ADDR_ERROR_CAUSE,
  230: 
  231:     INST_TLB_MISS_CAUSE,
  232:     INST_TLB_MULTI_HIT_CAUSE,
  233:     INST_FETCH_PRIVILEGE_CAUSE,
  234:     INST_FETCH_PROHIBITED_CAUSE = 20,
  235:     LOAD_STORE_TLB_MISS_CAUSE = 24,
  236:     LOAD_STORE_TLB_MULTI_HIT_CAUSE,
  237:     LOAD_STORE_PRIVILEGE_CAUSE,
  238:     LOAD_PROHIBITED_CAUSE = 28,
  239:     STORE_PROHIBITED_CAUSE,
  240: 
  241:     COPROCESSOR0_DISABLED = 32,
  242: };
  243: 
  244: typedef enum {
  245:     INTTYPE_LEVEL,
  246:     INTTYPE_EDGE,
  247:     INTTYPE_NMI,
  248:     INTTYPE_SOFTWARE,
  249:     INTTYPE_TIMER,
  250:     INTTYPE_DEBUG,
  251:     INTTYPE_WRITE_ERR,
  252:     INTTYPE_MAX
  253: } interrupt_type;
  254: 
  255: typedef struct xtensa_tlb_entry {
  256:     uint32_t vaddr;
  257:     uint32_t paddr;
  258:     uint8_t asid;
  259:     uint8_t attr;
  260:     bool variable;
  261: } xtensa_tlb_entry;
  262: 
  263: typedef struct xtensa_tlb {
  264:     unsigned nways;
  265:     const unsigned way_size[10];
  266:     bool varway56;
  267:     unsigned nrefillentries;
  268: } xtensa_tlb;
  269: 
  270: typedef struct XtensaGdbReg {
  271:     int targno;
  272:     int type;
  273:     int group;
  274: } XtensaGdbReg;
  275: 
  276: typedef struct XtensaGdbRegmap {
  277:     int num_regs;
  278:     int num_core_regs;
  279:     /* PC + a + ar + sr + ur */
  280:     XtensaGdbReg reg[1 + 16 + 64 + 256 + 256];
  281: } XtensaGdbRegmap;
  282: 
  283: typedef struct XtensaConfig {
  284:     const char *name;
  285:     uint64_t options;
  286:     XtensaGdbRegmap gdb_regmap;
  287:     unsigned nareg;
  288:     int excm_level;
  289:     int ndepc;
  290:     uint32_t vecbase;
  291:     uint32_t exception_vector[EXC_MAX];
  292:     unsigned ninterrupt;
  293:     unsigned nlevel;
  294:     uint32_t interrupt_vector[MAX_NLEVEL + MAX_NNMI + 1];
  295:     uint32_t level_mask[MAX_NLEVEL + MAX_NNMI + 1];
  296:     uint32_t inttype_mask[INTTYPE_MAX];
  297:     struct {
  298:         uint32_t level;
  299:         interrupt_type inttype;
  300:     } interrupt[MAX_NINTERRUPT];
  301:     unsigned nccompare;
  302:     uint32_t timerint[MAX_NCCOMPARE];
  303:     unsigned nextint;
  304:     unsigned extint[MAX_NINTERRUPT];
  305: 
  306:     unsigned debug_level;
  307:     unsigned nibreak;
  308:     unsigned ndbreak;
  309: 
  310:     uint32_t clock_freq_khz;
  311: 
  312:     xtensa_tlb itlb;
  313:     xtensa_tlb dtlb;
  314: } XtensaConfig;
  315: 
  316: typedef struct XtensaConfigList {
  317:     const XtensaConfig *config;
  318:     struct XtensaConfigList *next;
  319: } XtensaConfigList;
  320: 
  321: typedef struct CPUXtensaState {
  322:     const XtensaConfig *config;
  323:     uint32_t regs[16];
  324:     uint32_t pc;
  325:     uint32_t sregs[256];
  326:     uint32_t uregs[256];
  327:     uint32_t phys_regs[MAX_NAREG];
  328: 
  329:     xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
  330:     xtensa_tlb_entry dtlb[10][MAX_TLB_WAY_SIZE];
  331:     unsigned autorefill_idx;
  332: 
  333:     int pending_irq_level; /* level of last raised IRQ */
  334:     void **irq_inputs;
  335:     QEMUTimer *ccompare_timer;
  336:     uint32_t wake_ccount;
  337:     int64_t halt_clock;
  338: 
  339:     int exception_taken;
  340: 
  341:     /* Watchpoints for DBREAK registers */
  342:     CPUWatchpoint *cpu_watchpoint[MAX_NDBREAK];
  343: 
  344:     CPU_COMMON
  345: } CPUXtensaState;
  346: 
  347: #define cpu_init cpu_xtensa_init
  348: #define cpu_exec cpu_xtensa_exec
  349: #define cpu_gen_code cpu_xtensa_gen_code
  350: #define cpu_signal_handler cpu_xtensa_signal_handler
  351: #define cpu_list xtensa_cpu_list
  352: 
  353: CPUXtensaState *cpu_xtensa_init(const char *cpu_model);
  354: void xtensa_translate_init(void);
  355: int cpu_xtensa_exec(CPUXtensaState *s);
  356: void xtensa_register_core(XtensaConfigList *node);
  357: void do_interrupt(CPUXtensaState *s);
  358: void check_interrupts(CPUXtensaState *s);
  359: void xtensa_irq_init(CPUXtensaState *env);
  360: void *xtensa_get_extint(CPUXtensaState *env, unsigned extint);
  361: void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d);
  362: void xtensa_timer_irq(CPUXtensaState *env, uint32_t id, uint32_t active);
  363: void xtensa_rearm_ccompare_timer(CPUXtensaState *env);
  364: int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
  365: void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
  366: void xtensa_sync_window_from_phys(CPUXtensaState *env);
  367: void xtensa_sync_phys_from_window(CPUXtensaState *env);
  368: uint32_t xtensa_tlb_get_addr_mask(const CPUXtensaState *env, bool dtlb, uint32_t way);
  369: void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb,
  370:         uint32_t *vpn, uint32_t wi, uint32_t *ei);
  371: int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb,
  372:         uint32_t *pwi, uint32_t *pei, uint8_t *pring);
  373: void xtensa_tlb_set_entry_mmu(const CPUXtensaState *env,
  374:         xtensa_tlb_entry *entry, bool dtlb,
  375:         unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
  376: void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
  377:         unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
  378: int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb,
  379:         uint32_t vaddr, int is_write, int mmu_idx,
  380:         uint32_t *paddr, uint32_t *page_size, unsigned *access);
  381: void reset_mmu(CPUXtensaState *env);
  382: void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUXtensaState *env);
  383: void debug_exception_env(CPUXtensaState *new_env, uint32_t cause);
  384: 
  385: 
  386: #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
  387: 
  388: static inline bool xtensa_option_bits_enabled(const XtensaConfig *config,
  389:         uint64_t opt)
  390: {
  391:     return (config->options & opt) != 0;
  392: }
  393: 
  394: static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt)
  395: {
  396:     return xtensa_option_bits_enabled(config, XTENSA_OPTION_BIT(opt));
  397: }
  398: 
  399: static inline int xtensa_get_cintlevel(const CPUXtensaState *env)
  400: {
  401:     int level = (env->sregs[PS] & PS_INTLEVEL) >> PS_INTLEVEL_SHIFT;
  402:     if ((env->sregs[PS] & PS_EXCM) && env->config->excm_level > level) {
  403:         level = env->config->excm_level;
  404:     }
  405:     return level;
  406: }
  407: 
  408: static inline int xtensa_get_ring(const CPUXtensaState *env)
  409: {
  410:     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
  411:         return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
  412:     } else {
  413:         return 0;
  414:     }
  415: }
  416: 
  417: static inline int xtensa_get_cring(const CPUXtensaState *env)
  418: {
  419:     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) &&
  420:             (env->sregs[PS] & PS_EXCM) == 0) {
  421:         return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
  422:     } else {
  423:         return 0;
  424:     }
  425: }
  426: 
  427: static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env,
  428:         bool dtlb, unsigned wi, unsigned ei)
  429: {
  430:     return dtlb ?
  431:         env->dtlb[wi] + ei :
  432:         env->itlb[wi] + ei;
  433: }
  434: 
  435: /* MMU modes definitions */
  436: #define MMU_MODE0_SUFFIX _ring0
  437: #define MMU_MODE1_SUFFIX _ring1
  438: #define MMU_MODE2_SUFFIX _ring2
  439: #define MMU_MODE3_SUFFIX _ring3
  440: 
  441: static inline int cpu_mmu_index(CPUXtensaState *env)
  442: {
  443:     return xtensa_get_cring(env);
  444: }
  445: 
  446: #define XTENSA_TBFLAG_RING_MASK 0x3
  447: #define XTENSA_TBFLAG_EXCM 0x4
  448: #define XTENSA_TBFLAG_LITBASE 0x8
  449: #define XTENSA_TBFLAG_DEBUG 0x10
  450: #define XTENSA_TBFLAG_ICOUNT 0x20
  451: 
  452: static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
  453:         target_ulong *cs_base, int *flags)
  454: {
  455:     *pc = env->pc;
  456:     *cs_base = 0;
  457:     *flags = 0;
  458:     *flags |= xtensa_get_ring(env);
  459:     if (env->sregs[PS] & PS_EXCM) {
  460:         *flags |= XTENSA_TBFLAG_EXCM;
  461:     }
  462:     if (xtensa_option_enabled(env->config, XTENSA_OPTION_EXTENDED_L32R) &&
  463:             (env->sregs[LITBASE] & 1)) {
  464:         *flags |= XTENSA_TBFLAG_LITBASE;
  465:     }
  466:     if (xtensa_option_enabled(env->config, XTENSA_OPTION_DEBUG)) {
  467:         if (xtensa_get_cintlevel(env) < env->config->debug_level) {
  468:             *flags |= XTENSA_TBFLAG_DEBUG;
  469:         }
  470:         if (xtensa_get_cintlevel(env) < env->sregs[ICOUNTLEVEL]) {
  471:             *flags |= XTENSA_TBFLAG_ICOUNT;
  472:         }
  473:     }
  474: }
  475: 
  476: #include "cpu-all.h"
  477: #include "cpu-qom.h"
  478: #include "exec-all.h"
  479: 
  480: static inline int cpu_has_work(CPUXtensaState *env)
  481: {
  482:     return env->pending_irq_level;
  483: }
  484: 
  485: static inline void cpu_pc_from_tb(CPUXtensaState *env, TranslationBlock *tb)
  486: {
  487:     env->pc = tb->pc;
  488: }
  489: 
  490: #endif

unix.superglobalmegacorp.com