Annotation of qemu/target-xtensa/cpu.h, revision 1.1

1.1     ! root        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