Statistics
| Branch: | Revision:

root / target-sh4 / cpu.c @ 5b50e790

History | View | Annotate | Download (8.2 kB)

1 339894be Andreas Färber
/*
2 339894be Andreas Färber
 * QEMU SuperH CPU
3 339894be Andreas Färber
 *
4 c4bb0f99 Andreas Färber
 * Copyright (c) 2005 Samuel Tardieu
5 339894be Andreas Färber
 * Copyright (c) 2012 SUSE LINUX Products GmbH
6 339894be Andreas Färber
 *
7 339894be Andreas Färber
 * This library is free software; you can redistribute it and/or
8 339894be Andreas Färber
 * modify it under the terms of the GNU Lesser General Public
9 339894be Andreas Färber
 * License as published by the Free Software Foundation; either
10 339894be Andreas Färber
 * version 2.1 of the License, or (at your option) any later version.
11 339894be Andreas Färber
 *
12 339894be Andreas Färber
 * This library is distributed in the hope that it will be useful,
13 339894be Andreas Färber
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 339894be Andreas Färber
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 339894be Andreas Färber
 * Lesser General Public License for more details.
16 339894be Andreas Färber
 *
17 339894be Andreas Färber
 * You should have received a copy of the GNU Lesser General Public
18 339894be Andreas Färber
 * License along with this library; if not, see
19 339894be Andreas Färber
 * <http://www.gnu.org/licenses/lgpl-2.1.html>
20 339894be Andreas Färber
 */
