Statistics
| Branch: | Revision:

root / target-openrisc / cpu.h @ 5b50e790

History | View | Annotate | Download (11.8 kB)

1
/*
2
 * OpenRISC virtual CPU header.
3
 *
4
 * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 */
19

    
20
#ifndef CPU_OPENRISC_H
21
#define CPU_OPENRISC_H
22

    
23
#define TARGET_LONG_BITS 32
24
#define ELF_MACHINE    EM_OPENRISC
25

    
26
#define CPUArchState struct CPUOpenRISCState
27

    
28
/* cpu_openrisc_map_address_* in CPUOpenRISCTLBContext need this decl.  */
29
struct OpenRISCCPU;
30

    
31
#include "config.h"
32
#include "qemu-common.h"
33
#include "exec/cpu-defs.h"
34
#include "fpu/softfloat.h"
35
#include "qom/cpu.h"
36

    
37
#define TYPE_OPENRISC_CPU "or32-cpu"
38

    
39
#define OPENRISC_CPU_CLASS(klass) \
40
    OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU)
41
#define OPENRISC_CPU(obj) \
42
    OBJECT_CHECK(OpenRISCCPU, (obj), TYPE_OPENRISC_CPU)
43
#define OPENRISC_CPU_GET_CLASS(obj) \
44
    OBJECT_GET_CLASS(OpenRISCCPUClass, (obj), TYPE_OPENRISC_CPU)
45

    
46
/**
47
 * OpenRISCCPUClass:
48
 * @parent_realize: The parent class' realize handler.
49
 * @parent_reset: The parent class' reset handler.
50
 *
51
 * A OpenRISC CPU model.
52
 */
53
typedef struct OpenRISCCPUClass {
54
    /*< private >*/
55
    CPUClass parent_class;
56
    /*< public >*/
57

    
58
    DeviceRealize parent_realize;
59
    void (*parent_reset)(CPUState *cpu);
60
} OpenRISCCPUClass;
61

    
62
#define NB_MMU_MODES    3
63

    
64
enum {
65
    MMU_NOMMU_IDX = 0,
66
    MMU_SUPERVISOR_IDX = 1,
67
    MMU_USER_IDX = 2,
68
};
69

    
70
#define TARGET_PAGE_BITS 13
71

    
72
#define TARGET_PHYS_ADDR_SPACE_BITS 32
73
#define TARGET_VIRT_ADDR_SPACE_BITS 32
74

    
75
#define SET_FP_CAUSE(reg, v)    do {\
76
                                    (reg) = ((reg) & ~(0x3f << 12)) | \
77
                                            ((v & 0x3f) << 12);\
78
                                } while (0)
79
#define GET_FP_ENABLE(reg)       (((reg) >>  7) & 0x1f)
80
#define UPDATE_FP_FLAGS(reg, v)   do {\
81
                                      (reg) |= ((v & 0x1f) << 2);\
82
                                  } while (0)
