4 * Copyright (c) 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.1 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 #include "qemu/osdep.h"
21 #include "qapi/error.h"
22 #include "qemu/qemu-print.h"
24 #include "exec/exec-all.h"
25 #include "fpu/softfloat-helpers.h"
28 static void openrisc_cpu_set_pc(CPUState
*cs
, vaddr value
)
30 OpenRISCCPU
*cpu
= OPENRISC_CPU(cs
);
36 static vaddr
openrisc_cpu_get_pc(CPUState
*cs
)
38 OpenRISCCPU
*cpu
= OPENRISC_CPU(cs
);
43 static void openrisc_cpu_synchronize_from_tb(CPUState
*cs
,
44 const TranslationBlock
*tb
)
46 OpenRISCCPU
*cpu
= OPENRISC_CPU(cs
);
48 tcg_debug_assert(!(cs
->tcg_cflags
& CF_PCREL
));
52 static void openrisc_restore_state_to_opc(CPUState
*cs
,
53 const TranslationBlock
*tb
,
56 OpenRISCCPU
*cpu
= OPENRISC_CPU(cs
);
58 cpu
->env
.pc
= data
[0];
59 cpu
->env
.dflag
= data
[1] & 1;
61 cpu
->env
.ppc
= cpu
->env
.pc
- 4;
65 static bool openrisc_cpu_has_work(CPUState
*cs
)
67 return cs
->interrupt_request
& (CPU_INTERRUPT_HARD
|
71 static int openrisc_cpu_mmu_index(CPUState
*cs
, bool ifetch
)
73 CPUOpenRISCState
*env
= cpu_env(cs
);
75 if (env
->sr
& (ifetch
? SR_IME
: SR_DME
)) {
76 /* The mmu is enabled; test supervisor state. */
77 return env
->sr
& SR_SM
? MMU_SUPERVISOR_IDX
: MMU_USER_IDX
;
80 return MMU_NOMMU_IDX
; /* mmu is disabled */
83 static void openrisc_disas_set_info(CPUState
*cpu
, disassemble_info
*info
)
85 info
->print_insn
= print_insn_or1k
;
88 static void openrisc_cpu_reset_hold(Object
*obj
)
90 CPUState
*s
= CPU(obj
);
91 OpenRISCCPU
*cpu
= OPENRISC_CPU(s
);
92 OpenRISCCPUClass
*occ
= OPENRISC_CPU_GET_CLASS(cpu
);
94 if (occ
->parent_phases
.hold
) {
95 occ
->parent_phases
.hold(obj
);
98 memset(&cpu
->env
, 0, offsetof(CPUOpenRISCState
, end_reset_fields
));
101 cpu
->env
.sr
= SR_FO
| SR_SM
;
102 cpu
->env
.lock_addr
= -1;
103 s
->exception_index
= -1;
104 cpu_set_fpcsr(&cpu
->env
, 0);
106 set_float_detect_tininess(float_tininess_before_rounding
,
107 &cpu
->env
.fp_status
);
109 #ifndef CONFIG_USER_ONLY
110 cpu
->env
.picmr
= 0x00000000;
111 cpu
->env
.picsr
= 0x00000000;
113 cpu
->env
.ttmr
= 0x00000000;
117 #ifndef CONFIG_USER_ONLY
118 static void openrisc_cpu_set_irq(void *opaque
, int irq
, int level
)
120 OpenRISCCPU
*cpu
= (OpenRISCCPU
*)opaque
;
121 CPUState
*cs
= CPU(cpu
);
124 if (irq
> 31 || irq
< 0) {
131 cpu
->env
.picsr
|= irq_bit
;
133 cpu
->env
.picsr
&= ~irq_bit
;
136 if (cpu
->env
.picsr
& cpu
->env
.picmr
) {
137 cpu_interrupt(cs
, CPU_INTERRUPT_HARD
);
139 cpu_reset_interrupt(cs
, CPU_INTERRUPT_HARD
);
144 static void openrisc_cpu_realizefn(DeviceState
*dev
, Error
**errp
)
146 CPUState
*cs
= CPU(dev
);
147 OpenRISCCPUClass
*occ
= OPENRISC_CPU_GET_CLASS(dev
);
148 Error
*local_err
= NULL
;
150 cpu_exec_realizefn(cs
, &local_err
);
151 if (local_err
!= NULL
) {
152 error_propagate(errp
, local_err
);
159 occ
->parent_realize(dev
, errp
);
162 static void openrisc_cpu_initfn(Object
*obj
)
164 #ifndef CONFIG_USER_ONLY
165 qdev_init_gpio_in_named(DEVICE(obj
), openrisc_cpu_set_irq
, "IRQ", NR_IRQS
);
171 static ObjectClass
*openrisc_cpu_class_by_name(const char *cpu_model
)
176 typename
= g_strdup_printf(OPENRISC_CPU_TYPE_NAME("%s"), cpu_model
);
177 oc
= object_class_by_name(typename
);
183 static void or1200_initfn(Object
*obj
)
185 OpenRISCCPU
*cpu
= OPENRISC_CPU(obj
);
187 cpu
->env
.vr
= 0x13000008;
188 cpu
->env
.upr
= UPR_UP
| UPR_DMP
| UPR_IMP
| UPR_PICP
| UPR_TTP
| UPR_PMP
;
189 cpu
->env
.cpucfgr
= CPUCFGR_NSGF
| CPUCFGR_OB32S
| CPUCFGR_OF32S
|
192 /* 1Way, TLB_SIZE entries. */
193 cpu
->env
.dmmucfgr
= (DMMUCFGR_NTW
& (0 << 2))
194 | (DMMUCFGR_NTS
& (ctz32(TLB_SIZE
) << 2));
195 cpu
->env
.immucfgr
= (IMMUCFGR_NTW
& (0 << 2))
196 | (IMMUCFGR_NTS
& (ctz32(TLB_SIZE
) << 2));
199 static void openrisc_any_initfn(Object
*obj
)
201 OpenRISCCPU
*cpu
= OPENRISC_CPU(obj
);
203 cpu
->env
.vr
= 0x13000040; /* Obsolete VER + UVRP for new SPRs */
204 cpu
->env
.vr2
= 0; /* No version specific id */
205 cpu
->env
.avr
= 0x01030000; /* Architecture v1.3 */
207 cpu
->env
.upr
= UPR_UP
| UPR_DMP
| UPR_IMP
| UPR_PICP
| UPR_TTP
| UPR_PMP
;
208 cpu
->env
.cpucfgr
= CPUCFGR_NSGF
| CPUCFGR_OB32S
| CPUCFGR_OF32S
|
209 CPUCFGR_AVRP
| CPUCFGR_EVBARP
| CPUCFGR_OF64A32S
;
211 /* 1Way, TLB_SIZE entries. */
212 cpu
->env
.dmmucfgr
= (DMMUCFGR_NTW
& (0 << 2))
213 | (DMMUCFGR_NTS
& (ctz32(TLB_SIZE
) << 2));
214 cpu
->env
.immucfgr
= (IMMUCFGR_NTW
& (0 << 2))
215 | (IMMUCFGR_NTS
& (ctz32(TLB_SIZE
) << 2));
218 #ifndef CONFIG_USER_ONLY
219 #include "hw/core/sysemu-cpu-ops.h"
221 static const struct SysemuCPUOps openrisc_sysemu_ops
= {
222 .get_phys_page_debug
= openrisc_cpu_get_phys_page_debug
,
226 #include "hw/core/tcg-cpu-ops.h"
228 static const TCGCPUOps openrisc_tcg_ops
= {
229 .initialize
= openrisc_translate_init
,
230 .synchronize_from_tb
= openrisc_cpu_synchronize_from_tb
,
231 .restore_state_to_opc
= openrisc_restore_state_to_opc
,
233 #ifndef CONFIG_USER_ONLY
234 .tlb_fill
= openrisc_cpu_tlb_fill
,
235 .cpu_exec_interrupt
= openrisc_cpu_exec_interrupt
,
236 .do_interrupt
= openrisc_cpu_do_interrupt
,
237 #endif /* !CONFIG_USER_ONLY */
240 static void openrisc_cpu_class_init(ObjectClass
*oc
, void *data
)
242 OpenRISCCPUClass
*occ
= OPENRISC_CPU_CLASS(oc
);
243 CPUClass
*cc
= CPU_CLASS(occ
);
244 DeviceClass
*dc
= DEVICE_CLASS(oc
);
245 ResettableClass
*rc
= RESETTABLE_CLASS(oc
);
247 device_class_set_parent_realize(dc
, openrisc_cpu_realizefn
,
248 &occ
->parent_realize
);
249 resettable_class_set_parent_phases(rc
, NULL
, openrisc_cpu_reset_hold
, NULL
,
250 &occ
->parent_phases
);
252 cc
->class_by_name
= openrisc_cpu_class_by_name
;
253 cc
->has_work
= openrisc_cpu_has_work
;
254 cc
->mmu_index
= openrisc_cpu_mmu_index
;
255 cc
->dump_state
= openrisc_cpu_dump_state
;
256 cc
->set_pc
= openrisc_cpu_set_pc
;
257 cc
->get_pc
= openrisc_cpu_get_pc
;
258 cc
->gdb_read_register
= openrisc_cpu_gdb_read_register
;
259 cc
->gdb_write_register
= openrisc_cpu_gdb_write_register
;
260 #ifndef CONFIG_USER_ONLY
261 dc
->vmsd
= &vmstate_openrisc_cpu
;
262 cc
->sysemu_ops
= &openrisc_sysemu_ops
;
264 cc
->gdb_num_core_regs
= 32 + 3;
265 cc
->disas_set_info
= openrisc_disas_set_info
;
266 cc
->tcg_ops
= &openrisc_tcg_ops
;
269 #define DEFINE_OPENRISC_CPU_TYPE(cpu_model, initfn) \
271 .parent = TYPE_OPENRISC_CPU, \
272 .instance_init = initfn, \
273 .name = OPENRISC_CPU_TYPE_NAME(cpu_model), \
276 static const TypeInfo openrisc_cpus_type_infos
[] = {
277 { /* base class should be registered first */
278 .name
= TYPE_OPENRISC_CPU
,
280 .instance_size
= sizeof(OpenRISCCPU
),
281 .instance_align
= __alignof(OpenRISCCPU
),
282 .instance_init
= openrisc_cpu_initfn
,
284 .class_size
= sizeof(OpenRISCCPUClass
),
285 .class_init
= openrisc_cpu_class_init
,
287 DEFINE_OPENRISC_CPU_TYPE("or1200", or1200_initfn
),
288 DEFINE_OPENRISC_CPU_TYPE("any", openrisc_any_initfn
),
291 DEFINE_TYPES(openrisc_cpus_type_infos
)