~ahs3/+junk/cq-qemu

« back to all changes in this revision

Viewing changes to target-xtensa/cpu.h

  • Committer: Al Stone
  • Date: 2012-02-09 01:17:20 UTC
  • Revision ID: albert.stone@canonical.com-20120209011720-tztl7ik3qayz80p4
first commit to bzr for qemu

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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