File:  [Qemu by Fabrice Bellard] / qemu / target-xtensa / cpu.h
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:33:13 2018 UTC (2 years, 6 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1001, HEAD
qemu 1.0.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 CPUState 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:     EPC1 = 177,
  130:     DEPC = 192,
  131:     EPS2 = 194,
  132:     EXCSAVE1 = 209,
  133:     CPENABLE = 224,
  134:     INTSET = 226,
  135:     INTCLEAR = 227,
  136:     INTENABLE = 228,
  137:     PS = 230,
  138:     VECBASE = 231,
  139:     EXCCAUSE = 232,
  140:     CCOUNT = 234,
  141:     PRID = 235,
  142:     EXCVADDR = 238,
  143:     CCOMPARE = 240,
  144: };
  145: 
  146: #define PS_INTLEVEL 0xf
  147: #define PS_INTLEVEL_SHIFT 0
  148: 
  149: #define PS_EXCM 0x10
  150: #define PS_UM 0x20
  151: 
  152: #define PS_RING 0xc0
  153: #define PS_RING_SHIFT 6
  154: 
  155: #define PS_OWB 0xf00
  156: #define PS_OWB_SHIFT 8
  157: 
  158: #define PS_CALLINC 0x30000
  159: #define PS_CALLINC_SHIFT 16
  160: #define PS_CALLINC_LEN 2
  161: 
  162: #define PS_WOE 0x40000
  163: 
  164: #define MAX_NAREG 64
  165: #define MAX_NINTERRUPT 32
  166: #define MAX_NLEVEL 6
  167: #define MAX_NNMI 1
  168: #define MAX_NCCOMPARE 3
  169: #define MAX_TLB_WAY_SIZE 8
  170: 
  171: #define REGION_PAGE_MASK 0xe0000000
  172: 
  173: enum {
  174:     /* Static vectors */
  175:     EXC_RESET,
  176:     EXC_MEMORY_ERROR,
  177: 
  178:     /* Dynamic vectors */
  179:     EXC_WINDOW_OVERFLOW4,
  180:     EXC_WINDOW_UNDERFLOW4,
  181:     EXC_WINDOW_OVERFLOW8,
  182:     EXC_WINDOW_UNDERFLOW8,
  183:     EXC_WINDOW_OVERFLOW12,
  184:     EXC_WINDOW_UNDERFLOW12,
  185:     EXC_IRQ,
  186:     EXC_KERNEL,
  187:     EXC_USER,
  188:     EXC_DOUBLE,
  189:     EXC_MAX
  190: };
  191: 
  192: enum {
  193:     ILLEGAL_INSTRUCTION_CAUSE = 0,
  194:     SYSCALL_CAUSE,
  195:     INSTRUCTION_FETCH_ERROR_CAUSE,
  196:     LOAD_STORE_ERROR_CAUSE,
  197:     LEVEL1_INTERRUPT_CAUSE,
  198:     ALLOCA_CAUSE,
  199:     INTEGER_DIVIDE_BY_ZERO_CAUSE,
  200:     PRIVILEGED_CAUSE = 8,
  201:     LOAD_STORE_ALIGNMENT_CAUSE,
  202: 
  203:     INSTR_PIF_DATA_ERROR_CAUSE = 12,
  204:     LOAD_STORE_PIF_DATA_ERROR_CAUSE,
  205:     INSTR_PIF_ADDR_ERROR_CAUSE,
  206:     LOAD_STORE_PIF_ADDR_ERROR_CAUSE,
  207: 
  208:     INST_TLB_MISS_CAUSE,
  209:     INST_TLB_MULTI_HIT_CAUSE,
  210:     INST_FETCH_PRIVILEGE_CAUSE,
  211:     INST_FETCH_PROHIBITED_CAUSE = 20,
  212:     LOAD_STORE_TLB_MISS_CAUSE = 24,
  213:     LOAD_STORE_TLB_MULTI_HIT_CAUSE,
  214:     LOAD_STORE_PRIVILEGE_CAUSE,
  215:     LOAD_PROHIBITED_CAUSE = 28,
  216:     STORE_PROHIBITED_CAUSE,
  217: 
  218:     COPROCESSOR0_DISABLED = 32,
  219: };
  220: 
  221: typedef enum {
  222:     INTTYPE_LEVEL,
  223:     INTTYPE_EDGE,
  224:     INTTYPE_NMI,
  225:     INTTYPE_SOFTWARE,
  226:     INTTYPE_TIMER,
  227:     INTTYPE_DEBUG,
  228:     INTTYPE_WRITE_ERR,
  229:     INTTYPE_MAX
  230: } interrupt_type;
  231: 
  232: typedef struct xtensa_tlb_entry {
  233:     uint32_t vaddr;
  234:     uint32_t paddr;
  235:     uint8_t asid;
  236:     uint8_t attr;
  237:     bool variable;
  238: } xtensa_tlb_entry;
  239: 
  240: typedef struct xtensa_tlb {
  241:     unsigned nways;
  242:     const unsigned way_size[10];
  243:     bool varway56;
  244:     unsigned nrefillentries;
  245: } xtensa_tlb;
  246: 
  247: typedef struct XtensaGdbReg {
  248:     int targno;
  249:     int type;
  250:     int group;
  251: } XtensaGdbReg;
  252: 
  253: typedef struct XtensaGdbRegmap {
  254:     int num_regs;
  255:     int num_core_regs;
  256:     /* PC + a + ar + sr + ur */
  257:     XtensaGdbReg reg[1 + 16 + 64 + 256 + 256];
  258: } XtensaGdbRegmap;
  259: 
  260: typedef struct XtensaConfig {
  261:     const char *name;
  262:     uint64_t options;
  263:     XtensaGdbRegmap gdb_regmap;
  264:     unsigned nareg;
  265:     int excm_level;
  266:     int ndepc;
  267:     uint32_t vecbase;
  268:     uint32_t exception_vector[EXC_MAX];
  269:     unsigned ninterrupt;
  270:     unsigned nlevel;
  271:     uint32_t interrupt_vector[MAX_NLEVEL + MAX_NNMI + 1];
  272:     uint32_t level_mask[MAX_NLEVEL + MAX_NNMI + 1];
  273:     uint32_t inttype_mask[INTTYPE_MAX];
  274:     struct {
  275:         uint32_t level;
  276:         interrupt_type inttype;
  277:     } interrupt[MAX_NINTERRUPT];
  278:     unsigned nccompare;
  279:     uint32_t timerint[MAX_NCCOMPARE];
  280:     unsigned nextint;
  281:     unsigned extint[MAX_NINTERRUPT];
  282:     uint32_t clock_freq_khz;
  283: 
  284:     xtensa_tlb itlb;
  285:     xtensa_tlb dtlb;
  286: } XtensaConfig;
  287: 
  288: typedef struct XtensaConfigList {
  289:     const XtensaConfig *config;
  290:     struct XtensaConfigList *next;
  291: } XtensaConfigList;
  292: 
  293: typedef struct CPUXtensaState {
  294:     const XtensaConfig *config;
  295:     uint32_t regs[16];
  296:     uint32_t pc;
  297:     uint32_t sregs[256];
  298:     uint32_t uregs[256];
  299:     uint32_t phys_regs[MAX_NAREG];
  300: 
  301:     xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
  302:     xtensa_tlb_entry dtlb[10][MAX_TLB_WAY_SIZE];
  303:     unsigned autorefill_idx;
  304: 
  305:     int pending_irq_level; /* level of last raised IRQ */
  306:     void **irq_inputs;
  307:     QEMUTimer *ccompare_timer;
  308:     uint32_t wake_ccount;
  309:     int64_t halt_clock;
  310: 
  311:     int exception_taken;
  312: 
  313:     CPU_COMMON
  314: } CPUXtensaState;
  315: 
  316: #define cpu_init cpu_xtensa_init
  317: #define cpu_exec cpu_xtensa_exec
  318: #define cpu_gen_code cpu_xtensa_gen_code
  319: #define cpu_signal_handler cpu_xtensa_signal_handler
  320: #define cpu_list xtensa_cpu_list
  321: 
  322: CPUXtensaState *cpu_xtensa_init(const char *cpu_model);
  323: void xtensa_translate_init(void);
  324: int cpu_xtensa_exec(CPUXtensaState *s);
  325: void xtensa_register_core(XtensaConfigList *node);
  326: void do_interrupt(CPUXtensaState *s);
  327: void check_interrupts(CPUXtensaState *s);
  328: void xtensa_irq_init(CPUState *env);
  329: void *xtensa_get_extint(CPUState *env, unsigned extint);
  330: void xtensa_advance_ccount(CPUState *env, uint32_t d);
  331: void xtensa_timer_irq(CPUState *env, uint32_t id, uint32_t active);
  332: void xtensa_rearm_ccompare_timer(CPUState *env);
  333: int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
  334: void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
  335: void xtensa_sync_window_from_phys(CPUState *env);
  336: void xtensa_sync_phys_from_window(CPUState *env);
  337: uint32_t xtensa_tlb_get_addr_mask(const CPUState *env, bool dtlb, uint32_t way);
  338: void split_tlb_entry_spec_way(const CPUState *env, uint32_t v, bool dtlb,
  339:         uint32_t *vpn, uint32_t wi, uint32_t *ei);
  340: int xtensa_tlb_lookup(const CPUState *env, uint32_t addr, bool dtlb,
  341:         uint32_t *pwi, uint32_t *pei, uint8_t *pring);
  342: void xtensa_tlb_set_entry(CPUState *env, bool dtlb,
  343:         unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
  344: int xtensa_get_physical_addr(CPUState *env,
  345:         uint32_t vaddr, int is_write, int mmu_idx,
  346:         uint32_t *paddr, uint32_t *page_size, unsigned *access);
  347: 
  348: 
  349: #define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
  350: 
  351: static inline bool xtensa_option_bits_enabled(const XtensaConfig *config,
  352:         uint64_t opt)
  353: {
  354:     return (config->options & opt) != 0;
  355: }
  356: 
  357: static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt)
  358: {
  359:     return xtensa_option_bits_enabled(config, XTENSA_OPTION_BIT(opt));
  360: }
  361: 
  362: static inline int xtensa_get_cintlevel(const CPUState *env)
  363: {
  364:     int level = (env->sregs[PS] & PS_INTLEVEL) >> PS_INTLEVEL_SHIFT;
  365:     if ((env->sregs[PS] & PS_EXCM) && env->config->excm_level > level) {
  366:         level = env->config->excm_level;
  367:     }
  368:     return level;
  369: }
  370: 
  371: static inline int xtensa_get_ring(const CPUState *env)
  372: {
  373:     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
  374:         return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
  375:     } else {
  376:         return 0;
  377:     }
  378: }
  379: 
  380: static inline int xtensa_get_cring(const CPUState *env)
  381: {
  382:     if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) &&
  383:             (env->sregs[PS] & PS_EXCM) == 0) {
  384:         return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
  385:     } else {
  386:         return 0;
  387:     }
  388: }
  389: 
  390: static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUState *env,
  391:         bool dtlb, unsigned wi, unsigned ei)
  392: {
  393:     return dtlb ?
  394:         env->dtlb[wi] + ei :
  395:         env->itlb[wi] + ei;
  396: }
  397: 
  398: /* MMU modes definitions */
  399: #define MMU_MODE0_SUFFIX _ring0
  400: #define MMU_MODE1_SUFFIX _ring1
  401: #define MMU_MODE2_SUFFIX _ring2
  402: #define MMU_MODE3_SUFFIX _ring3
  403: 
  404: static inline int cpu_mmu_index(CPUState *env)
  405: {
  406:     return xtensa_get_cring(env);
  407: }
  408: 
  409: #define XTENSA_TBFLAG_RING_MASK 0x3
  410: #define XTENSA_TBFLAG_EXCM 0x4
  411: #define XTENSA_TBFLAG_LITBASE 0x8
  412: 
  413: static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
  414:         target_ulong *cs_base, int *flags)
  415: {
  416:     *pc = env->pc;
  417:     *cs_base = 0;
  418:     *flags = 0;
  419:     *flags |= xtensa_get_ring(env);
  420:     if (env->sregs[PS] & PS_EXCM) {
  421:         *flags |= XTENSA_TBFLAG_EXCM;
  422:     }
  423:     if (xtensa_option_enabled(env->config, XTENSA_OPTION_EXTENDED_L32R) &&
  424:             (env->sregs[LITBASE] & 1)) {
  425:         *flags |= XTENSA_TBFLAG_LITBASE;
  426:     }
  427: }
  428: 
  429: #include "cpu-all.h"
  430: #include "exec-all.h"
  431: 
  432: static inline int cpu_has_work(CPUState *env)
  433: {
  434:     return env->pending_irq_level;
  435: }
  436: 
  437: static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
  438: {
  439:     env->pc = tb->pc;
  440: }
  441: 
  442: #endif

unix.superglobalmegacorp.com