Statistics
| Branch: | Revision:

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