]> Git Repo - qemu.git/blob - target-m68k/cpu.c
Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
[qemu.git] / target-m68k / cpu.c
1 /*
2  * QEMU Motorola 68k CPU
3  *
4  * Copyright (c) 2012 SUSE LINUX Products GmbH
5  *
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.
10  *
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.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see
18  * <http://www.gnu.org/licenses/lgpl-2.1.html>
19  */
20
21 #include "cpu.h"
22 #include "qemu-common.h"
23
24
25 static void m68k_set_feature(CPUM68KState *env, int feature)
26 {
27     env->features |= (1u << feature);
28 }
29
30 /* CPUClass::reset() */
31 static void m68k_cpu_reset(CPUState *s)
32 {
33     M68kCPU *cpu = M68K_CPU(s);
34     M68kCPUClass *mcc = M68K_CPU_GET_CLASS(cpu);
35     CPUM68KState *env = &cpu->env;
36
37     if (qemu_loglevel_mask(CPU_LOG_RESET)) {
38         qemu_log("CPU Reset (CPU %d)\n", s->cpu_index);
39         log_cpu_state(env, 0);
40     }
41
42     mcc->parent_reset(s);
43
44     memset(env, 0, offsetof(CPUM68KState, breakpoints));
45 #if !defined(CONFIG_USER_ONLY)
46     env->sr = 0x2700;
47 #endif
48     m68k_switch_sp(env);
49     /* ??? FP regs should be initialized to NaN.  */
50     env->cc_op = CC_OP_FLAGS;
51     /* TODO: We should set PC from the interrupt vector.  */
52     env->pc = 0;
53     tlb_flush(env, 1);
54 }
55
56 /* CPU models */
57
58 static ObjectClass *m68k_cpu_class_by_name(const char *cpu_model)
59 {
60     ObjectClass *oc;
61
62     if (cpu_model == NULL) {
63         return NULL;
64     }
65
66     oc = object_class_by_name(cpu_model);
67     if (oc != NULL && (object_class_dynamic_cast(oc, TYPE_M68K_CPU) == NULL ||
68                        object_class_is_abstract(oc))) {
69         return NULL;
70     }
71     return oc;
72 }
73
74 static void m5206_cpu_initfn(Object *obj)
75 {
76     M68kCPU *cpu = M68K_CPU(obj);
77     CPUM68KState *env = &cpu->env;
78
79     m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
80 }
81
82 static void m5208_cpu_initfn(Object *obj)
83 {
84     M68kCPU *cpu = M68K_CPU(obj);
85     CPUM68KState *env = &cpu->env;
86
87     m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
88     m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
89     m68k_set_feature(env, M68K_FEATURE_BRAL);
90     m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
91     m68k_set_feature(env, M68K_FEATURE_USP);
92 }
93
94 static void cfv4e_cpu_initfn(Object *obj)
95 {
96     M68kCPU *cpu = M68K_CPU(obj);
97     CPUM68KState *env = &cpu->env;
98
99     m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
100     m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
101     m68k_set_feature(env, M68K_FEATURE_BRAL);
102     m68k_set_feature(env, M68K_FEATURE_CF_FPU);
103     m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
104     m68k_set_feature(env, M68K_FEATURE_USP);
105 }
106
107 static void any_cpu_initfn(Object *obj)
108 {
109     M68kCPU *cpu = M68K_CPU(obj);
110     CPUM68KState *env = &cpu->env;
111
112     m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
113     m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
114     m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
115     m68k_set_feature(env, M68K_FEATURE_BRAL);
116     m68k_set_feature(env, M68K_FEATURE_CF_FPU);
117     /* MAC and EMAC are mututally exclusive, so pick EMAC.
118        It's mostly backwards compatible.  */
119     m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
120     m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
121     m68k_set_feature(env, M68K_FEATURE_USP);
122     m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
123     m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
124 }
125
126 typedef struct M68kCPUInfo {
127     const char *name;
128     void (*instance_init)(Object *obj);
129 } M68kCPUInfo;
130
131 static const M68kCPUInfo m68k_cpus[] = {
132     { .name = "m5206", .instance_init = m5206_cpu_initfn },
133     { .name = "m5208", .instance_init = m5208_cpu_initfn },
134     { .name = "cfv4e", .instance_init = cfv4e_cpu_initfn },
135     { .name = "any",   .instance_init = any_cpu_initfn },
136 };
137
138 static void m68k_cpu_initfn(Object *obj)
139 {
140     M68kCPU *cpu = M68K_CPU(obj);
141     CPUM68KState *env = &cpu->env;
142
143     cpu_exec_init(env);
144 }
145
146 static void m68k_cpu_class_init(ObjectClass *c, void *data)
147 {
148     M68kCPUClass *mcc = M68K_CPU_CLASS(c);
149     CPUClass *cc = CPU_CLASS(c);
150
151     mcc->parent_reset = cc->reset;
152     cc->reset = m68k_cpu_reset;
153
154     cc->class_by_name = m68k_cpu_class_by_name;
155 }
156
157 static void register_cpu_type(const M68kCPUInfo *info)
158 {
159     TypeInfo type_info = {
160         .name = info->name,
161         .parent = TYPE_M68K_CPU,
162         .instance_init = info->instance_init,
163     };
164
165     type_register(&type_info);
166 }
167
168 static const TypeInfo m68k_cpu_type_info = {
169     .name = TYPE_M68K_CPU,
170     .parent = TYPE_CPU,
171     .instance_size = sizeof(M68kCPU),
172     .instance_init = m68k_cpu_initfn,
173     .abstract = true,
174     .class_size = sizeof(M68kCPUClass),
175     .class_init = m68k_cpu_class_init,
176 };
177
178 static void m68k_cpu_register_types(void)
179 {
180     int i;
181
182     type_register_static(&m68k_cpu_type_info);
183     for (i = 0; i < ARRAY_SIZE(m68k_cpus); i++) {
184         register_cpu_type(&m68k_cpus[i]);
185     }
186 }
187
188 type_init(m68k_cpu_register_types)
This page took 0.036682 seconds and 4 git commands to generate.