83

    
84
/* Version Register */
85
#define SPR_VR 0xFFFF003F
86

    
87
/* Internal flags, delay slot flag */
88
#define D_FLAG    1
89

    
90
/* Interrupt */
91
#define NR_IRQS  32
92

    
93
/* Unit presece register */
94
enum {
95
    UPR_UP = (1 << 0),
96
    UPR_DCP = (1 << 1),
97
    UPR_ICP = (1 << 2),
98
    UPR_DMP = (1 << 3),
99
    UPR_IMP = (1 << 4),
100
    UPR_MP = (1 << 5),
101
    UPR_DUP = (1 << 6),
102
    UPR_PCUR = (1 << 7),
103
    UPR_PMP = (1 << 8),
104
    UPR_PICP = (1 << 9),
105
    UPR_TTP = (1 << 10),
106
    UPR_CUP = (255 << 24),
107
};
108

    
109
/* CPU configure register */
110
enum {
111
    CPUCFGR_NSGF = (15 << 0),
112
    CPUCFGR_CGF = (1 << 4),
113
    CPUCFGR_OB32S = (1 << 5),
114
    CPUCFGR_OB64S = (1 << 6),
115
    CPUCFGR_OF32S = (1 << 7),
116
    CPUCFGR_OF64S = (1 << 8),
117
    CPUCFGR_OV64S = (1 << 9),
118
};
119

    
120
/* DMMU configure register */
121
enum {
122
    DMMUCFGR_NTW = (3 << 0),
123
    DMMUCFGR_NTS = (7 << 2),
124
    DMMUCFGR_NAE = (7 << 5),
125
    DMMUCFGR_CRI = (1 << 8),
126
    DMMUCFGR_PRI = (1 << 9),
127
    DMMUCFGR_TEIRI = (1 << 10),
128
    DMMUCFGR_HTR = (1 << 11),
129
};
130

    
131
/* IMMU configure register */
132
enum {
133
    IMMUCFGR_NTW = (3 << 0),
134
    IMMUCFGR_NTS = (7 << 2),
135
    IMMUCFGR_NAE = (7 << 5),
136
    IMMUCFGR_CRI = (1 << 8),
137
    IMMUCFGR_PRI = (1 << 9),
138
    IMMUCFGR_TEIRI = (1 << 10),
139
    IMMUCFGR_HTR = (1 << 11),
140
};
141

    
142
/* Float point control status register */
143
enum {
144
    FPCSR_FPEE = 1,
145
    FPCSR_RM = (3 << 1),
146
    FPCSR_OVF = (1 << 3),
147
    FPCSR_UNF = (1 << 4),
148
    FPCSR_SNF = (1 << 5),
149
    FPCSR_QNF = (1 << 6),
150
    FPCSR_ZF = (1 << 7),
151
    FPCSR_IXF = (1 << 8),
152
    FPCSR_IVF = (1 << 9),
153
    FPCSR_INF = (1 << 10),
154
    FPCSR_DZF = (1 << 11),
155
};
156

    
157
/* Exceptions indices */
158
enum {
159
    EXCP_RESET    = 0x1,
160
    EXCP_BUSERR   = 0x2,
161
    EXCP_DPF      = 0x3,
162
    EXCP_IPF      = 0x4,
163
    EXCP_TICK     = 0x5,
164
    EXCP_ALIGN    = 0x6,
165
    EXCP_ILLEGAL  = 0x7,
166
    EXCP_INT      = 0x8,
167
    EXCP_DTLBMISS = 0x9,
168
    EXCP_ITLBMISS = 0xa,
169
    EXCP_RANGE    = 0xb,
170
    EXCP_SYSCALL  = 0xc,
171
    EXCP_FPE      = 0xd,
172
    EXCP_TRAP     = 0xe,
173
    EXCP_NR,
174
};
175

    
176
/* Supervisor register */
177
enum {
178
    SR_SM = (1 << 0),
179
    SR_TEE = (1 << 1),
180
    SR_IEE = (1 << 2),
181
    SR_DCE = (1 << 3),
182
    SR_ICE = (1 << 4),
183
    SR_DME = (1 << 5),
184
    SR_IME = (1 << 6),
185
    SR_LEE = (1 << 7),
186
    SR_CE  = (1 << 8),
187
    SR_F   = (1 << 9),
188
    SR_CY  = (1 << 10),
189
    SR_OV  = (1 << 11),
190
    SR_OVE = (1 << 12),
191
    SR_DSX = (1 << 13),
192
    SR_EPH = (1 << 14),
193
    SR_FO  = (1 << 15),
194
    SR_SUMRA = (1 << 16),
195
    SR_SCE = (1 << 17),
196
};
197

    
198
/* OpenRISC Hardware Capabilities */
199
enum {
200
    OPENRISC_FEATURE_NSGF = (15 << 0),
201
    OPENRISC_FEATURE_CGF = (1 << 4),
202
    OPENRISC_FEATURE_OB32S = (1 << 5),
203
    OPENRISC_FEATURE_OB64S = (1 << 6),
204
    OPENRISC_FEATURE_OF32S = (1 << 7),
205
    OPENRISC_FEATURE_OF64S = (1 << 8),
206
    OPENRISC_FEATURE_OV64S = (1 << 9),
207
};
208

    
209
/* Tick Timer Mode Register */
210
enum {
211
    TTMR_TP = (0xfffffff),
212
    TTMR_IP = (1 << 28),
213
    TTMR_IE = (1 << 29),
214
    TTMR_M  = (3 << 30),
215
};
216

    
217
/* Timer Mode */
218
enum {
219
    TIMER_NONE = (0 << 30),
220
    TIMER_INTR = (1 << 30),
221
    TIMER_SHOT = (2 << 30),
222
    TIMER_CONT = (3 << 30),
223
};
224

    
225
/* TLB size */
226
enum {
227
    DTLB_WAYS = 1,
228
    DTLB_SIZE = 64,
229
    DTLB_MASK = (DTLB_SIZE-1),
230
    ITLB_WAYS = 1,
231
    ITLB_SIZE = 64,
232
    ITLB_MASK = (ITLB_SIZE-1),
233
};
234

    
235
/* TLB prot */
236
enum {
237
    URE = (1 << 6),
238
    UWE = (1 << 7),
239
    SRE = (1 << 8),
240
    SWE = (1 << 9),
241

    
242
    SXE = (1 << 6),
243
    UXE = (1 << 7),
244
};
245

    
246
/* check if tlb available */
247
enum {
248
    TLBRET_INVALID = -3,
249
    TLBRET_NOMATCH = -2,
250
    TLBRET_BADADDR = -1,
251
    TLBRET_MATCH = 0
252
};
253

    
254
typedef struct OpenRISCTLBEntry {
255
    uint32_t mr;
256
    uint32_t tr;
257
} OpenRISCTLBEntry;
258

    
259
#ifndef CONFIG_USER_ONLY
260
typedef struct CPUOpenRISCTLBContext {
261
    OpenRISCTLBEntry itlb[ITLB_WAYS][ITLB_SIZE];
262
    OpenRISCTLBEntry dtlb[DTLB_WAYS][DTLB_SIZE];
263

    
264
    int (*cpu_openrisc_map_address_code)(struct OpenRISCCPU *cpu,
265
                                         hwaddr *physical,
266
                                         int *prot,
267
                                         target_ulong address, int rw);
268
    int (*cpu_openrisc_map_address_data)(struct OpenRISCCPU *cpu,
269
                                         hwaddr *physical,
270
                                         int *prot,
271
                                         target_ulong address, int rw);
272
} CPUOpenRISCTLBContext;
273
#endif
274

    
275
typedef struct CPUOpenRISCState {
276
    target_ulong gpr[32];     /* General registers */
277
    target_ulong pc;          /* Program counter */
278
    target_ulong npc;         /* Next PC */
279
    target_ulong ppc;         /* Prev PC */
280
    target_ulong jmp_pc;      /* Jump PC */
281

    
282
    target_ulong machi;       /* Multiply register MACHI */
283
    target_ulong maclo;       /* Multiply register MACLO */
284

    
285
    target_ulong fpmaddhi;    /* Multiply and add float register FPMADDHI */
286
    target_ulong fpmaddlo;    /* Multiply and add float register FPMADDLO */
287

    
288
    target_ulong epcr;        /* Exception PC register */
289
    target_ulong eear;        /* Exception EA register */
290

    
291
    uint32_t sr;              /* Supervisor register */
292
    uint32_t vr;              /* Version register */
293
    uint32_t upr;             /* Unit presence register */
294
    uint32_t cpucfgr;         /* CPU configure register */
295
    uint32_t dmmucfgr;        /* DMMU configure register */
296
    uint32_t immucfgr;        /* IMMU configure register */
297
    uint32_t esr;             /* Exception supervisor register */
298
    uint32_t fpcsr;           /* Float register */
299
    float_status fp_status;
300

    
301
    uint32_t flags;           /* cpu_flags, we only use it for exception
302
                                 in solt so far.  */
303
    uint32_t btaken;          /* the SR_F bit */
304

    
305
    CPU_COMMON
306

    
307
#ifndef CONFIG_USER_ONLY
308
    CPUOpenRISCTLBContext * tlb;
309

    
310
    struct QEMUTimer *timer;
311
    uint32_t ttmr;          /* Timer tick mode register */
312
    uint32_t ttcr;          /* Timer tick count register */
313

    
314
    uint32_t picmr;         /* Interrupt mask register */
315
    uint32_t picsr;         /* Interrupt contrl register*/
316
#endif
317
    void *irq[32];          /* Interrupt irq input */
318
} CPUOpenRISCState;
319

    
320
/**
321
 * OpenRISCCPU:
322
 * @env: #CPUOpenRISCState
323
 *
324
 * A OpenRISC CPU.
325
 */
