root / target-cris / cpu.c @ 14a10fc3
History | View | Annotate | Download (7.3 kB)
1 | e739a48e | Andreas Färber | /*
|
---|---|---|---|
2 | e739a48e | Andreas Färber | * QEMU CRIS CPU
|
3 | e739a48e | Andreas Färber | *
|
4 | 1c3b52fb | Andreas Färber | * Copyright (c) 2008 AXIS Communications AB
|
5 | 1c3b52fb | Andreas Färber | * Written by Edgar E. Iglesias.
|
6 | 1c3b52fb | Andreas Färber | *
|
7 | e739a48e | Andreas Färber | * Copyright (c) 2012 SUSE LINUX Products GmbH
|
8 | e739a48e | Andreas Färber | *
|
9 | e739a48e | Andreas Färber | * This library is free software; you can redistribute it and/or
|
10 | e739a48e | Andreas Färber | * modify it under the terms of the GNU Lesser General Public
|
11 | e739a48e | Andreas Färber | * License as published by the Free Software Foundation; either
|
12 | e739a48e | Andreas Färber | * version 2.1 of the License, or (at your option) any later version.
|
13 | e739a48e | Andreas Färber | *
|
14 | e739a48e | Andreas Färber | * This library is distributed in the hope that it will be useful,
|
15 | e739a48e | Andreas Färber | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16 | e739a48e | Andreas Färber | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
17 | e739a48e | Andreas Färber | * Lesser General Public License for more details.
|
18 | e739a48e | Andreas Färber | *
|
19 | e739a48e | Andreas Färber | * You should have received a copy of the GNU Lesser General Public
|
20 | e739a48e | Andreas Färber | * License along with this library; if not, see
|
21 | e739a48e | Andreas Färber | * <http://www.gnu.org/licenses/lgpl-2.1.html>
|
22 | e739a48e | Andreas Färber | */
|
23 | e739a48e | Andreas Färber | |
24 | e739a48e | Andreas Färber | #include "cpu.h" |
25 | e739a48e | Andreas Färber | #include "qemu-common.h" |
26 | 1c3b52fb | Andreas Färber | #include "mmu.h" |
27 | e739a48e | Andreas Färber | |
28 | e739a48e | Andreas Färber | |
29 | f45748f1 | Andreas Färber | static void cris_cpu_set_pc(CPUState *cs, vaddr value) |
30 | f45748f1 | Andreas Färber | { |
31 | f45748f1 | Andreas Färber | CRISCPU *cpu = CRIS_CPU(cs); |
32 | f45748f1 | Andreas Färber | |
33 | f45748f1 | Andreas Färber | cpu->env.pc = value; |
34 | f45748f1 | Andreas Färber | } |
35 | f45748f1 | Andreas Färber | |
36 | e739a48e | Andreas Färber | /* CPUClass::reset() */
|
37 | e739a48e | Andreas Färber | static void cris_cpu_reset(CPUState *s) |
38 | e739a48e | Andreas Färber | { |
39 | e739a48e | Andreas Färber | CRISCPU *cpu = CRIS_CPU(s); |
40 | e739a48e | Andreas Färber | CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(cpu); |
41 | e739a48e | Andreas Färber | CPUCRISState *env = &cpu->env; |
42 | 1c3b52fb | Andreas Färber | uint32_t vr; |
43 | 1c3b52fb | Andreas Färber | |
44 | e739a48e | Andreas Färber | ccc->parent_reset(s); |
45 | e739a48e | Andreas Färber | |
46 | 1c3b52fb | Andreas Färber | vr = env->pregs[PR_VR]; |
47 | 1c3b52fb | Andreas Färber | memset(env, 0, offsetof(CPUCRISState, breakpoints));
|
48 | 1c3b52fb | Andreas Färber | env->pregs[PR_VR] = vr; |
49 | 1c3b52fb | Andreas Färber | tlb_flush(env, 1);
|
50 | 1c3b52fb | Andreas Färber | |
51 | 1c3b52fb | Andreas Färber | #if defined(CONFIG_USER_ONLY)
|
52 | 1c3b52fb | Andreas Färber | /* start in user mode with interrupts enabled. */
|
53 | 1c3b52fb | Andreas Färber | env->pregs[PR_CCS] |= U_FLAG | I_FLAG | P_FLAG; |
54 | 1c3b52fb | Andreas Färber | #else
|
55 | 1c3b52fb | Andreas Färber | cris_mmu_init(env); |
56 | 1c3b52fb | Andreas Färber | env->pregs[PR_CCS] = 0;
|
57 | 1c3b52fb | Andreas Färber | #endif
|
58 | e739a48e | Andreas Färber | } |
59 | e739a48e | Andreas Färber | |
60 | 6ae064fc | Andreas Färber | static ObjectClass *cris_cpu_class_by_name(const char *cpu_model) |
61 | 6ae064fc | Andreas Färber | { |
62 | 6ae064fc | Andreas Färber | ObjectClass *oc; |
63 | 6ae064fc | Andreas Färber | char *typename;
|
64 | 6ae064fc | Andreas Färber | |
65 | 6ae064fc | Andreas Färber | if (cpu_model == NULL) { |
66 | 6ae064fc | Andreas Färber | return NULL; |
67 | 6ae064fc | Andreas Färber | } |
68 | 6ae064fc | Andreas Färber | |
69 | 6ae064fc | Andreas Färber | typename = g_strdup_printf("%s-" TYPE_CRIS_CPU, cpu_model);
|
70 | 6ae064fc | Andreas Färber | oc = object_class_by_name(typename); |
71 | 6ae064fc | Andreas Färber | g_free(typename); |
72 | 6ae064fc | Andreas Färber | if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_CRIS_CPU) || |
73 | 6ae064fc | Andreas Färber | object_class_is_abstract(oc))) { |
74 | 6ae064fc | Andreas Färber | oc = NULL;
|
75 | 6ae064fc | Andreas Färber | } |
76 | 6ae064fc | Andreas Färber | return oc;
|
77 | 6ae064fc | Andreas Färber | } |
78 | 6ae064fc | Andreas Färber | |
79 | 6ae064fc | Andreas Färber | CRISCPU *cpu_cris_init(const char *cpu_model) |
80 | 6ae064fc | Andreas Färber | { |
81 | 6ae064fc | Andreas Färber | CRISCPU *cpu; |
82 | 6ae064fc | Andreas Färber | ObjectClass *oc; |
83 | 6ae064fc | Andreas Färber | |
84 | 6ae064fc | Andreas Färber | oc = cris_cpu_class_by_name(cpu_model); |
85 | 6ae064fc | Andreas Färber | if (oc == NULL) { |
86 | 6ae064fc | Andreas Färber | return NULL; |
87 | 6ae064fc | Andreas Färber | } |
88 | 6ae064fc | Andreas Färber | cpu = CRIS_CPU(object_new(object_class_get_name(oc))); |
89 | 6ae064fc | Andreas Färber | |
90 | 6ae064fc | Andreas Färber | object_property_set_bool(OBJECT(cpu), true, "realized", NULL); |
91 | 6ae064fc | Andreas Färber | |
92 | 6ae064fc | Andreas Färber | return cpu;
|
93 | 6ae064fc | Andreas Färber | } |
94 | 6ae064fc | Andreas Färber | |
95 | 6ae064fc | Andreas Färber | /* Sort alphabetically by VR. */
|
96 | 6ae064fc | Andreas Färber | static gint cris_cpu_list_compare(gconstpointer a, gconstpointer b)
|
97 | 6ae064fc | Andreas Färber | { |
98 | 6ae064fc | Andreas Färber | CRISCPUClass *ccc_a = CRIS_CPU_CLASS(a); |
99 | 6ae064fc | Andreas Färber | CRISCPUClass *ccc_b = CRIS_CPU_CLASS(b); |
100 | 6ae064fc | Andreas Färber | |
101 | 6ae064fc | Andreas Färber | /* */
|
102 | 6ae064fc | Andreas Färber | if (ccc_a->vr > ccc_b->vr) {
|
103 | 6ae064fc | Andreas Färber | return 1; |
104 | 6ae064fc | Andreas Färber | } else if (ccc_a->vr < ccc_b->vr) { |
105 | 6ae064fc | Andreas Färber | return -1; |
106 | 6ae064fc | Andreas Färber | } else {
|
107 | 6ae064fc | Andreas Färber | return 0; |
108 | 6ae064fc | Andreas Färber | } |
109 | 6ae064fc | Andreas Färber | } |
110 | 6ae064fc | Andreas Färber | |
111 | 6ae064fc | Andreas Färber | static void cris_cpu_list_entry(gpointer data, gpointer user_data) |
112 | 6ae064fc | Andreas Färber | { |
113 | 6ae064fc | Andreas Färber | ObjectClass *oc = data; |
114 | 6ae064fc | Andreas Färber | CPUListState *s = user_data; |
115 | 6ae064fc | Andreas Färber | const char *typename = object_class_get_name(oc); |
116 | 6ae064fc | Andreas Färber | char *name;
|
117 | 6ae064fc | Andreas Färber | |
118 | 6ae064fc | Andreas Färber | name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_CRIS_CPU));
|
119 | 6ae064fc | Andreas Färber | (*s->cpu_fprintf)(s->file, " %s\n", name);
|
120 | 6ae064fc | Andreas Färber | g_free(name); |
121 | 6ae064fc | Andreas Färber | } |
122 | 6ae064fc | Andreas Färber | |
123 | 6ae064fc | Andreas Färber | void cris_cpu_list(FILE *f, fprintf_function cpu_fprintf)
|
124 | 6ae064fc | Andreas Färber | { |
125 | 6ae064fc | Andreas Färber | CPUListState s = { |
126 | 6ae064fc | Andreas Färber | .file = f, |
127 | 6ae064fc | Andreas Färber | .cpu_fprintf = cpu_fprintf, |
128 | 6ae064fc | Andreas Färber | }; |
129 | 6ae064fc | Andreas Färber | GSList *list; |
130 | 6ae064fc | Andreas Färber | |
131 | 6ae064fc | Andreas Färber | list = object_class_get_list(TYPE_CRIS_CPU, false);
|
132 | 6ae064fc | Andreas Färber | list = g_slist_sort(list, cris_cpu_list_compare); |
133 | 6ae064fc | Andreas Färber | (*cpu_fprintf)(f, "Available CPUs:\n");
|
134 | 6ae064fc | Andreas Färber | g_slist_foreach(list, cris_cpu_list_entry, &s); |
135 | 6ae064fc | Andreas Färber | g_slist_free(list); |
136 | 6ae064fc | Andreas Färber | } |
137 | 6ae064fc | Andreas Färber | |
138 | ca45f8b0 | Andreas Färber | static void cris_cpu_realizefn(DeviceState *dev, Error **errp) |
139 | ca45f8b0 | Andreas Färber | { |
140 | 14a10fc3 | Andreas Färber | CPUState *cs = CPU(dev); |
141 | ca45f8b0 | Andreas Färber | CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(dev); |
142 | ca45f8b0 | Andreas Färber | |
143 | 14a10fc3 | Andreas Färber | cpu_reset(cs); |
144 | 14a10fc3 | Andreas Färber | qemu_init_vcpu(cs); |
145 | ca45f8b0 | Andreas Färber | |
146 | ca45f8b0 | Andreas Färber | ccc->parent_realize(dev, errp); |
147 | ca45f8b0 | Andreas Färber | } |
148 | ca45f8b0 | Andreas Färber | |
149 | aa0d1267 | Andreas Färber | static void cris_cpu_initfn(Object *obj) |
150 | aa0d1267 | Andreas Färber | { |
151 | c05efcb1 | Andreas Färber | CPUState *cs = CPU(obj); |
152 | aa0d1267 | Andreas Färber | CRISCPU *cpu = CRIS_CPU(obj); |
153 | 6ae064fc | Andreas Färber | CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(obj); |
154 | aa0d1267 | Andreas Färber | CPUCRISState *env = &cpu->env; |
155 | d1a94fec | Andreas Färber | static bool tcg_initialized; |
156 | aa0d1267 | Andreas Färber | |
157 | c05efcb1 | Andreas Färber | cs->env_ptr = env; |
158 | aa0d1267 | Andreas Färber | cpu_exec_init(env); |
159 | d1a94fec | Andreas Färber | |
160 | 6ae064fc | Andreas Färber | env->pregs[PR_VR] = ccc->vr; |
161 | 6ae064fc | Andreas Färber | |
162 | d1a94fec | Andreas Färber | if (tcg_enabled() && !tcg_initialized) {
|
163 | d1a94fec | Andreas Färber | tcg_initialized = true;
|
164 | d1a94fec | Andreas Färber | if (env->pregs[PR_VR] < 32) { |
165 | d1a94fec | Andreas Färber | cris_initialize_crisv10_tcg(); |
166 | d1a94fec | Andreas Färber | } else {
|
167 | d1a94fec | Andreas Färber | cris_initialize_tcg(); |
168 | d1a94fec | Andreas Färber | } |
169 | d1a94fec | Andreas Färber | } |
170 | aa0d1267 | Andreas Färber | } |
171 | aa0d1267 | Andreas Färber | |
172 | 6ae064fc | Andreas Färber | static void crisv8_cpu_class_init(ObjectClass *oc, void *data) |
173 | 6ae064fc | Andreas Färber | { |
174 | b21bfeea | Andreas Färber | CPUClass *cc = CPU_CLASS(oc); |
175 | 6ae064fc | Andreas Färber | CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); |
176 | 6ae064fc | Andreas Färber | |
177 | 6ae064fc | Andreas Färber | ccc->vr = 8;
|
178 | b21bfeea | Andreas Färber | cc->do_interrupt = crisv10_cpu_do_interrupt; |
179 | 90431220 | Andreas Färber | cc->gdb_read_register = crisv10_cpu_gdb_read_register; |
180 | 6ae064fc | Andreas Färber | } |
181 | 6ae064fc | Andreas Färber | |
182 | 6ae064fc | Andreas Färber | static void crisv9_cpu_class_init(ObjectClass *oc, void *data) |
183 | 6ae064fc | Andreas Färber | { |
184 | b21bfeea | Andreas Färber | CPUClass *cc = CPU_CLASS(oc); |
185 | 6ae064fc | Andreas Färber | CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); |
186 | 6ae064fc | Andreas Färber | |
187 | 6ae064fc | Andreas Färber | ccc->vr = 9;
|
188 | b21bfeea | Andreas Färber | cc->do_interrupt = crisv10_cpu_do_interrupt; |
189 | 90431220 | Andreas Färber | cc->gdb_read_register = crisv10_cpu_gdb_read_register; |
190 | 6ae064fc | Andreas Färber | } |
191 | 6ae064fc | Andreas Färber | |
192 | 6ae064fc | Andreas Färber | static void crisv10_cpu_class_init(ObjectClass *oc, void *data) |
193 | 6ae064fc | Andreas Färber | { |
194 | b21bfeea | Andreas Färber | CPUClass *cc = CPU_CLASS(oc); |
195 | 6ae064fc | Andreas Färber | CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); |
196 | 6ae064fc | Andreas Färber | |
197 | 6ae064fc | Andreas Färber | ccc->vr = 10;
|
198 | b21bfeea | Andreas Färber | cc->do_interrupt = crisv10_cpu_do_interrupt; |
199 | 90431220 | Andreas Färber | cc->gdb_read_register = crisv10_cpu_gdb_read_register; |
200 | 6ae064fc | Andreas Färber | } |
201 | 6ae064fc | Andreas Färber | |
202 | 6ae064fc | Andreas Färber | static void crisv11_cpu_class_init(ObjectClass *oc, void *data) |
203 | 6ae064fc | Andreas Färber | { |
204 | b21bfeea | Andreas Färber | CPUClass *cc = CPU_CLASS(oc); |
205 | 6ae064fc | Andreas Färber | CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); |
206 | 6ae064fc | Andreas Färber | |
207 | 6ae064fc | Andreas Färber | ccc->vr = 11;
|
208 | b21bfeea | Andreas Färber | cc->do_interrupt = crisv10_cpu_do_interrupt; |
209 | 90431220 | Andreas Färber | cc->gdb_read_register = crisv10_cpu_gdb_read_register; |
210 | 6ae064fc | Andreas Färber | } |
211 | 6ae064fc | Andreas Färber | |
212 | 6ae064fc | Andreas Färber | static void crisv32_cpu_class_init(ObjectClass *oc, void *data) |
213 | 6ae064fc | Andreas Färber | { |
214 | 6ae064fc | Andreas Färber | CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); |
215 | 6ae064fc | Andreas Färber | |
216 | 6ae064fc | Andreas Färber | ccc->vr = 32;
|
217 | 6ae064fc | Andreas Färber | } |
218 | 6ae064fc | Andreas Färber | |
219 | 6ae064fc | Andreas Färber | #define TYPE(model) model "-" TYPE_CRIS_CPU |
220 | 6ae064fc | Andreas Färber | |
221 | 6ae064fc | Andreas Färber | static const TypeInfo cris_cpu_model_type_infos[] = { |
222 | 6ae064fc | Andreas Färber | { |
223 | 6ae064fc | Andreas Färber | .name = TYPE("crisv8"),
|
224 | 6ae064fc | Andreas Färber | .parent = TYPE_CRIS_CPU, |
225 | 6ae064fc | Andreas Färber | .class_init = crisv8_cpu_class_init, |
226 | 6ae064fc | Andreas Färber | }, { |
227 | 6ae064fc | Andreas Färber | .name = TYPE("crisv9"),
|
228 | 6ae064fc | Andreas Färber | .parent = TYPE_CRIS_CPU, |
229 | 6ae064fc | Andreas Färber | .class_init = crisv9_cpu_class_init, |
230 | 6ae064fc | Andreas Färber | }, { |
231 | 6ae064fc | Andreas Färber | .name = TYPE("crisv10"),
|
232 | 6ae064fc | Andreas Färber | .parent = TYPE_CRIS_CPU, |
233 | 6ae064fc | Andreas Färber | .class_init = crisv10_cpu_class_init, |
234 | 6ae064fc | Andreas Färber | }, { |
235 | 6ae064fc | Andreas Färber | .name = TYPE("crisv11"),
|
236 | 6ae064fc | Andreas Färber | .parent = TYPE_CRIS_CPU, |
237 | 6ae064fc | Andreas Färber | .class_init = crisv11_cpu_class_init, |
238 | 6ae064fc | Andreas Färber | }, { |
239 | 6ae064fc | Andreas Färber | .name = TYPE("crisv32"),
|
240 | 6ae064fc | Andreas Färber | .parent = TYPE_CRIS_CPU, |
241 | 6ae064fc | Andreas Färber | .class_init = crisv32_cpu_class_init, |
242 | 6ae064fc | Andreas Färber | } |
243 | 6ae064fc | Andreas Färber | }; |
244 | 6ae064fc | Andreas Färber | |
245 | 6ae064fc | Andreas Färber | #undef TYPE
|
246 | 6ae064fc | Andreas Färber | |
247 | e739a48e | Andreas Färber | static void cris_cpu_class_init(ObjectClass *oc, void *data) |
248 | e739a48e | Andreas Färber | { |
249 | ca45f8b0 | Andreas Färber | DeviceClass *dc = DEVICE_CLASS(oc); |
250 | e739a48e | Andreas Färber | CPUClass *cc = CPU_CLASS(oc); |
251 | e739a48e | Andreas Färber | CRISCPUClass *ccc = CRIS_CPU_CLASS(oc); |
252 | e739a48e | Andreas Färber | |
253 | ca45f8b0 | Andreas Färber | ccc->parent_realize = dc->realize; |
254 | ca45f8b0 | Andreas Färber | dc->realize = cris_cpu_realizefn; |
255 | ca45f8b0 | Andreas Färber | |
256 | e739a48e | Andreas Färber | ccc->parent_reset = cc->reset; |
257 | e739a48e | Andreas Färber | cc->reset = cris_cpu_reset; |
258 | 6ae064fc | Andreas Färber | |
259 | 6ae064fc | Andreas Färber | cc->class_by_name = cris_cpu_class_by_name; |
260 | 97a8ea5a | Andreas Färber | cc->do_interrupt = cris_cpu_do_interrupt; |
261 | 878096ee | Andreas Färber | cc->dump_state = cris_cpu_dump_state; |
262 | f45748f1 | Andreas Färber | cc->set_pc = cris_cpu_set_pc; |
263 | 5b50e790 | Andreas Färber | cc->gdb_read_register = cris_cpu_gdb_read_register; |
264 | 5b50e790 | Andreas Färber | cc->gdb_write_register = cris_cpu_gdb_write_register; |
265 | 00b941e5 | Andreas Färber | #ifndef CONFIG_USER_ONLY
|
266 | 00b941e5 | Andreas Färber | cc->get_phys_page_debug = cris_cpu_get_phys_page_debug; |
267 | 00b941e5 | Andreas Färber | #endif
|
268 | a0e372f0 | Andreas Färber | |
269 | a0e372f0 | Andreas Färber | cc->gdb_num_core_regs = 49;
|
270 | e739a48e | Andreas Färber | } |
271 | e739a48e | Andreas Färber | |
272 | e739a48e | Andreas Färber | static const TypeInfo cris_cpu_type_info = { |
273 | e739a48e | Andreas Färber | .name = TYPE_CRIS_CPU, |
274 | e739a48e | Andreas Färber | .parent = TYPE_CPU, |
275 | e739a48e | Andreas Färber | .instance_size = sizeof(CRISCPU),
|
276 | aa0d1267 | Andreas Färber | .instance_init = cris_cpu_initfn, |
277 | 6ae064fc | Andreas Färber | .abstract = true,
|
278 | e739a48e | Andreas Färber | .class_size = sizeof(CRISCPUClass),
|
279 | e739a48e | Andreas Färber | .class_init = cris_cpu_class_init, |
280 | e739a48e | Andreas Färber | }; |
281 | e739a48e | Andreas Färber | |
282 | e739a48e | Andreas Färber | static void cris_cpu_register_types(void) |
283 | e739a48e | Andreas Färber | { |
284 | 6ae064fc | Andreas Färber | int i;
|
285 | 6ae064fc | Andreas Färber | |
286 | e739a48e | Andreas Färber | type_register_static(&cris_cpu_type_info); |
287 | 6ae064fc | Andreas Färber | for (i = 0; i < ARRAY_SIZE(cris_cpu_model_type_infos); i++) { |
288 | 6ae064fc | Andreas Färber | type_register_static(&cris_cpu_model_type_infos[i]); |
289 | 6ae064fc | Andreas Färber | } |
290 | e739a48e | Andreas Färber | } |
291 | e739a48e | Andreas Färber | |
292 | e739a48e | Andreas Färber | type_init(cris_cpu_register_types) |