]> git.proxmox.com Git - qemu.git/blame - target-xtensa/cpu.h
target-xtensa: Let cpu_xtensa_init() return XtensaCPU
[qemu.git] / target-xtensa / cpu.h
CommitLineData
2328826b
MF
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
9349b4f9 34#define CPUArchState struct CPUXtensaState
2328826b
MF
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
dedc5eae
MF
48enum {
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,
7f65f4b0 55 XTENSA_OPTION_32_BIT_IMUL_HIGH,
dedc5eae
MF
56 XTENSA_OPTION_32_BIT_IDIV,
57 XTENSA_OPTION_MAC16,
7f65f4b0
MF
58 XTENSA_OPTION_MISC_OP_NSA,
59 XTENSA_OPTION_MISC_OP_MINMAX,
60 XTENSA_OPTION_MISC_OP_SEXT,
61 XTENSA_OPTION_MISC_OP_CLAMPS,
dedc5eae
MF
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
2af3da91
MF
106enum {
107 THREADPTR = 231,
108 FCR = 232,
109 FSR = 233,
110};
111
3580ecad 112enum {
797d780b
MF
113 LBEG = 0,
114 LEND = 1,
115 LCOUNT = 2,
3580ecad 116 SAR = 3,
4dd85b6b 117 BR = 4,
6ad6dbf7 118 LITBASE = 5,
809377aa 119 SCOMPARE1 = 12,
6825b6c3
MF
120 ACCLO = 16,
121 ACCHI = 17,
122 MR = 32,
553e44f9
MF
123 WINDOW_BASE = 72,
124 WINDOW_START = 73,
b67ea0cd
MF
125 PTEVADDR = 83,
126 RASID = 90,
127 ITLBCFG = 91,
128 DTLBCFG = 92,
e61dc8f7
MF
129 IBREAKENABLE = 96,
130 IBREAKA = 128,
f14c4b5f
MF
131 DBREAKA = 144,
132 DBREAKC = 160,
40643d7c
MF
133 EPC1 = 177,
134 DEPC = 192,
b994e91b 135 EPS2 = 194,
40643d7c 136 EXCSAVE1 = 209,
f3df4c04 137 CPENABLE = 224,
b994e91b
MF
138 INTSET = 226,
139 INTCLEAR = 227,
140 INTENABLE = 228,
f0a548b9 141 PS = 230,
97836cee 142 VECBASE = 231,
40643d7c 143 EXCCAUSE = 232,
ab58c5b4 144 DEBUGCAUSE = 233,
b994e91b 145 CCOUNT = 234,
f3df4c04 146 PRID = 235,
35b5c044
MF
147 ICOUNT = 236,
148 ICOUNTLEVEL = 237,
40643d7c 149 EXCVADDR = 238,
b994e91b 150 CCOMPARE = 240,
3580ecad
MF
151};
152
f0a548b9
MF
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
ab58c5b4
MF
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
f14c4b5f
MF
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
553e44f9 185#define MAX_NAREG 64
b994e91b
MF
186#define MAX_NINTERRUPT 32
187#define MAX_NLEVEL 6
188#define MAX_NNMI 1
189#define MAX_NCCOMPARE 3
b67ea0cd 190#define MAX_TLB_WAY_SIZE 8
f14c4b5f 191#define MAX_NDBREAK 2
b67ea0cd
MF
192
193#define REGION_PAGE_MASK 0xe0000000
553e44f9 194
40643d7c
MF
195enum {
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,
e61dc8f7 211 EXC_DEBUG,
40643d7c
MF
212 EXC_MAX
213};
214
215enum {
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
b994e91b
MF
244typedef 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
b67ea0cd
MF
255typedef 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
263typedef struct xtensa_tlb {
264 unsigned nways;
265 const unsigned way_size[10];
266 bool varway56;
267 unsigned nrefillentries;
268} xtensa_tlb;
269
ccfcaba6
MF
270typedef struct XtensaGdbReg {
271 int targno;
272 int type;
273 int group;
274} XtensaGdbReg;
275
276typedef 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
dedc5eae
MF
283typedef struct XtensaConfig {
284 const char *name;
285 uint64_t options;
ccfcaba6 286 XtensaGdbRegmap gdb_regmap;
553e44f9 287 unsigned nareg;
40643d7c
MF
288 int excm_level;
289 int ndepc;
97836cee 290 uint32_t vecbase;
40643d7c 291 uint32_t exception_vector[EXC_MAX];
b994e91b
MF
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];
b8929a54
MF
303 unsigned nextint;
304 unsigned extint[MAX_NINTERRUPT];
ab58c5b4
MF
305
306 unsigned debug_level;
307 unsigned nibreak;
308 unsigned ndbreak;
309
b994e91b 310 uint32_t clock_freq_khz;
b67ea0cd
MF
311
312 xtensa_tlb itlb;
313 xtensa_tlb dtlb;
dedc5eae
MF
314} XtensaConfig;
315
ac8b7db4
MF
316typedef struct XtensaConfigList {
317 const XtensaConfig *config;
318 struct XtensaConfigList *next;
319} XtensaConfigList;
320
2328826b 321typedef struct CPUXtensaState {
dedc5eae 322 const XtensaConfig *config;
2328826b
MF
323 uint32_t regs[16];
324 uint32_t pc;
325 uint32_t sregs[256];
2af3da91 326 uint32_t uregs[256];
553e44f9 327 uint32_t phys_regs[MAX_NAREG];
2328826b 328
b67ea0cd
MF
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
b994e91b
MF
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
40643d7c
MF
339 int exception_taken;
340
f14c4b5f
MF
341 /* Watchpoints for DBREAK registers */
342 CPUWatchpoint *cpu_watchpoint[MAX_NDBREAK];
343
2328826b
MF
344 CPU_COMMON
345} CPUXtensaState;
346
15be3171
AF
347#include "cpu-qom.h"
348
2328826b
MF
349#define cpu_exec cpu_xtensa_exec
350#define cpu_gen_code cpu_xtensa_gen_code
351#define cpu_signal_handler cpu_xtensa_signal_handler
352#define cpu_list xtensa_cpu_list
353
15be3171
AF
354XtensaCPU *cpu_xtensa_init(const char *cpu_model);
355
356static inline CPUXtensaState *cpu_init(const char *cpu_model)
357{
358 XtensaCPU *cpu = cpu_xtensa_init(cpu_model);
359 if (cpu == NULL) {
360 return NULL;
361 }
362 return &cpu->env;
363}
364
2328826b
MF
365void xtensa_translate_init(void);
366int cpu_xtensa_exec(CPUXtensaState *s);
ac8b7db4 367void xtensa_register_core(XtensaConfigList *node);
2328826b 368void do_interrupt(CPUXtensaState *s);
b994e91b 369void check_interrupts(CPUXtensaState *s);
97129ac8
AF
370void xtensa_irq_init(CPUXtensaState *env);
371void *xtensa_get_extint(CPUXtensaState *env, unsigned extint);
372void xtensa_advance_ccount(CPUXtensaState *env, uint32_t d);
373void xtensa_timer_irq(CPUXtensaState *env, uint32_t id, uint32_t active);
374void xtensa_rearm_ccompare_timer(CPUXtensaState *env);
2328826b
MF
375int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc);
376void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
97129ac8
AF
377void xtensa_sync_window_from_phys(CPUXtensaState *env);
378void xtensa_sync_phys_from_window(CPUXtensaState *env);
379uint32_t xtensa_tlb_get_addr_mask(const CPUXtensaState *env, bool dtlb, uint32_t way);
380void split_tlb_entry_spec_way(const CPUXtensaState *env, uint32_t v, bool dtlb,
b67ea0cd 381 uint32_t *vpn, uint32_t wi, uint32_t *ei);
97129ac8 382int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb,
b67ea0cd 383 uint32_t *pwi, uint32_t *pei, uint8_t *pring);
97129ac8 384void xtensa_tlb_set_entry(CPUXtensaState *env, bool dtlb,
b67ea0cd 385 unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte);
97129ac8 386int xtensa_get_physical_addr(CPUXtensaState *env,
b67ea0cd
MF
387 uint32_t vaddr, int is_write, int mmu_idx,
388 uint32_t *paddr, uint32_t *page_size, unsigned *access);
5087a72c 389void reset_mmu(CPUXtensaState *env);
97129ac8
AF
390void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUXtensaState *env);
391void debug_exception_env(CPUXtensaState *new_env, uint32_t cause);
b67ea0cd 392
2328826b 393
dedc5eae
MF
394#define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt))
395
b67ea0cd
MF
396static inline bool xtensa_option_bits_enabled(const XtensaConfig *config,
397 uint64_t opt)
398{
399 return (config->options & opt) != 0;
400}
401
dedc5eae
MF
402static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt)
403{
b67ea0cd 404 return xtensa_option_bits_enabled(config, XTENSA_OPTION_BIT(opt));
dedc5eae
MF
405}
406
97129ac8 407static inline int xtensa_get_cintlevel(const CPUXtensaState *env)
40643d7c
MF
408{
409 int level = (env->sregs[PS] & PS_INTLEVEL) >> PS_INTLEVEL_SHIFT;
410 if ((env->sregs[PS] & PS_EXCM) && env->config->excm_level > level) {
411 level = env->config->excm_level;
412 }
413 return level;
414}
415
97129ac8 416static inline int xtensa_get_ring(const CPUXtensaState *env)
f0a548b9
MF
417{
418 if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
419 return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
420 } else {
421 return 0;
422 }
423}
424
97129ac8 425static inline int xtensa_get_cring(const CPUXtensaState *env)
f0a548b9
MF
426{
427 if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) &&
428 (env->sregs[PS] & PS_EXCM) == 0) {
429 return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
430 } else {
431 return 0;
432 }
433}
434
97129ac8 435static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUXtensaState *env,
b67ea0cd
MF
436 bool dtlb, unsigned wi, unsigned ei)
437{
438 return dtlb ?
439 env->dtlb[wi] + ei :
440 env->itlb[wi] + ei;
441}
442
f0a548b9
MF
443/* MMU modes definitions */
444#define MMU_MODE0_SUFFIX _ring0
445#define MMU_MODE1_SUFFIX _ring1
446#define MMU_MODE2_SUFFIX _ring2
447#define MMU_MODE3_SUFFIX _ring3
448
97129ac8 449static inline int cpu_mmu_index(CPUXtensaState *env)
2328826b 450{
f0a548b9 451 return xtensa_get_cring(env);
2328826b
MF
452}
453
f0a548b9
MF
454#define XTENSA_TBFLAG_RING_MASK 0x3
455#define XTENSA_TBFLAG_EXCM 0x4
6ad6dbf7 456#define XTENSA_TBFLAG_LITBASE 0x8
e61dc8f7 457#define XTENSA_TBFLAG_DEBUG 0x10
35b5c044 458#define XTENSA_TBFLAG_ICOUNT 0x20
f0a548b9 459
97129ac8 460static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
2328826b
MF
461 target_ulong *cs_base, int *flags)
462{
463 *pc = env->pc;
464 *cs_base = 0;
465 *flags = 0;
f0a548b9
MF
466 *flags |= xtensa_get_ring(env);
467 if (env->sregs[PS] & PS_EXCM) {
468 *flags |= XTENSA_TBFLAG_EXCM;
469 }
6ad6dbf7
MF
470 if (xtensa_option_enabled(env->config, XTENSA_OPTION_EXTENDED_L32R) &&
471 (env->sregs[LITBASE] & 1)) {
472 *flags |= XTENSA_TBFLAG_LITBASE;
473 }
e61dc8f7
MF
474 if (xtensa_option_enabled(env->config, XTENSA_OPTION_DEBUG)) {
475 if (xtensa_get_cintlevel(env) < env->config->debug_level) {
476 *flags |= XTENSA_TBFLAG_DEBUG;
477 }
35b5c044
MF
478 if (xtensa_get_cintlevel(env) < env->sregs[ICOUNTLEVEL]) {
479 *flags |= XTENSA_TBFLAG_ICOUNT;
480 }
e61dc8f7 481 }
2328826b
MF
482}
483
484#include "cpu-all.h"
485#include "exec-all.h"
486
97129ac8 487static inline int cpu_has_work(CPUXtensaState *env)
2328826b 488{
b994e91b 489 return env->pending_irq_level;
2328826b
MF
490}
491
97129ac8 492static inline void cpu_pc_from_tb(CPUXtensaState *env, TranslationBlock *tb)
2328826b
MF
493{
494 env->pc = tb->pc;
495}
496
497#endif