root / target-m68k / cpu.c @ 5b50e790
History | View | Annotate | Download (6.2 kB)
1 | b9e7a234 | Andreas Färber | /*
|
---|---|---|---|
2 | b9e7a234 | Andreas Färber | * QEMU Motorola 68k CPU
|
3 | b9e7a234 | Andreas Färber | *
|
4 | b9e7a234 | Andreas Färber | * Copyright (c) 2012 SUSE LINUX Products GmbH
|
5 | b9e7a234 | Andreas Färber | *
|
6 | b9e7a234 | Andreas Färber | * This library is free software; you can redistribute it and/or
|
7 | b9e7a234 | Andreas Färber | * modify it under the terms of the GNU Lesser General Public
|
8 | b9e7a234 | Andreas Färber | * License as published by the Free Software Foundation; either
|
9 | b9e7a234 | Andreas Färber | * version 2.1 of the License, or (at your option) any later version.
|
10 | b9e7a234 | Andreas Färber | *
|
11 | b9e7a234 | Andreas Färber | * This library is distributed in the hope that it will be useful,
|
12 | b9e7a234 | Andreas Färber | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | b9e7a234 | Andreas Färber | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | b9e7a234 | Andreas Färber | * Lesser General Public License for more details.
|
15 | b9e7a234 | Andreas Färber | *
|
16 | b9e7a234 | Andreas Färber | * You should have received a copy of the GNU Lesser General Public
|
17 | b9e7a234 | Andreas Färber | * License along with this library; if not, see
|
18 | b9e7a234 | Andreas Färber | * <http://www.gnu.org/licenses/lgpl-2.1.html>
|
19 | b9e7a234 | Andreas Färber | */
|
20 | b9e7a234 | Andreas Färber | |
21 | b9e7a234 | Andreas Färber | #include "cpu.h" |
22 | b9e7a234 | Andreas Färber | #include "qemu-common.h" |
23 | 087fe4f8 | Andreas Färber | #include "migration/vmstate.h" |
24 | b9e7a234 | Andreas Färber | |
25 | b9e7a234 | Andreas Färber | |
26 | e700604d | Andreas Färber | static void m68k_cpu_set_pc(CPUState *cs, vaddr value) |
27 | e700604d | Andreas Färber | { |
28 | e700604d | Andreas Färber | M68kCPU *cpu = M68K_CPU(cs); |
29 | e700604d | Andreas Färber | |
30 | e700604d | Andreas Färber | cpu->env.pc = value; |
31 | e700604d | Andreas Färber | } |
32 | e700604d | Andreas Färber | |
33 | 11150915 | Andreas Färber | static void m68k_set_feature(CPUM68KState *env, int feature) |
34 | 11150915 | Andreas Färber | { |
35 | 11150915 | Andreas Färber | env->features |= (1u << feature);
|
36 | 11150915 | Andreas Färber | } |
37 | 11150915 | Andreas Färber | |
38 | b9e7a234 | Andreas Färber | /* CPUClass::reset() */
|
39 | b9e7a234 | Andreas Färber | static void m68k_cpu_reset(CPUState *s) |
40 | b9e7a234 | Andreas Färber | { |
41 | b9e7a234 | Andreas Färber | M68kCPU *cpu = M68K_CPU(s); |
42 | b9e7a234 | Andreas Färber | M68kCPUClass *mcc = M68K_CPU_GET_CLASS(cpu); |
43 | b9e7a234 | Andreas Färber | CPUM68KState *env = &cpu->env; |
44 | b9e7a234 | Andreas Färber | |
45 | b9e7a234 | Andreas Färber | mcc->parent_reset(s); |
46 | b9e7a234 | Andreas Färber | |
47 | 11c19868 | Andreas Färber | memset(env, 0, offsetof(CPUM68KState, breakpoints));
|
48 | 11c19868 | Andreas Färber | #if !defined(CONFIG_USER_ONLY)
|
49 | 11c19868 | Andreas Färber | env->sr = 0x2700;
|
50 | 11c19868 | Andreas Färber | #endif
|
51 | 11c19868 | Andreas Färber | m68k_switch_sp(env); |
52 | 11c19868 | Andreas Färber | /* ??? FP regs should be initialized to NaN. */
|
53 | 11c19868 | Andreas Färber | env->cc_op = CC_OP_FLAGS; |
54 | 11c19868 | Andreas Färber | /* TODO: We should set PC from the interrupt vector. */
|
55 | 11c19868 | Andreas Färber | env->pc = 0;
|
56 | 11c19868 | Andreas Färber | tlb_flush(env, 1);
|
57 | b9e7a234 | Andreas Färber | } |
58 | b9e7a234 | Andreas Färber | |
59 | 11150915 | Andreas Färber | /* CPU models */
|
60 | 11150915 | Andreas Färber | |
61 | bc5b2da3 | Andreas Färber | static ObjectClass *m68k_cpu_class_by_name(const char *cpu_model) |
62 | bc5b2da3 | Andreas Färber | { |
63 | bc5b2da3 | Andreas Färber | ObjectClass *oc; |
64 | 7a9f812b | Andreas Färber | char *typename;
|
65 | bc5b2da3 | Andreas Färber | |
66 | bc5b2da3 | Andreas Färber | if (cpu_model == NULL) { |
67 | bc5b2da3 | Andreas Färber | return NULL; |
68 | bc5b2da3 | Andreas Färber | } |
69 | bc5b2da3 | Andreas Färber | |
70 | 7a9f812b | Andreas Färber | typename = g_strdup_printf("%s-" TYPE_M68K_CPU, cpu_model);
|
71 | 7a9f812b | Andreas Färber | oc = object_class_by_name(typename); |
72 | 7a9f812b | Andreas Färber | g_free(typename); |
73 | cae85065 | Andreas Färber | if (oc != NULL && (object_class_dynamic_cast(oc, TYPE_M68K_CPU) == NULL || |
74 | cae85065 | Andreas Färber | object_class_is_abstract(oc))) { |
75 | bc5b2da3 | Andreas Färber | return NULL; |
76 | bc5b2da3 | Andreas Färber | } |
77 | bc5b2da3 | Andreas Färber | return oc;
|
78 | bc5b2da3 | Andreas Färber | } |
79 | bc5b2da3 | Andreas Färber | |
80 | 11150915 | Andreas Färber | static void m5206_cpu_initfn(Object *obj) |
81 | 11150915 | Andreas Färber | { |
82 | 11150915 | Andreas Färber | M68kCPU *cpu = M68K_CPU(obj); |
83 | 11150915 | Andreas Färber | CPUM68KState *env = &cpu->env; |
84 | 11150915 | Andreas Färber | |
85 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); |
86 | 11150915 | Andreas Färber | } |
87 | 11150915 | Andreas Färber | |
88 | 11150915 | Andreas Färber | static void m5208_cpu_initfn(Object *obj) |
89 | 11150915 | Andreas Färber | { |
90 | 11150915 | Andreas Färber | M68kCPU *cpu = M68K_CPU(obj); |
91 | 11150915 | Andreas Färber | CPUM68KState *env = &cpu->env; |
92 | 11150915 | Andreas Färber | |
93 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); |
94 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC); |
95 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_BRAL); |
96 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_CF_EMAC); |
97 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_USP); |
98 | 11150915 | Andreas Färber | } |
99 | 11150915 | Andreas Färber | |
100 | 11150915 | Andreas Färber | static void cfv4e_cpu_initfn(Object *obj) |
101 | 11150915 | Andreas Färber | { |
102 | 11150915 | Andreas Färber | M68kCPU *cpu = M68K_CPU(obj); |
103 | 11150915 | Andreas Färber | CPUM68KState *env = &cpu->env; |
104 | 11150915 | Andreas Färber | |
105 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); |
106 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); |
107 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_BRAL); |
108 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_CF_FPU); |
109 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_CF_EMAC); |
110 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_USP); |
111 | 11150915 | Andreas Färber | } |
112 | 11150915 | Andreas Färber | |
113 | 11150915 | Andreas Färber | static void any_cpu_initfn(Object *obj) |
114 | 11150915 | Andreas Färber | { |
115 | 11150915 | Andreas Färber | M68kCPU *cpu = M68K_CPU(obj); |
116 | 11150915 | Andreas Färber | CPUM68KState *env = &cpu->env; |
117 | 11150915 | Andreas Färber | |
118 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); |
119 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); |
120 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC); |
121 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_BRAL); |
122 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_CF_FPU); |
123 | 11150915 | Andreas Färber | /* MAC and EMAC are mututally exclusive, so pick EMAC.
|
124 | 11150915 | Andreas Färber | It's mostly backwards compatible. */
|
125 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_CF_EMAC); |
126 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B); |
127 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_USP); |
128 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_EXT_FULL); |
129 | 11150915 | Andreas Färber | m68k_set_feature(env, M68K_FEATURE_WORD_INDEX); |
130 | 11150915 | Andreas Färber | } |
131 | 11150915 | Andreas Färber | |
132 | 11150915 | Andreas Färber | typedef struct M68kCPUInfo { |
133 | 11150915 | Andreas Färber | const char *name; |
134 | 11150915 | Andreas Färber | void (*instance_init)(Object *obj);
|
135 | 11150915 | Andreas Färber | } M68kCPUInfo; |
136 | 11150915 | Andreas Färber | |
137 | 11150915 | Andreas Färber | static const M68kCPUInfo m68k_cpus[] = { |
138 | 11150915 | Andreas Färber | { .name = "m5206", .instance_init = m5206_cpu_initfn },
|
139 | 11150915 | Andreas Färber | { .name = "m5208", .instance_init = m5208_cpu_initfn },
|
140 | 11150915 | Andreas Färber | { .name = "cfv4e", .instance_init = cfv4e_cpu_initfn },
|
141 | 11150915 | Andreas Färber | { .name = "any", .instance_init = any_cpu_initfn },
|
142 | 11150915 | Andreas Färber | }; |
143 | 11150915 | Andreas Färber | |
144 | 6d1bbc62 | Andreas Färber | static void m68k_cpu_realizefn(DeviceState *dev, Error **errp) |
145 | 6d1bbc62 | Andreas Färber | { |
146 | 6d1bbc62 | Andreas Färber | M68kCPU *cpu = M68K_CPU(dev); |
147 | 6d1bbc62 | Andreas Färber | M68kCPUClass *mcc = M68K_CPU_GET_CLASS(dev); |
148 | 6d1bbc62 | Andreas Färber | |
149 | 6d1bbc62 | Andreas Färber | m68k_cpu_init_gdb(cpu); |
150 | 6d1bbc62 | Andreas Färber | |
151 | 6d1bbc62 | Andreas Färber | cpu_reset(CPU(cpu)); |
152 | 6d1bbc62 | Andreas Färber | |
153 | 6d1bbc62 | Andreas Färber | mcc->parent_realize(dev, errp); |
154 | 6d1bbc62 | Andreas Färber | } |
155 | 6d1bbc62 | Andreas Färber | |
156 | 9b706039 | Andreas Färber | static void m68k_cpu_initfn(Object *obj) |
157 | 9b706039 | Andreas Färber | { |
158 | c05efcb1 | Andreas Färber | CPUState *cs = CPU(obj); |
159 | 9b706039 | Andreas Färber | M68kCPU *cpu = M68K_CPU(obj); |
160 | 9b706039 | Andreas Färber | CPUM68KState *env = &cpu->env; |
161 | 1cc89619 | Andreas Färber | static bool inited; |
162 | 9b706039 | Andreas Färber | |
163 | c05efcb1 | Andreas Färber | cs->env_ptr = env; |
164 | 9b706039 | Andreas Färber | cpu_exec_init(env); |
165 | 1cc89619 | Andreas Färber | |
166 | 1cc89619 | Andreas Färber | if (tcg_enabled() && !inited) {
|
167 | 1cc89619 | Andreas Färber | inited = true;
|
168 | 1cc89619 | Andreas Färber | m68k_tcg_init(); |
169 | 1cc89619 | Andreas Färber | } |
170 | 9b706039 | Andreas Färber | } |
171 | 9b706039 | Andreas Färber | |
172 | 087fe4f8 | Andreas Färber | static const VMStateDescription vmstate_m68k_cpu = { |
173 | 087fe4f8 | Andreas Färber | .name = "cpu",
|
174 | 087fe4f8 | Andreas Färber | .unmigratable = 1,
|
175 | 087fe4f8 | Andreas Färber | }; |
176 | 087fe4f8 | Andreas Färber | |
177 | b9e7a234 | Andreas Färber | static void m68k_cpu_class_init(ObjectClass *c, void *data) |
178 | b9e7a234 | Andreas Färber | { |
179 | b9e7a234 | Andreas Färber | M68kCPUClass *mcc = M68K_CPU_CLASS(c); |
180 | b9e7a234 | Andreas Färber | CPUClass *cc = CPU_CLASS(c); |
181 | 087fe4f8 | Andreas Färber | DeviceClass *dc = DEVICE_CLASS(c); |
182 | b9e7a234 | Andreas Färber | |
183 | 6d1bbc62 | Andreas Färber | mcc->parent_realize = dc->realize; |
184 | 6d1bbc62 | Andreas Färber | dc->realize = m68k_cpu_realizefn; |
185 | 6d1bbc62 | Andreas Färber | |
186 | b9e7a234 | Andreas Färber | mcc->parent_reset = cc->reset; |
187 | b9e7a234 | Andreas Färber | cc->reset = m68k_cpu_reset; |
188 | bc5b2da3 | Andreas Färber | |
189 | bc5b2da3 | Andreas Färber | cc->class_by_name = m68k_cpu_class_by_name; |
190 | 97a8ea5a | Andreas Färber | cc->do_interrupt = m68k_cpu_do_interrupt; |
191 | 878096ee | Andreas Färber | cc->dump_state = m68k_cpu_dump_state; |
192 | e700604d | Andreas Färber | cc->set_pc = m68k_cpu_set_pc; |
193 | 5b50e790 | Andreas Färber | cc->gdb_read_register = m68k_cpu_gdb_read_register; |
194 | 5b50e790 | Andreas Färber | cc->gdb_write_register = m68k_cpu_gdb_write_register; |
195 | 00b941e5 | Andreas Färber | #ifndef CONFIG_USER_ONLY
|
196 | 00b941e5 | Andreas Färber | cc->get_phys_page_debug = m68k_cpu_get_phys_page_debug; |
197 | 00b941e5 | Andreas Färber | #endif
|
198 | 087fe4f8 | Andreas Färber | dc->vmsd = &vmstate_m68k_cpu; |
199 | a0e372f0 | Andreas Färber | cc->gdb_num_core_regs = 18;
|
200 | b9e7a234 | Andreas Färber | } |
201 | b9e7a234 | Andreas Färber | |
202 | 11150915 | Andreas Färber | static void register_cpu_type(const M68kCPUInfo *info) |
203 | 11150915 | Andreas Färber | { |
204 | 11150915 | Andreas Färber | TypeInfo type_info = { |
205 | 11150915 | Andreas Färber | .parent = TYPE_M68K_CPU, |
206 | 11150915 | Andreas Färber | .instance_init = info->instance_init, |
207 | 11150915 | Andreas Färber | }; |
208 | 11150915 | Andreas Färber | |
209 | 7a9f812b | Andreas Färber | type_info.name = g_strdup_printf("%s-" TYPE_M68K_CPU, info->name);
|
210 | 2dddbc21 | Andreas Färber | type_register(&type_info); |
211 | 7a9f812b | Andreas Färber | g_free((void *)type_info.name);
|
212 | 11150915 | Andreas Färber | } |
213 | 11150915 | Andreas Färber | |
214 | b9e7a234 | Andreas Färber | static const TypeInfo m68k_cpu_type_info = { |
215 | b9e7a234 | Andreas Färber | .name = TYPE_M68K_CPU, |
216 | b9e7a234 | Andreas Färber | .parent = TYPE_CPU, |
217 | b9e7a234 | Andreas Färber | .instance_size = sizeof(M68kCPU),
|
218 | 9b706039 | Andreas Färber | .instance_init = m68k_cpu_initfn, |
219 | 11150915 | Andreas Färber | .abstract = true,
|
220 | b9e7a234 | Andreas Färber | .class_size = sizeof(M68kCPUClass),
|
221 | b9e7a234 | Andreas Färber | .class_init = m68k_cpu_class_init, |
222 | b9e7a234 | Andreas Färber | }; |
223 | b9e7a234 | Andreas Färber | |
224 | b9e7a234 | Andreas Färber | static void m68k_cpu_register_types(void) |
225 | b9e7a234 | Andreas Färber | { |
226 | 11150915 | Andreas Färber | int i;
|
227 | 11150915 | Andreas Färber | |
228 | b9e7a234 | Andreas Färber | type_register_static(&m68k_cpu_type_info); |
229 | 11150915 | Andreas Färber | for (i = 0; i < ARRAY_SIZE(m68k_cpus); i++) { |
230 | 11150915 | Andreas Färber | register_cpu_type(&m68k_cpus[i]); |
231 | 11150915 | Andreas Färber | } |
232 | b9e7a234 | Andreas Färber | } |
233 | b9e7a234 | Andreas Färber | |
234 | b9e7a234 | Andreas Färber | type_init(m68k_cpu_register_types) |