21 339894be Andreas Färber
22 339894be Andreas Färber
#include "cpu.h"
23 339894be Andreas Färber
#include "qemu-common.h"
24 1e45d31b Andreas Färber
#include "migration/vmstate.h"
25 339894be Andreas Färber
26 339894be Andreas Färber
27 f45748f1 Andreas Färber
static void superh_cpu_set_pc(CPUState *cs, vaddr value)
28 f45748f1 Andreas Färber
{
29 f45748f1 Andreas Färber
    SuperHCPU *cpu = SUPERH_CPU(cs);
30 f45748f1 Andreas Färber
31 f45748f1 Andreas Färber
    cpu->env.pc = value;
32 f45748f1 Andreas Färber
}
33 f45748f1 Andreas Färber
34 bdf7ae5b Andreas Färber
static void superh_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
35 bdf7ae5b Andreas Färber
{
36 bdf7ae5b Andreas Färber
    SuperHCPU *cpu = SUPERH_CPU(cs);
37 bdf7ae5b Andreas Färber
38 bdf7ae5b Andreas Färber
    cpu->env.pc = tb->pc;
39 bdf7ae5b Andreas Färber
    cpu->env.flags = tb->flags;
40 bdf7ae5b Andreas Färber
}
41 bdf7ae5b Andreas Färber
42 339894be Andreas Färber
/* CPUClass::reset() */
43 339894be Andreas Färber
static void superh_cpu_reset(CPUState *s)
44 339894be Andreas Färber
{
45 339894be Andreas Färber
    SuperHCPU *cpu = SUPERH_CPU(s);
46 339894be Andreas Färber
    SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(cpu);
47 339894be Andreas Färber
    CPUSH4State *env = &cpu->env;
48 339894be Andreas Färber
49 339894be Andreas Färber
    scc->parent_reset(s);
50 339894be Andreas Färber
51 c4bb0f99 Andreas Färber
    memset(env, 0, offsetof(CPUSH4State, breakpoints));
52 c4bb0f99 Andreas Färber
    tlb_flush(env, 1);
53 c4bb0f99 Andreas Färber
54 c4bb0f99 Andreas Färber
    env->pc = 0xA0000000;
55 c4bb0f99 Andreas Färber
#if defined(CONFIG_USER_ONLY)
56 c4bb0f99 Andreas Färber
    env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
57 c4bb0f99 Andreas Färber
    set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
58 c4bb0f99 Andreas Färber
#else
59 c4bb0f99 Andreas Färber
    env->sr = SR_MD | SR_RB | SR_BL | SR_I3 | SR_I2 | SR_I1 | SR_I0;
60 c4bb0f99 Andreas Färber
    env->fpscr = FPSCR_DN | FPSCR_RM_ZERO; /* CPU reset value according to SH4 manual */
61 c4bb0f99 Andreas Färber
    set_float_rounding_mode(float_round_to_zero, &env->fp_status);
62 c4bb0f99 Andreas Färber
    set_flush_to_zero(1, &env->fp_status);
63 c4bb0f99 Andreas Färber
#endif
64 c4bb0f99 Andreas Färber
    set_default_nan_mode(1, &env->fp_status);
65 339894be Andreas Färber
}
66 339894be Andreas Färber
67 c1b382e7 Andreas Färber
typedef struct SuperHCPUListState {
68 c1b382e7 Andreas Färber
    fprintf_function cpu_fprintf;
69 c1b382e7 Andreas Färber
    FILE *file;
70 c1b382e7 Andreas Färber
} SuperHCPUListState;
71 c1b382e7 Andreas Färber
72 c1b382e7 Andreas Färber
/* Sort alphabetically by type name. */
73 c1b382e7 Andreas Färber
static gint superh_cpu_list_compare(gconstpointer a, gconstpointer b)
74 c1b382e7 Andreas Färber
{
75 c1b382e7 Andreas Färber
    ObjectClass *class_a = (ObjectClass *)a;
76 c1b382e7 Andreas Färber
    ObjectClass *class_b = (ObjectClass *)b;
77 c1b382e7 Andreas Färber
    const char *name_a, *name_b;
78 c1b382e7 Andreas Färber
79 c1b382e7 Andreas Färber
    name_a = object_class_get_name(class_a);
80 c1b382e7 Andreas Färber
    name_b = object_class_get_name(class_b);
81 c1b382e7 Andreas Färber
    return strcmp(name_a, name_b);
82 c1b382e7 Andreas Färber
}
83 c1b382e7 Andreas Färber
84 c1b382e7 Andreas Färber
static void superh_cpu_list_entry(gpointer data, gpointer user_data)
85 c1b382e7 Andreas Färber
{
86 c1b382e7 Andreas Färber
    ObjectClass *oc = data;
87 c1b382e7 Andreas Färber
    SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
88 c1b382e7 Andreas Färber
    SuperHCPUListState *s = user_data;
89 c1b382e7 Andreas Färber
90 c1b382e7 Andreas Färber
    (*s->cpu_fprintf)(s->file, "%s\n",
91 c1b382e7 Andreas Färber
                      scc->name);
92 c1b382e7 Andreas Färber
}
93 c1b382e7 Andreas Färber
94 c1b382e7 Andreas Färber
void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf)
95 c1b382e7 Andreas Färber
{
96 c1b382e7 Andreas Färber
    SuperHCPUListState s = {
97 c1b382e7 Andreas Färber
        .cpu_fprintf = cpu_fprintf,
98 c1b382e7 Andreas Färber
        .file = f,
99 c1b382e7 Andreas Färber
    };
100 c1b382e7 Andreas Färber
    GSList *list;
101 c1b382e7 Andreas Färber
102 c1b382e7 Andreas Färber
    list = object_class_get_list(TYPE_SUPERH_CPU, false);
103 c1b382e7 Andreas Färber
    list = g_slist_sort(list, superh_cpu_list_compare);
104 c1b382e7 Andreas Färber
    g_slist_foreach(list, superh_cpu_list_entry, &s);
105 c1b382e7 Andreas Färber
    g_slist_free(list);
106 c1b382e7 Andreas Färber
}
107 c1b382e7 Andreas Färber
108 c1b382e7 Andreas Färber
static gint superh_cpu_name_compare(gconstpointer a, gconstpointer b)
109 c1b382e7 Andreas Färber
{
110 c1b382e7 Andreas Färber
    const SuperHCPUClass *scc = SUPERH_CPU_CLASS(a);
111 c1b382e7 Andreas Färber
    const char *name = b;
112 c1b382e7 Andreas Färber
113 c1b382e7 Andreas Färber
    return strcasecmp(scc->name, name);
114 c1b382e7 Andreas Färber
}
115 c1b382e7 Andreas Färber
116 c1b382e7 Andreas Färber
static ObjectClass *superh_cpu_class_by_name(const char *cpu_model)
117 c1b382e7 Andreas Färber
{
118 c1b382e7 Andreas Färber
    ObjectClass *oc;
119 c1b382e7 Andreas Färber
    GSList *list, *item;
120 c1b382e7 Andreas Färber
121 c1b382e7 Andreas Färber
    if (cpu_model == NULL) {
122 c1b382e7 Andreas Färber
        return NULL;
123 c1b382e7 Andreas Färber
    }
124 c1b382e7 Andreas Färber
    if (strcasecmp(cpu_model, "any") == 0) {
125 c1b382e7 Andreas Färber
        return object_class_by_name(TYPE_SH7750R_CPU);
126 c1b382e7 Andreas Färber
    }
127 c1b382e7 Andreas Färber
128 c1b382e7 Andreas Färber
    oc = object_class_by_name(cpu_model);
129 c1b382e7 Andreas Färber
    if (oc != NULL && object_class_dynamic_cast(oc, TYPE_SUPERH_CPU) != NULL
130 c1b382e7 Andreas Färber
        && !object_class_is_abstract(oc)) {
131 c1b382e7 Andreas Färber
        return oc;
132 c1b382e7 Andreas Färber
    }
133 c1b382e7 Andreas Färber
134 c1b382e7 Andreas Färber
    oc = NULL;
135 c1b382e7 Andreas Färber
    list = object_class_get_list(TYPE_SUPERH_CPU, false);
136 c1b382e7 Andreas Färber
    item = g_slist_find_custom(list, cpu_model, superh_cpu_name_compare);
137 c1b382e7 Andreas Färber
    if (item != NULL) {
138 c1b382e7 Andreas Färber
        oc = item->data;
139 c1b382e7 Andreas Färber
    }
140 c1b382e7 Andreas Färber
    g_slist_free(list);
141 c1b382e7 Andreas Färber
    return oc;
142 c1b382e7 Andreas Färber
}
143 c1b382e7 Andreas Färber
144 c1b382e7 Andreas Färber
SuperHCPU *cpu_sh4_init(const char *cpu_model)
145 c1b382e7 Andreas Färber
{
146 c1b382e7 Andreas Färber
    SuperHCPU *cpu;
147 c1b382e7 Andreas Färber
    CPUSH4State *env;
148 c1b382e7 Andreas Färber
    ObjectClass *oc;
149 c1b382e7 Andreas Färber
150 c1b382e7 Andreas Färber
    oc = superh_cpu_class_by_name(cpu_model);
151 c1b382e7 Andreas Färber
    if (oc == NULL) {
152 c1b382e7 Andreas Färber
        return NULL;
153 c1b382e7 Andreas Färber
    }
154 c1b382e7 Andreas Färber
    cpu = SUPERH_CPU(object_new(object_class_get_name(oc)));
155 c1b382e7 Andreas Färber
    env = &cpu->env;
156 c1b382e7 Andreas Färber
    env->cpu_model_str = cpu_model;
157 c1b382e7 Andreas Färber
158 c1b382e7 Andreas Färber
    object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
159 c1b382e7 Andreas Färber
160 c1b382e7 Andreas Färber
    return cpu;
161 c1b382e7 Andreas Färber
}
162 c1b382e7 Andreas Färber
163 c1b382e7 Andreas Färber
static void sh7750r_cpu_initfn(Object *obj)
164 c1b382e7 Andreas Färber
{
165 c1b382e7 Andreas Färber
    SuperHCPU *cpu = SUPERH_CPU(obj);
166 c1b382e7 Andreas Färber
    CPUSH4State *env = &cpu->env;
167 c1b382e7 Andreas Färber
168 c1b382e7 Andreas Färber
    env->id = SH_CPU_SH7750R;
169 c1b382e7 Andreas Färber
    env->features = SH_FEATURE_BCR3_AND_BCR4;
170 c1b382e7 Andreas Färber
}
171 c1b382e7 Andreas Färber
172 c1b382e7 Andreas Färber
static void sh7750r_class_init(ObjectClass *oc, void *data)
173 c1b382e7 Andreas Färber
{
174 c1b382e7 Andreas Färber
    SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
175 c1b382e7 Andreas Färber
176 c1b382e7 Andreas Färber
    scc->name = "SH7750R";
177 b350ab75 Andreas Färber
    scc->pvr = 0x00050000;
178 b350ab75 Andreas Färber
    scc->prr = 0x00000100;
179 b350ab75 Andreas Färber
    scc->cvr = 0x00110000;
180 c1b382e7 Andreas Färber
}
181 c1b382e7 Andreas Färber
182 c1b382e7 Andreas Färber
static const TypeInfo sh7750r_type_info = {
183 c1b382e7 Andreas Färber
    .name = TYPE_SH7750R_CPU,
184 c1b382e7 Andreas Färber
    .parent = TYPE_SUPERH_CPU,
185 c1b382e7 Andreas Färber
    .class_init = sh7750r_class_init,
186 c1b382e7 Andreas Färber
    .instance_init = sh7750r_cpu_initfn,
187 c1b382e7 Andreas Färber
};
188 c1b382e7 Andreas Färber
189 c1b382e7 Andreas Färber
static void sh7751r_cpu_initfn(Object *obj)
190 c1b382e7 Andreas Färber
{
191 c1b382e7 Andreas Färber
    SuperHCPU *cpu = SUPERH_CPU(obj);
192 c1b382e7 Andreas Färber
    CPUSH4State *env = &cpu->env;
193 c1b382e7 Andreas Färber
194 c1b382e7 Andreas Färber
    env->id = SH_CPU_SH7751R;
195 c1b382e7 Andreas Färber
    env->features = SH_FEATURE_BCR3_AND_BCR4;
196 c1b382e7 Andreas Färber
}
197 c1b382e7 Andreas Färber
198 c1b382e7 Andreas Färber
static void sh7751r_class_init(ObjectClass *oc, void *data)
199 c1b382e7 Andreas Färber
{
200 c1b382e7 Andreas Färber
    SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
201 c1b382e7 Andreas Färber
202 c1b382e7 Andreas Färber
    scc->name = "SH7751R";
203 b350ab75 Andreas Färber
    scc->pvr = 0x04050005;
204 b350ab75 Andreas Färber
    scc->prr = 0x00000113;
205 b350ab75 Andreas Färber
    scc->cvr = 0x00110000; /* Neutered caches, should be 0x20480000 */
206 c1b382e7 Andreas Färber
}
207 c1b382e7 Andreas Färber
208 c1b382e7 Andreas Färber
static const TypeInfo sh7751r_type_info = {
209 c1b382e7 Andreas Färber
    .name = TYPE_SH7751R_CPU,
210 c1b382e7 Andreas Färber
    .parent = TYPE_SUPERH_CPU,
211 c1b382e7 Andreas Färber
    .class_init = sh7751r_class_init,
212 c1b382e7 Andreas Färber
    .instance_init = sh7751r_cpu_initfn,
213 c1b382e7 Andreas Färber
};
214 c1b382e7 Andreas Färber
215 c1b382e7 Andreas Färber
static void sh7785_cpu_initfn(Object *obj)
216 c1b382e7 Andreas Färber
{
217 c1b382e7 Andreas Färber
    SuperHCPU *cpu = SUPERH_CPU(obj);
218 c1b382e7 Andreas Färber
    CPUSH4State *env = &cpu->env;
219 c1b382e7 Andreas Färber
220 c1b382e7 Andreas Färber
    env->id = SH_CPU_SH7785;
221 c1b382e7 Andreas Färber
    env->features = SH_FEATURE_SH4A;
222 c1b382e7 Andreas Färber
}
223 c1b382e7 Andreas Färber
224 c1b382e7 Andreas Färber
static void sh7785_class_init(ObjectClass *oc, void *data)
225 c1b382e7 Andreas Färber
{
226 c1b382e7 Andreas Färber
    SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
227 c1b382e7 Andreas Färber
228 c1b382e7 Andreas Färber
    scc->name = "SH7785";
229 b350ab75 Andreas Färber
    scc->pvr = 0x10300700;
230 b350ab75 Andreas Färber
    scc->prr = 0x00000200;
231 b350ab75 Andreas Färber
    scc->cvr = 0x71440211;
232 c1b382e7 Andreas Färber
}
233 c1b382e7 Andreas Färber
234 c1b382e7 Andreas Färber
static const TypeInfo sh7785_type_info = {
235 c1b382e7 Andreas Färber
    .name = TYPE_SH7785_CPU,
236 c1b382e7 Andreas Färber
    .parent = TYPE_SUPERH_CPU,
237 c1b382e7 Andreas Färber
    .class_init = sh7785_class_init,
238 c1b382e7 Andreas Färber
    .instance_init = sh7785_cpu_initfn,
239 c1b382e7 Andreas Färber
};
240 c1b382e7 Andreas Färber
241 55acb588 Andreas Färber
static void superh_cpu_realizefn(DeviceState *dev, Error **errp)
242 55acb588 Andreas Färber
{
243 55acb588 Andreas Färber
    SuperHCPU *cpu = SUPERH_CPU(dev);
244 55acb588 Andreas Färber
    SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(dev);
245 55acb588 Andreas Färber
246 55acb588 Andreas Färber
    cpu_reset(CPU(cpu));
247 55acb588 Andreas Färber
248 55acb588 Andreas Färber
    scc->parent_realize(dev, errp);
249 55acb588 Andreas Färber
}
250 55acb588 Andreas Färber
251 2b4b4906 Andreas Färber
static void superh_cpu_initfn(Object *obj)
252 2b4b4906 Andreas Färber
{
253 c05efcb1 Andreas Färber
    CPUState *cs = CPU(obj);
254 2b4b4906 Andreas Färber
    SuperHCPU *cpu = SUPERH_CPU(obj);
255 2b4b4906 Andreas Färber
    CPUSH4State *env = &cpu->env;
256 2b4b4906 Andreas Färber
257 c05efcb1 Andreas Färber
    cs->env_ptr = env;
258 2b4b4906 Andreas Färber
    cpu_exec_init(env);
259 2b4b4906 Andreas Färber
260 2b4b4906 Andreas Färber
    env->movcal_backup_tail = &(env->movcal_backup);
261 aa7408ec Andreas Färber
262 aa7408ec Andreas Färber
    if (tcg_enabled()) {
263 aa7408ec Andreas Färber
        sh4_translate_init();
264 aa7408ec Andreas Färber
    }
265 2b4b4906 Andreas Färber
}
266 2b4b4906 Andreas Färber
267 1e45d31b Andreas Färber
static const VMStateDescription vmstate_sh_cpu = {
268 1e45d31b Andreas Färber
    .name = "cpu",
269 1e45d31b Andreas Färber
    .unmigratable = 1,
270 1e45d31b Andreas Färber
};
271 1e45d31b Andreas Färber
272 339894be Andreas Färber
static void superh_cpu_class_init(ObjectClass *oc, void *data)
273 339894be Andreas Färber
{
274 1e45d31b Andreas Färber
    DeviceClass *dc = DEVICE_CLASS(oc);
275 339894be Andreas Färber
    CPUClass *cc = CPU_CLASS(oc);
276 339894be Andreas Färber
    SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
277 339894be Andreas Färber
278 55acb588 Andreas Färber
    scc->parent_realize = dc->realize;
279 55acb588 Andreas Färber
    dc->realize = superh_cpu_realizefn;
280 55acb588 Andreas Färber
281 339894be Andreas Färber
    scc->parent_reset = cc->reset;
282 339894be Andreas Färber
    cc->reset = superh_cpu_reset;
283 1e45d31b Andreas Färber
284 c1b382e7 Andreas Färber
    cc->class_by_name = superh_cpu_class_by_name;
285 97a8ea5a Andreas Färber
    cc->do_interrupt = superh_cpu_do_interrupt;
286 878096ee Andreas Färber
    cc->dump_state = superh_cpu_dump_state;
287 f45748f1 Andreas Färber
    cc->set_pc = superh_cpu_set_pc;
288 bdf7ae5b Andreas Färber
    cc->synchronize_from_tb = superh_cpu_synchronize_from_tb;
289 5b50e790 Andreas Färber
    cc->gdb_read_register = superh_cpu_gdb_read_register;
290 5b50e790 Andreas Färber
    cc->gdb_write_register = superh_cpu_gdb_write_register;
291 00b941e5 Andreas Färber
#ifndef CONFIG_USER_ONLY
292 00b941e5 Andreas Färber
    cc->get_phys_page_debug = superh_cpu_get_phys_page_debug;
293 00b941e5 Andreas Färber
#endif
294 1e45d31b Andreas Färber
    dc->vmsd = &vmstate_sh_cpu;
295 a0e372f0 Andreas Färber
    cc->gdb_num_core_regs = 59;
296 339894be Andreas Färber
}
297 339894be Andreas Färber
298 339894be Andreas Färber
static const TypeInfo superh_cpu_type_info = {
299 339894be Andreas Färber
    .name = TYPE_SUPERH_CPU,
300 339894be Andreas Färber
    .parent = TYPE_CPU,
301 339894be Andreas Färber
    .instance_size = sizeof(SuperHCPU),
302 2b4b4906 Andreas Färber
    .instance_init = superh_cpu_initfn,
303 c1b382e7 Andreas Färber
    .abstract = true,
304 339894be Andreas Färber
    .class_size = sizeof(SuperHCPUClass),
305 339894be Andreas Färber
    .class_init = superh_cpu_class_init,
306 339894be Andreas Färber
};
307 339894be Andreas Färber
308 339894be Andreas Färber
static void superh_cpu_register_types(void)
309 339894be Andreas Färber
{
310 339894be Andreas Färber
    type_register_static(&superh_cpu_type_info);
311 c1b382e7 Andreas Färber
    type_register_static(&sh7750r_type_info);
312 c1b382e7 Andreas Färber
    type_register_static(&sh7751r_type_info);
313 c1b382e7 Andreas Färber
    type_register_static(&sh7785_type_info);
314 339894be Andreas Färber
}
315 339894be Andreas Färber
316 339894be Andreas Färber
type_init(superh_cpu_register_types)