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 "or1k-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
61
#define TARGET_INSN_START_EXTRA_WORDS 1
65
MMU_SUPERVISOR_IDX = 1,
69
#define TARGET_PAGE_BITS 13
71
#define TARGET_PHYS_ADDR_SPACE_BITS 32
72
#define TARGET_VIRT_ADDR_SPACE_BITS 32
74
#define SET_FP_CAUSE(reg, v) do {\
75
(reg) = ((reg) & ~(0x3f << 12)) | \
78
#define GET_FP_ENABLE(reg) (((reg) >> 7) & 0x1f)
79
#define UPDATE_FP_FLAGS(reg, v) do {\
80
(reg) |= ((v & 0x1f) << 2);\
83
/* Version Register */
84
#define SPR_VR 0xFFFF003F
89
/* Unit presece register */
102
UPR_CUP = (255 << 24),
105
/* CPU configure register */
107
CPUCFGR_NSGF = (15 << 0),
108
CPUCFGR_CGF = (1 << 4),
109
CPUCFGR_OB32S = (1 << 5),
110
CPUCFGR_OB64S = (1 << 6),
111
CPUCFGR_OF32S = (1 << 7),
112
CPUCFGR_OF64S = (1 << 8),
113
CPUCFGR_OV64S = (1 << 9),
116
/* DMMU configure register */
118
DMMUCFGR_NTW = (3 << 0),
119
DMMUCFGR_NTS = (7 << 2),
120
DMMUCFGR_NAE = (7 << 5),
121
DMMUCFGR_CRI = (1 << 8),
122
DMMUCFGR_PRI = (1 << 9),
123
DMMUCFGR_TEIRI = (1 << 10),
124
DMMUCFGR_HTR = (1 << 11),
127
/* IMMU configure register */
129
IMMUCFGR_NTW = (3 << 0),
130
IMMUCFGR_NTS = (7 << 2),
131
IMMUCFGR_NAE = (7 << 5),
132
IMMUCFGR_CRI = (1 << 8),
133
IMMUCFGR_PRI = (1 << 9),
134
IMMUCFGR_TEIRI = (1 << 10),
135
IMMUCFGR_HTR = (1 << 11),
138
/* Float point control status register */
142
FPCSR_OVF = (1 << 3),
143
FPCSR_UNF = (1 << 4),
144
FPCSR_SNF = (1 << 5),
145
FPCSR_QNF = (1 << 6),
147
FPCSR_IXF = (1 << 8),
148
FPCSR_IVF = (1 << 9),
149
FPCSR_INF = (1 << 10),
150
FPCSR_DZF = (1 << 11),
153
/* Exceptions indices */
172
/* Supervisor register */
190
SR_SUMRA = (1 << 16),
194
/* OpenRISC Hardware Capabilities */
196
OPENRISC_FEATURE_NSGF = (15 << 0),
197
OPENRISC_FEATURE_CGF = (1 << 4),
198
OPENRISC_FEATURE_OB32S = (1 << 5),
199
OPENRISC_FEATURE_OB64S = (1 << 6),
200
OPENRISC_FEATURE_OF32S = (1 << 7),
201
OPENRISC_FEATURE_OF64S = (1 << 8),
202
OPENRISC_FEATURE_OV64S = (1 << 9),
205
/* Tick Timer Mode Register */
207
TTMR_TP = (0xfffffff),
215
TIMER_NONE = (0 << 30),
216
TIMER_INTR = (1 << 30),
217
TIMER_SHOT = (2 << 30),
218
TIMER_CONT = (3 << 30),
225
DTLB_MASK = (DTLB_SIZE-1),
228
ITLB_MASK = (ITLB_SIZE-1),
242
/* check if tlb available */
250
typedef struct OpenRISCTLBEntry {
255
#ifndef CONFIG_USER_ONLY
256
typedef struct CPUOpenRISCTLBContext {
257
OpenRISCTLBEntry itlb[ITLB_WAYS][ITLB_SIZE];
258
OpenRISCTLBEntry dtlb[DTLB_WAYS][DTLB_SIZE];
260
int (*cpu_openrisc_map_address_code)(struct OpenRISCCPU *cpu,
263
target_ulong address, int rw);
264
int (*cpu_openrisc_map_address_data)(struct OpenRISCCPU *cpu,
267
target_ulong address, int rw);
268
} CPUOpenRISCTLBContext;
271
typedef struct CPUOpenRISCState {
272
target_ulong gpr[32]; /* General registers */
273
target_ulong pc; /* Program counter */
274
target_ulong ppc; /* Prev PC */
275
target_ulong jmp_pc; /* Jump PC */
277
uint64_t mac; /* Multiply registers MACHI:MACLO */
279
target_ulong epcr; /* Exception PC register */
280
target_ulong eear; /* Exception EA register */
282
target_ulong sr_f; /* the SR_F bit, values 0, 1. */
283
target_ulong sr_cy; /* the SR_CY bit, values 0, 1. */
284
target_long sr_ov; /* the SR_OV bit (in the sign bit only) */
285
uint32_t sr; /* Supervisor register, without SR_{F,CY,OV} */
286
uint32_t vr; /* Version register */
287
uint32_t upr; /* Unit presence register */
288
uint32_t cpucfgr; /* CPU configure register */
289
uint32_t dmmucfgr; /* DMMU configure register */
290
uint32_t immucfgr; /* IMMU configure register */
291
uint32_t esr; /* Exception supervisor register */
292
uint32_t fpcsr; /* Float register */
293
float_status fp_status;
295
target_ulong lock_addr;
296
target_ulong lock_value;
298
uint32_t dflag; /* In delay slot (boolean) */
300
/* Fields up to this point are cleared by a CPU reset */
301
struct {} end_reset_fields;
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
#define TB_FLAGS_DFLAG 1
392
#define TB_FLAGS_R0_0 2
393
#define TB_FLAGS_OVE SR_OVE
395
static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
397
target_ulong *cs_base, uint32_t *flags)
402
| (env->gpr[0] == 0 ? TB_FLAGS_R0_0 : 0)
403
| (env->sr & SR_OVE));
406
static inline int cpu_mmu_index(CPUOpenRISCState *env, bool ifetch)
408
if (!(env->sr & SR_IME)) {
409
return MMU_NOMMU_IDX;
411
return (env->sr & SR_SM) == 0 ? MMU_USER_IDX : MMU_SUPERVISOR_IDX;
414
static inline uint32_t cpu_get_sr(const CPUOpenRISCState *env)
419
+ (env->sr_ov < 0) * SR_OV);
422
static inline void cpu_set_sr(CPUOpenRISCState *env, uint32_t val)
424
env->sr_f = (val & SR_F) != 0;
425
env->sr_cy = (val & SR_CY) != 0;
426
env->sr_ov = (val & SR_OV ? -1 : 0);
427
env->sr = (val & ~(SR_F | SR_CY | SR_OV)) | SR_FO;
430
#define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_INT_0
432
#endif /* OPENRISC_CPU_H */