326
typedef struct OpenRISCCPU {
327
    /*< private >*/
328
    CPUState parent_obj;
329
    /*< public >*/
330

    
331
    CPUOpenRISCState env;
332

    
333
    uint32_t feature;       /* CPU Capabilities */
334
} OpenRISCCPU;
335

    
336
static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env)
337
{
338
    return container_of(env, OpenRISCCPU, env);
339
}
340

    
341
#define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e))
342

    
343
#define ENV_OFFSET offsetof(OpenRISCCPU, env)
344

    
345
OpenRISCCPU *cpu_openrisc_init(const char *cpu_model);
346

    
347
void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
348
int cpu_openrisc_exec(CPUOpenRISCState *s);
349
void openrisc_cpu_do_interrupt(CPUState *cpu);
350
void openrisc_cpu_dump_state(CPUState *cpu, FILE *f,
351
                             fprintf_function cpu_fprintf, int flags);
352
hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
353
int openrisc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
354
int openrisc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
355
void openrisc_translate_init(void);
356
int cpu_openrisc_handle_mmu_fault(CPUOpenRISCState *env,
357
                                  target_ulong address,
358
                                  int rw, int mmu_idx);
359
int cpu_openrisc_signal_handler(int host_signum, void *pinfo, void *puc);
360

    
361
#define cpu_list cpu_openrisc_list
362
#define cpu_exec cpu_openrisc_exec
363
#define cpu_gen_code cpu_openrisc_gen_code
364
#define cpu_handle_mmu_fault cpu_openrisc_handle_mmu_fault
365
#define cpu_signal_handler cpu_openrisc_signal_handler
366

    
367
#ifndef CONFIG_USER_ONLY
368
extern const struct VMStateDescription vmstate_openrisc_cpu;
369

    
370
/* hw/openrisc_pic.c */
371
void cpu_openrisc_pic_init(OpenRISCCPU *cpu);
372

    
373
/* hw/openrisc_timer.c */
374
void cpu_openrisc_clock_init(OpenRISCCPU *cpu);
375
void cpu_openrisc_count_update(OpenRISCCPU *cpu);
376
void cpu_openrisc_count_start(OpenRISCCPU *cpu);
377
void cpu_openrisc_count_stop(OpenRISCCPU *cpu);
378

    
379
void cpu_openrisc_mmu_init(OpenRISCCPU *cpu);
380
int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu,
381
                                hwaddr *physical,
