Add qemu 2.4.0
[kvmfornfv.git] / qemu / target-tricore / cpu.c
1 /*
2  *  TriCore emulation for qemu: main translation routines.
3  *
4  *  Copyright (c) 2012-2014 Bastian Koppelmann C-Lab/University Paderborn
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 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 <http://www.gnu.org/licenses/>.
18  */
19
20 #include "cpu.h"
21 #include "qemu-common.h"
22
23 static inline void set_feature(CPUTriCoreState *env, int feature)
24 {
25     env->features |= 1ULL << feature;
26 }
27
28 static void tricore_cpu_set_pc(CPUState *cs, vaddr value)
29 {
30     TriCoreCPU *cpu = TRICORE_CPU(cs);
31     CPUTriCoreState *env = &cpu->env;
32
33     env->PC = value & ~(target_ulong)1;
34 }
35
36 static void tricore_cpu_synchronize_from_tb(CPUState *cs,
37                                             TranslationBlock *tb)
38 {
39     TriCoreCPU *cpu = TRICORE_CPU(cs);
40     CPUTriCoreState *env = &cpu->env;
41
42     env->PC = tb->pc;
43 }
44
45 static void tricore_cpu_reset(CPUState *s)
46 {
47     TriCoreCPU *cpu = TRICORE_CPU(s);
48     TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(cpu);
49     CPUTriCoreState *env = &cpu->env;
50
51     tcc->parent_reset(s);
52
53     tlb_flush(s, 1);
54
55     cpu_state_reset(env);
56 }
57
58 static bool tricore_cpu_has_work(CPUState *cs)
59 {
60     return true;
61 }
62
63 static void tricore_cpu_realizefn(DeviceState *dev, Error **errp)
64 {
65     CPUState *cs = CPU(dev);
66     TriCoreCPU *cpu = TRICORE_CPU(dev);
67     TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(dev);
68     CPUTriCoreState *env = &cpu->env;
69
70     /* Some features automatically imply others */
71     if (tricore_feature(env, TRICORE_FEATURE_161)) {
72         set_feature(env, TRICORE_FEATURE_16);
73     }
74
75     if (tricore_feature(env, TRICORE_FEATURE_16)) {
76         set_feature(env, TRICORE_FEATURE_131);
77     }
78     if (tricore_feature(env, TRICORE_FEATURE_131)) {
79         set_feature(env, TRICORE_FEATURE_13);
80     }
81     cpu_reset(cs);
82     qemu_init_vcpu(cs);
83
84     tcc->parent_realize(dev, errp);
85 }
86
87
88 static void tricore_cpu_initfn(Object *obj)
89 {
90     CPUState *cs = CPU(obj);
91     TriCoreCPU *cpu = TRICORE_CPU(obj);
92     CPUTriCoreState *env = &cpu->env;
93
94     cs->env_ptr = env;
95     cpu_exec_init(cs, &error_abort);
96
97     if (tcg_enabled()) {
98         tricore_tcg_init();
99     }
100 }
101
102 static ObjectClass *tricore_cpu_class_by_name(const char *cpu_model)
103 {
104     ObjectClass *oc;
105     char *typename;
106
107     if (!cpu_model) {
108         return NULL;
109     }
110
111     typename = g_strdup_printf("%s-" TYPE_TRICORE_CPU, cpu_model);
112     oc = object_class_by_name(typename);
113     g_free(typename);
114     if (!oc || !object_class_dynamic_cast(oc, TYPE_TRICORE_CPU) ||
115         object_class_is_abstract(oc)) {
116         return NULL;
117     }
118     return oc;
119 }
120
121 static void tc1796_initfn(Object *obj)
122 {
123     TriCoreCPU *cpu = TRICORE_CPU(obj);
124
125     set_feature(&cpu->env, TRICORE_FEATURE_13);
126 }
127
128 static void tc1797_initfn(Object *obj)
129 {
130     TriCoreCPU *cpu = TRICORE_CPU(obj);
131
132     set_feature(&cpu->env, TRICORE_FEATURE_131);
133 }
134
135 static void tc27x_initfn(Object *obj)
136 {
137     TriCoreCPU *cpu = TRICORE_CPU(obj);
138
139     set_feature(&cpu->env, TRICORE_FEATURE_161);
140 }
141
142 typedef struct TriCoreCPUInfo {
143     const char *name;
144     void (*initfn)(Object *obj);
145     void (*class_init)(ObjectClass *oc, void *data);
146 } TriCoreCPUInfo;
147
148 static const TriCoreCPUInfo tricore_cpus[] = {
149     { .name = "tc1796",      .initfn = tc1796_initfn },
150     { .name = "tc1797",      .initfn = tc1797_initfn },
151     { .name = "tc27x",       .initfn = tc27x_initfn },
152     { .name = NULL }
153 };
154
155 static void tricore_cpu_class_init(ObjectClass *c, void *data)
156 {
157     TriCoreCPUClass *mcc = TRICORE_CPU_CLASS(c);
158     CPUClass *cc = CPU_CLASS(c);
159     DeviceClass *dc = DEVICE_CLASS(c);
160
161     mcc->parent_realize = dc->realize;
162     dc->realize = tricore_cpu_realizefn;
163
164     mcc->parent_reset = cc->reset;
165     cc->reset = tricore_cpu_reset;
166     cc->class_by_name = tricore_cpu_class_by_name;
167     cc->has_work = tricore_cpu_has_work;
168
169     cc->dump_state = tricore_cpu_dump_state;
170     cc->set_pc = tricore_cpu_set_pc;
171     cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb;
172
173 }
174
175 static void cpu_register(const TriCoreCPUInfo *info)
176 {
177     TypeInfo type_info = {
178         .parent = TYPE_TRICORE_CPU,
179         .instance_size = sizeof(TriCoreCPU),
180         .instance_init = info->initfn,
181         .class_size = sizeof(TriCoreCPUClass),
182         .class_init = info->class_init,
183     };
184
185     type_info.name = g_strdup_printf("%s-" TYPE_TRICORE_CPU, info->name);
186     type_register(&type_info);
187     g_free((void *)type_info.name);
188 }
189
190 static const TypeInfo tricore_cpu_type_info = {
191     .name = TYPE_TRICORE_CPU,
192     .parent = TYPE_CPU,
193     .instance_size = sizeof(TriCoreCPU),
194     .instance_init = tricore_cpu_initfn,
195     .abstract = true,
196     .class_size = sizeof(TriCoreCPUClass),
197     .class_init = tricore_cpu_class_init,
198 };
199
200 static void tricore_cpu_register_types(void)
201 {
202     const TriCoreCPUInfo *info = tricore_cpus;
203
204     type_register_static(&tricore_cpu_type_info);
205
206     while (info->name) {
207         cpu_register(info);
208         info++;
209     }
210 }
211
212 type_init(tricore_cpu_register_types)