2
* OpenRISC virtual CPU header.
4
* Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
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.
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.
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/>.
20
#ifndef OPENRISC_CPU_H
21
#define OPENRISC_CPU_H
23
#define TARGET_LONG_BITS 32
25
#define CPUArchState struct CPUOpenRISCState
27
/* cpu_openrisc_map_address_* in CPUOpenRISCTLBContext need this decl. */
30
#include "qemu-common.h"
31
#include "exec/cpu-defs.h"
32
#include "fpu/softfloat.h"
35
#define TYPE_OPENRISC_CPU "or32-cpu"
37
#define OPENRISC_CPU_CLASS(klass) \
38
OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU)
39
#define OPENRISC_CPU(obj) \
40
OBJECT_CHECK(OpenRISCCPU, (obj), TYPE_OPENRISC_CPU)
41
#define OPENRISC_CPU_GET_CLASS(obj) \
42
OBJECT_GET_CLASS(OpenRISCCPUClass, (obj), TYPE_OPENRISC_CPU)
46
* @parent_realize: The parent class' realize handler.
47
* @parent_reset: The parent class' reset handler.
49
* A OpenRISC CPU model.
51
typedef struct OpenRISCCPUClass {
53
CPUClass parent_class;
56
DeviceRealize parent_realize;
57
void (*parent_reset)(CPUState *cpu);
60
#define NB_MMU_MODES 3
64
MMU_SUPERVISOR_IDX = 1,
68
#define TARGET_PAGE_BITS 13
70
#define TARGET_PHYS_ADDR_SPACE_BITS 32
71
#define TARGET_VIRT_ADDR_SPACE_BITS 32
73
#define SET_FP_CAUSE(reg, v) do {\
74
(reg) = ((reg) & ~(0x3f << 12)) | \
77
#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f)
78
#define UPDATE_FP_FLAGS(reg, v) do {\
79
(reg) |= ((v & 0x1f) << 2);\
82
/* Version Register */
83
#define SPR_VR 0xFFFF003F
85
/* Internal flags, delay slot flag */
91
/* Unit presece register */
104
UPR_CUP = (255 << 24),
107
/* CPU configure register */
109
CPUCFGR_NSGF = (15 << 0),
110
CPUCFGR_CGF = (1 << 4),
111
CPUCFGR_OB32S = (1 << 5),
112
CPUCFGR_OB64S = (1 << 6),
113
CPUCFGR_OF32S = (1 << 7),
114
CPUCFGR_OF64S = (1 << 8),
115
CPUCFGR_OV64S = (1 << 9),
118
/* DMMU configure register */
120
DMMUCFGR_NTW = (3 << 0),
121
DMMUCFGR_NTS = (7 << 2),
122
DMMUCFGR_NAE = (7 << 5),
123
DMMUCFGR_CRI = (1 << 8),
124
DMMUCFGR_PRI = (1 << 9),
125
DMMUCFGR_TEIRI = (1 << 10),
126
DMMUCFGR_HTR = (1 << 11),
129
/* IMMU configure register */
131
IMMUCFGR_NTW = (3 << 0),
132
IMMUCFGR_NTS = (7 << 2),
133
IMMUCFGR_NAE = (7 << 5),
134
IMMUCFGR_CRI = (1 << 8),
135
IMMUCFGR_PRI = (1 << 9),
136
IMMUCFGR_TEIRI = (1 << 10),
137
IMMUCFGR_HTR = (1 << 11),
140
/* Float point control status register */
144
FPCSR_OVF = (1 << 3),
145
FPCSR_UNF = (1 << 4),
146
FPCSR_SNF = (1 << 5),
147
FPCSR_QNF = (1 << 6),
149
FPCSR_IXF = (1 << 8),
150
FPCSR_IVF = (1 << 9),
151
FPCSR_INF = (1 << 10),
152
FPCSR_DZF = (1 << 11),
155
/* Exceptions indices */
174
/* Supervisor register */
192
SR_SUMRA = (1 << 16),
196
/* OpenRISC Hardware Capabilities */
198
OPENRISC_FEATURE_NSGF = (15 << 0),
199
OPENRISC_FEATURE_CGF = (1 << 4),
200
OPENRISC_FEATURE_OB32S = (1 << 5),
201
OPENRISC_FEATURE_OB64S = (1 << 6),
202
OPENRISC_FEATURE_OF32S = (1 << 7),
203
OPENRISC_FEATURE_OF64S = (1 << 8),
204
OPENRISC_FEATURE_OV64S = (1 << 9),
207
/* Tick Timer Mode Register */
209
TTMR_TP = (0xfffffff),
217
TIMER_NONE = (0 << 30),
218
TIMER_INTR = (1 << 30),
219
TIMER_SHOT = (2 << 30),
220
TIMER_CONT = (3 << 30),
227
DTLB_MASK = (DTLB_SIZE-1),
230
ITLB_MASK = (ITLB_SIZE-1),
244
/* check if tlb available */
252
typedef struct OpenRISCTLBEntry {
257
#ifndef CONFIG_USER_ONLY
258
typedef struct CPUOpenRISCTLBContext {
259
OpenRISCTLBEntry itlb[ITLB_WAYS][ITLB_SIZE];
260
OpenRISCTLBEntry dtlb[DTLB_WAYS][DTLB_SIZE];
262
int (*cpu_openrisc_map_address_code)(struct OpenRISCCPU *cpu,
265
target_ulong address, int rw);
266
int (*cpu_openrisc_map_address_data)(struct OpenRISCCPU *cpu,
269
target_ulong address, int rw);
270
} CPUOpenRISCTLBContext;
273
typedef struct CPUOpenRISCState {
274
target_ulong gpr[32]; /* General registers */
275
target_ulong pc; /* Program counter */
276
target_ulong npc; /* Next PC */
277
target_ulong ppc; /* Prev PC */
278
target_ulong jmp_pc; /* Jump PC */
280
target_ulong machi; /* Multiply register MACHI */
281
target_ulong maclo; /* Multiply register MACLO */
283
target_ulong fpmaddhi; /* Multiply and add float register FPMADDHI */
284
target_ulong fpmaddlo; /* Multiply and add float register FPMADDLO */
286
target_ulong epcr; /* Exception PC register */
287
target_ulong eear; /* Exception EA register */
289
uint32_t sr; /* Supervisor register */
290
uint32_t vr; /* Version register */
291
uint32_t upr; /* Unit presence register */
292
uint32_t cpucfgr; /* CPU configure register */
293
uint32_t dmmucfgr; /* DMMU configure register */
294
uint32_t immucfgr; /* IMMU configure register */
295
uint32_t esr; /* Exception supervisor register */
296
uint32_t fpcsr; /* Float register */
297
float_status fp_status;
299
uint32_t flags; /* cpu_flags, we only use it for exception
301
uint32_t btaken; /* the SR_F bit */
305
/* Fields from here on are preserved across CPU reset. */
306
#ifndef CONFIG_USER_ONLY
307
CPUOpenRISCTLBContext * tlb;
310
uint32_t ttmr; /* Timer tick mode register */
311
uint32_t ttcr; /* Timer tick count register */
313
uint32_t picmr; /* Interrupt mask register */
314
uint32_t picsr; /* Interrupt contrl register*/
316
void *irq[32]; /* Interrupt irq input */
321
* @env: #CPUOpenRISCState
325
typedef struct OpenRISCCPU {
330
CPUOpenRISCState env;
332
uint32_t feature; /* CPU Capabilities */
335
static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env)
337
return container_of(env, OpenRISCCPU, env);
340
#define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e))
342
#define ENV_OFFSET offsetof(OpenRISCCPU, env)
344
OpenRISCCPU *cpu_openrisc_init(const char *cpu_model);
346
void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
347
void openrisc_cpu_do_interrupt(CPUState *cpu);
348
bool openrisc_cpu_exec_interrupt(CPUState *cpu, int int_req);
349
void openrisc_cpu_dump_state(CPUState *cpu, FILE *f,
350
fprintf_function cpu_fprintf, int flags);
351
hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
352
int openrisc_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
353
int openrisc_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
354
void openrisc_translate_init(void);
355
int openrisc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address,
356
int rw, int mmu_idx);
357
int cpu_openrisc_signal_handler(int host_signum, void *pinfo, void *puc);
359
#define cpu_list cpu_openrisc_list
360
#define cpu_signal_handler cpu_openrisc_signal_handler
362
#ifndef CONFIG_USER_ONLY
363
extern const struct VMStateDescription vmstate_openrisc_cpu;
365
/* hw/openrisc_pic.c */
366
void cpu_openrisc_pic_init(OpenRISCCPU *cpu);
368
/* hw/openrisc_timer.c */
369
void cpu_openrisc_clock_init(OpenRISCCPU *cpu);
370
void cpu_openrisc_count_update(OpenRISCCPU *cpu);
371
void cpu_openrisc_timer_update(OpenRISCCPU *cpu);
372
void cpu_openrisc_count_start(OpenRISCCPU *cpu);
373
void cpu_openrisc_count_stop(OpenRISCCPU *cpu);
375
void cpu_openrisc_mmu_init(OpenRISCCPU *cpu);
376
int cpu_openrisc_get_phys_nommu(OpenRISCCPU *cpu,
378
int *prot, target_ulong address, int rw);
379
int cpu_openrisc_get_phys_code(OpenRISCCPU *cpu,
381
int *prot, target_ulong address, int rw);
382
int cpu_openrisc_get_phys_data(OpenRISCCPU *cpu,
384
int *prot, target_ulong address, int rw);
387
#define cpu_init(cpu_model) CPU(cpu_openrisc_init(cpu_model))
389
#include "exec/cpu-all.h"
391
static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
393
target_ulong *cs_base, uint32_t *flags)
397
/* D_FLAG -- branch instruction exception */
398
*flags = (env->flags & D_FLAG);
401
static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch)
403
if (!(env->sr & SR_IME)) {
404
return MMU_NOMMU_IDX;
406
return (env->sr & SR_SM) == 0 ? MMU_USER_IDX : MMU_SUPERVISOR_IDX;
409
#define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_INT_0
411
#endif /* OPENRISC_CPU_H */