382
                                int *prot, target_ulong address, int rw);
383
int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu,
384
                               hwaddr *physical,
385
                               int *prot, target_ulong address, int rw);
386
int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu,
387
                               hwaddr *physical,
388
                               int *prot, target_ulong address, int rw);
389
#endif
390

    
391
static inline CPUOpenRISCState *cpu_init(const char *cpu_model)
392
{
393
    OpenRISCCPU *cpu = cpu_openrisc_init(cpu_model);
394
    if (cpu) {
395
        return &cpu->env;
396
    }
397
    return NULL;
398
}
399

    
400
#include "exec/cpu-all.h"
401

    
402
static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
403
                                        target_ulong *pc,
404
                                        target_ulong *cs_base, int *flags)
405
{
406
    *pc = env->pc;
407
    *cs_base = 0;
408
    /* D_FLAG -- branch instruction exception */
409
    *flags = (env->flags & D_FLAG);
410
}
411

    
412
static inline int cpu_mmu_index(CPUOpenRISCState *env)
413
{
414
    if (!(env->sr & SR_IME)) {
415
        return MMU_NOMMU_IDX;
416
    }
417
    return (env->sr & SR_SM) == 0 ? MMU_USER_IDX : MMU_SUPERVISOR_IDX;
418
}
419

    
420
#define CPU_INTERRUPT_TIMER   CPU_INTERRUPT_TGT_INT_0
421
static inline bool cpu_has_work(CPUState *cpu)
422
{
423
    return cpu->interrupt_request & (CPU_INTERRUPT_HARD |
424
                                     CPU_INTERRUPT_TIMER);
425
}
426

    
427
#include "exec/exec-all.h"
428

    
429
static inline target_ulong cpu_get_pc(CPUOpenRISCState *env)
430
{
431
    return env->pc;
432
}
433

    
434
#endif /* CPU_OPENRISC_H */