root / target-xtensa / cpu.h @ 4dd85b6b
History | View | Annotate | Download (11 kB)
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_IDIV, |
56 |
XTENSA_OPTION_MAC16, |
57 |
XTENSA_OPTION_MISC_OP, |
58 |
XTENSA_OPTION_COPROCESSOR, |
59 |
XTENSA_OPTION_BOOLEAN, |
60 |
XTENSA_OPTION_FP_COPROCESSOR, |
61 |
XTENSA_OPTION_MP_SYNCHRO, |
62 |
XTENSA_OPTION_CONDITIONAL_STORE, |
63 |
|
64 |
/* Interrupts and exceptions */
|
65 |
XTENSA_OPTION_EXCEPTION, |
66 |
XTENSA_OPTION_RELOCATABLE_VECTOR, |
67 |
XTENSA_OPTION_UNALIGNED_EXCEPTION, |
68 |
XTENSA_OPTION_INTERRUPT, |
69 |
XTENSA_OPTION_HIGH_PRIORITY_INTERRUPT, |
70 |
XTENSA_OPTION_TIMER_INTERRUPT, |
71 |
|
72 |
/* Local memory */
|
73 |
XTENSA_OPTION_ICACHE, |
74 |
XTENSA_OPTION_ICACHE_TEST, |
75 |
XTENSA_OPTION_ICACHE_INDEX_LOCK, |
76 |
XTENSA_OPTION_DCACHE, |
77 |
XTENSA_OPTION_DCACHE_TEST, |
78 |
XTENSA_OPTION_DCACHE_INDEX_LOCK, |
79 |
XTENSA_OPTION_IRAM, |
80 |
XTENSA_OPTION_IROM, |
81 |
XTENSA_OPTION_DRAM, |
82 |
XTENSA_OPTION_DROM, |
83 |
XTENSA_OPTION_XLMI, |
84 |
XTENSA_OPTION_HW_ALIGNMENT, |
85 |
XTENSA_OPTION_MEMORY_ECC_PARITY, |
86 |
|
87 |
/* Memory protection and translation */
|
88 |
XTENSA_OPTION_REGION_PROTECTION, |
89 |
XTENSA_OPTION_REGION_TRANSLATION, |
90 |
XTENSA_OPTION_MMU, |
91 |
|
92 |
/* Other */
|
93 |
XTENSA_OPTION_WINDOWED_REGISTER, |
94 |
XTENSA_OPTION_PROCESSOR_INTERFACE, |
95 |
XTENSA_OPTION_MISC_SR, |
96 |
XTENSA_OPTION_THREAD_POINTER, |
97 |
XTENSA_OPTION_PROCESSOR_ID, |
98 |
XTENSA_OPTION_DEBUG, |
99 |
XTENSA_OPTION_TRACE_PORT, |
100 |
}; |
101 |
|
102 |
enum {
|
103 |
THREADPTR = 231,
|
104 |
FCR = 232,
|
105 |
FSR = 233,
|
106 |
}; |
107 |
|
108 |
enum {
|
109 |
LBEG = 0,
|
110 |
LEND = 1,
|
111 |
LCOUNT = 2,
|
112 |
SAR = 3,
|
113 |
BR = 4,
|
114 |
LITBASE = 5,
|
115 |
SCOMPARE1 = 12,
|
116 |
WINDOW_BASE = 72,
|
117 |
WINDOW_START = 73,
|
118 |
PTEVADDR = 83,
|
119 |
RASID = 90,
|
120 |
ITLBCFG = 91,
|
121 |
DTLBCFG = 92,
|
122 |
EPC1 = 177,
|
123 |
DEPC = 192,
|
124 |
EPS2 = 194,
|
125 |
EXCSAVE1 = 209,
|
126 |
CPENABLE = 224,
|
127 |
INTSET = 226,
|
128 |
INTCLEAR = 227,
|
129 |
INTENABLE = 228,
|
130 |
PS = 230,
|
131 |
VECBASE = 231,
|
132 |
EXCCAUSE = 232,
|
133 |
CCOUNT = 234,
|
134 |
PRID = 235,
|
135 |
EXCVADDR = 238,
|
136 |
CCOMPARE = 240,
|
137 |
}; |
138 |
|
139 |
#define PS_INTLEVEL 0xf |
140 |
#define PS_INTLEVEL_SHIFT 0 |
141 |
|
142 |
#define PS_EXCM 0x10 |
143 |
#define PS_UM 0x20 |
144 |
|
145 |
#define PS_RING 0xc0 |
146 |
#define PS_RING_SHIFT 6 |
147 |
|
148 |
#define PS_OWB 0xf00 |
149 |
#define PS_OWB_SHIFT 8 |
150 |
|
151 |
#define PS_CALLINC 0x30000 |
152 |
#define PS_CALLINC_SHIFT 16 |
153 |
#define PS_CALLINC_LEN 2 |
154 |
|
155 |
#define PS_WOE 0x40000 |
156 |
|
157 |
#define MAX_NAREG 64 |
158 |
#define MAX_NINTERRUPT 32 |
159 |
#define MAX_NLEVEL 6 |
160 |
#define MAX_NNMI 1 |
161 |
#define MAX_NCCOMPARE 3 |
162 |
#define MAX_TLB_WAY_SIZE 8 |
163 |
|
164 |
#define REGION_PAGE_MASK 0xe0000000 |
165 |
|
166 |
enum {
|
167 |
/* Static vectors */
|
168 |
EXC_RESET, |
169 |
EXC_MEMORY_ERROR, |
170 |
|
171 |
/* Dynamic vectors */
|
172 |
EXC_WINDOW_OVERFLOW4, |
173 |
EXC_WINDOW_UNDERFLOW4, |
174 |
EXC_WINDOW_OVERFLOW8, |
175 |
EXC_WINDOW_UNDERFLOW8, |
176 |
EXC_WINDOW_OVERFLOW12, |
177 |
EXC_WINDOW_UNDERFLOW12, |
178 |
EXC_IRQ, |
179 |
EXC_KERNEL, |
180 |
EXC_USER, |
181 |
EXC_DOUBLE, |
182 |
EXC_MAX |
183 |
}; |
184 |
|
185 |
enum {
|
186 |
ILLEGAL_INSTRUCTION_CAUSE = 0,
|
187 |
SYSCALL_CAUSE, |
188 |
INSTRUCTION_FETCH_ERROR_CAUSE, |
189 |
LOAD_STORE_ERROR_CAUSE, |
190 |
LEVEL1_INTERRUPT_CAUSE, |
191 |
ALLOCA_CAUSE, |
192 |
INTEGER_DIVIDE_BY_ZERO_CAUSE, |
193 |
PRIVILEGED_CAUSE = 8,
|
194 |
LOAD_STORE_ALIGNMENT_CAUSE, |
195 |
|
196 |
INSTR_PIF_DATA_ERROR_CAUSE = 12,
|
197 |
LOAD_STORE_PIF_DATA_ERROR_CAUSE, |
198 |
INSTR_PIF_ADDR_ERROR_CAUSE, |
199 |
LOAD_STORE_PIF_ADDR_ERROR_CAUSE, |
200 |
|
201 |
INST_TLB_MISS_CAUSE, |
202 |
INST_TLB_MULTI_HIT_CAUSE, |
203 |
INST_FETCH_PRIVILEGE_CAUSE, |
204 |
INST_FETCH_PROHIBITED_CAUSE = 20,
|
205 |
LOAD_STORE_TLB_MISS_CAUSE = 24,
|
206 |
LOAD_STORE_TLB_MULTI_HIT_CAUSE, |
207 |
LOAD_STORE_PRIVILEGE_CAUSE, |
208 |
LOAD_PROHIBITED_CAUSE = 28,
|
209 |
STORE_PROHIBITED_CAUSE, |
210 |
|
211 |
COPROCESSOR0_DISABLED = 32,
|
212 |
}; |
213 |
|
214 |
typedef enum { |
215 |
INTTYPE_LEVEL, |
216 |
INTTYPE_EDGE, |
217 |
INTTYPE_NMI, |
218 |
INTTYPE_SOFTWARE, |
219 |
INTTYPE_TIMER, |
220 |
INTTYPE_DEBUG, |
221 |
INTTYPE_WRITE_ERR, |
222 |
INTTYPE_MAX |
223 |
} interrupt_type; |
224 |
|
225 |
typedef struct xtensa_tlb_entry { |
226 |
uint32_t vaddr; |
227 |
uint32_t paddr; |
228 |
uint8_t asid; |
229 |
uint8_t attr; |
230 |
bool variable;
|
231 |
} xtensa_tlb_entry; |
232 |
|
233 |
typedef struct xtensa_tlb { |
234 |
unsigned nways;
|
235 |
const unsigned way_size[10]; |
236 |
bool varway56;
|
237 |
unsigned nrefillentries;
|
238 |
} xtensa_tlb; |
239 |
|
240 |
typedef struct XtensaGdbReg { |
241 |
int targno;
|
242 |
int type;
|
243 |
int group;
|
244 |
} XtensaGdbReg; |
245 |
|
246 |
typedef struct XtensaGdbRegmap { |
247 |
int num_regs;
|
248 |
int num_core_regs;
|
249 |
/* PC + a + ar + sr + ur */
|
250 |
XtensaGdbReg reg[1 + 16 + 64 + 256 + 256]; |
251 |
} XtensaGdbRegmap; |
252 |
|
253 |
typedef struct XtensaConfig { |
254 |
const char *name; |
255 |
uint64_t options; |
256 |
XtensaGdbRegmap gdb_regmap; |
257 |
unsigned nareg;
|
258 |
int excm_level;
|
259 |
int ndepc;
|
260 |
uint32_t vecbase; |
261 |
uint32_t exception_vector[EXC_MAX]; |
262 |
unsigned ninterrupt;
|
263 |
unsigned nlevel;
|
264 |
uint32_t interrupt_vector[MAX_NLEVEL + MAX_NNMI + 1];
|
265 |
uint32_t level_mask[MAX_NLEVEL + MAX_NNMI + 1];
|
266 |
uint32_t inttype_mask[INTTYPE_MAX]; |
267 |
struct {
|
268 |
uint32_t level; |
269 |
interrupt_type inttype; |
270 |
} interrupt[MAX_NINTERRUPT]; |
271 |
unsigned nccompare;
|
272 |
uint32_t timerint[MAX_NCCOMPARE]; |
273 |
uint32_t clock_freq_khz; |
274 |
|
275 |
xtensa_tlb itlb; |
276 |
xtensa_tlb dtlb; |
277 |
} XtensaConfig; |
278 |
|
279 |
typedef struct CPUXtensaState { |
280 |
const XtensaConfig *config;
|
281 |
uint32_t regs[16];
|
282 |
uint32_t pc; |
283 |
uint32_t sregs[256];
|
284 |
uint32_t uregs[256];
|
285 |
uint32_t phys_regs[MAX_NAREG]; |
286 |
|
287 |
xtensa_tlb_entry itlb[7][MAX_TLB_WAY_SIZE];
|
288 |
xtensa_tlb_entry dtlb[10][MAX_TLB_WAY_SIZE];
|
289 |
unsigned autorefill_idx;
|
290 |
|
291 |
int pending_irq_level; /* level of last raised IRQ */ |
292 |
void **irq_inputs;
|
293 |
QEMUTimer *ccompare_timer; |
294 |
uint32_t wake_ccount; |
295 |
int64_t halt_clock; |
296 |
|
297 |
int exception_taken;
|
298 |
|
299 |
CPU_COMMON |
300 |
} CPUXtensaState; |
301 |
|
302 |
#define cpu_init cpu_xtensa_init
|
303 |
#define cpu_exec cpu_xtensa_exec
|
304 |
#define cpu_gen_code cpu_xtensa_gen_code
|
305 |
#define cpu_signal_handler cpu_xtensa_signal_handler
|
306 |
#define cpu_list xtensa_cpu_list
|
307 |
|
308 |
CPUXtensaState *cpu_xtensa_init(const char *cpu_model); |
309 |
void xtensa_translate_init(void); |
310 |
int cpu_xtensa_exec(CPUXtensaState *s);
|
311 |
void do_interrupt(CPUXtensaState *s);
|
312 |
void check_interrupts(CPUXtensaState *s);
|
313 |
void xtensa_irq_init(CPUState *env);
|
314 |
void xtensa_advance_ccount(CPUState *env, uint32_t d);
|
315 |
void xtensa_timer_irq(CPUState *env, uint32_t id, uint32_t active);
|
316 |
int cpu_xtensa_signal_handler(int host_signum, void *pinfo, void *puc); |
317 |
void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf);
|
318 |
void xtensa_sync_window_from_phys(CPUState *env);
|
319 |
void xtensa_sync_phys_from_window(CPUState *env);
|
320 |
uint32_t xtensa_tlb_get_addr_mask(const CPUState *env, bool dtlb, uint32_t way); |
321 |
void split_tlb_entry_spec_way(const CPUState *env, uint32_t v, bool dtlb, |
322 |
uint32_t *vpn, uint32_t wi, uint32_t *ei); |
323 |
int xtensa_tlb_lookup(const CPUState *env, uint32_t addr, bool dtlb, |
324 |
uint32_t *pwi, uint32_t *pei, uint8_t *pring); |
325 |
void xtensa_tlb_set_entry(CPUState *env, bool dtlb, |
326 |
unsigned wi, unsigned ei, uint32_t vpn, uint32_t pte); |
327 |
int xtensa_get_physical_addr(CPUState *env,
|
328 |
uint32_t vaddr, int is_write, int mmu_idx, |
329 |
uint32_t *paddr, uint32_t *page_size, unsigned *access);
|
330 |
|
331 |
|
332 |
#define XTENSA_OPTION_BIT(opt) (((uint64_t)1) << (opt)) |
333 |
|
334 |
static inline bool xtensa_option_bits_enabled(const XtensaConfig *config, |
335 |
uint64_t opt) |
336 |
{ |
337 |
return (config->options & opt) != 0; |
338 |
} |
339 |
|
340 |
static inline bool xtensa_option_enabled(const XtensaConfig *config, int opt) |
341 |
{ |
342 |
return xtensa_option_bits_enabled(config, XTENSA_OPTION_BIT(opt));
|
343 |
} |
344 |
|
345 |
static inline int xtensa_get_cintlevel(const CPUState *env) |
346 |
{ |
347 |
int level = (env->sregs[PS] & PS_INTLEVEL) >> PS_INTLEVEL_SHIFT;
|
348 |
if ((env->sregs[PS] & PS_EXCM) && env->config->excm_level > level) {
|
349 |
level = env->config->excm_level; |
350 |
} |
351 |
return level;
|
352 |
} |
353 |
|
354 |
static inline int xtensa_get_ring(const CPUState *env) |
355 |
{ |
356 |
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) {
|
357 |
return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
|
358 |
} else {
|
359 |
return 0; |
360 |
} |
361 |
} |
362 |
|
363 |
static inline int xtensa_get_cring(const CPUState *env) |
364 |
{ |
365 |
if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) &&
|
366 |
(env->sregs[PS] & PS_EXCM) == 0) {
|
367 |
return (env->sregs[PS] & PS_RING) >> PS_RING_SHIFT;
|
368 |
} else {
|
369 |
return 0; |
370 |
} |
371 |
} |
372 |
|
373 |
static inline xtensa_tlb_entry *xtensa_tlb_get_entry(CPUState *env, |
374 |
bool dtlb, unsigned wi, unsigned ei) |
375 |
{ |
376 |
return dtlb ?
|
377 |
env->dtlb[wi] + ei : |
378 |
env->itlb[wi] + ei; |
379 |
} |
380 |
|
381 |
/* MMU modes definitions */
|
382 |
#define MMU_MODE0_SUFFIX _ring0
|
383 |
#define MMU_MODE1_SUFFIX _ring1
|
384 |
#define MMU_MODE2_SUFFIX _ring2
|
385 |
#define MMU_MODE3_SUFFIX _ring3
|
386 |
|
387 |
static inline int cpu_mmu_index(CPUState *env) |
388 |
{ |
389 |
return xtensa_get_cring(env);
|
390 |
} |
391 |
|
392 |
#define XTENSA_TBFLAG_RING_MASK 0x3 |
393 |
#define XTENSA_TBFLAG_EXCM 0x4 |
394 |
#define XTENSA_TBFLAG_LITBASE 0x8 |
395 |
|
396 |
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc, |
397 |
target_ulong *cs_base, int *flags)
|
398 |
{ |
399 |
*pc = env->pc; |
400 |
*cs_base = 0;
|
401 |
*flags = 0;
|
402 |
*flags |= xtensa_get_ring(env); |
403 |
if (env->sregs[PS] & PS_EXCM) {
|
404 |
*flags |= XTENSA_TBFLAG_EXCM; |
405 |
} |
406 |
if (xtensa_option_enabled(env->config, XTENSA_OPTION_EXTENDED_L32R) &&
|
407 |
(env->sregs[LITBASE] & 1)) {
|
408 |
*flags |= XTENSA_TBFLAG_LITBASE; |
409 |
} |
410 |
} |
411 |
|
412 |
#include "cpu-all.h" |
413 |
#include "exec-all.h" |
414 |
|
415 |
static inline int cpu_has_work(CPUState *env) |
416 |
{ |
417 |
return env->pending_irq_level;
|
418 |
} |
419 |
|
420 |
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb) |
421 |
{ |
422 |
env->pc = tb->pc; |
423 |
} |
424 |
|
425 |
#endif
|