xref: /openbmc/qemu/target/tricore/cpu.c (revision f6476697)
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.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 <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "qemu/osdep.h"
21 #include "qapi/error.h"
22 #include "cpu.h"
23 #include "exec/exec-all.h"
24 #include "qemu/error-report.h"
25 
26 static inline void set_feature(CPUTriCoreState *env, int feature)
27 {
28     env->features |= 1ULL << feature;
29 }
30 
31 static gchar *tricore_gdb_arch_name(CPUState *cs)
32 {
33     return g_strdup("tricore");
34 }
35 
36 static void tricore_cpu_set_pc(CPUState *cs, vaddr value)
37 {
38     TriCoreCPU *cpu = TRICORE_CPU(cs);
39     CPUTriCoreState *env = &cpu->env;
40 
41     env->PC = value & ~(target_ulong)1;
42 }
43 
44 static void tricore_cpu_synchronize_from_tb(CPUState *cs,
45                                             const TranslationBlock *tb)
46 {
47     TriCoreCPU *cpu = TRICORE_CPU(cs);
48     CPUTriCoreState *env = &cpu->env;
49 
50     env->PC = tb->pc;
51 }
52 
53 static void tricore_cpu_reset(DeviceState *dev)
54 {
55     CPUState *s = CPU(dev);
56     TriCoreCPU *cpu = TRICORE_CPU(s);
57     TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(cpu);
58     CPUTriCoreState *env = &cpu->env;
59 
60     tcc->parent_reset(dev);
61 
62     cpu_state_reset(env);
63 }
64 
65 static bool tricore_cpu_has_work(CPUState *cs)
66 {
67     return true;
68 }
69 
70 static void tricore_cpu_realizefn(DeviceState *dev, Error **errp)
71 {
72     CPUState *cs = CPU(dev);
73     TriCoreCPU *cpu = TRICORE_CPU(dev);
74     TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(dev);
75     CPUTriCoreState *env = &cpu->env;
76     Error *local_err = NULL;
77 
78     cpu_exec_realizefn(cs, &local_err);
79     if (local_err != NULL) {
80         error_propagate(errp, local_err);
81         return;
82     }
83 
84     /* Some features automatically imply others */
85     if (tricore_feature(env, TRICORE_FEATURE_161)) {
86         set_feature(env, TRICORE_FEATURE_16);
87     }
88 
89     if (tricore_feature(env, TRICORE_FEATURE_16)) {
90         set_feature(env, TRICORE_FEATURE_131);
91     }
92     if (tricore_feature(env, TRICORE_FEATURE_131)) {
93         set_feature(env, TRICORE_FEATURE_13);
94     }
95     cpu_reset(cs);
96     qemu_init_vcpu(cs);
97 
98     tcc->parent_realize(dev, errp);
99 }
100 
101 
102 static void tricore_cpu_initfn(Object *obj)
103 {
104     TriCoreCPU *cpu = TRICORE_CPU(obj);
105 
106     cpu_set_cpustate_pointers(cpu);
107 }
108 
109 static ObjectClass *tricore_cpu_class_by_name(const char *cpu_model)
110 {
111     ObjectClass *oc;
112     char *typename;
113 
114     typename = g_strdup_printf(TRICORE_CPU_TYPE_NAME("%s"), cpu_model);
115     oc = object_class_by_name(typename);
116     g_free(typename);
117     if (!oc || !object_class_dynamic_cast(oc, TYPE_TRICORE_CPU) ||
118         object_class_is_abstract(oc)) {
119         return NULL;
120     }
121     return oc;
122 }
123 
124 static void tc1796_initfn(Object *obj)
125 {
126     TriCoreCPU *cpu = TRICORE_CPU(obj);
127 
128     set_feature(&cpu->env, TRICORE_FEATURE_13);
129 }
130 
131 static void tc1797_initfn(Object *obj)
132 {
133     TriCoreCPU *cpu = TRICORE_CPU(obj);
134 
135     set_feature(&cpu->env, TRICORE_FEATURE_131);
136 }
137 
138 static void tc27x_initfn(Object *obj)
139 {
140     TriCoreCPU *cpu = TRICORE_CPU(obj);
141 
142     set_feature(&cpu->env, TRICORE_FEATURE_161);
143 }
144 
145 #include "hw/core/sysemu-cpu-ops.h"
146 
147 static const struct SysemuCPUOps tricore_sysemu_ops = {
148     .get_phys_page_debug = tricore_cpu_get_phys_page_debug,
149 };
150 
151 #include "hw/core/tcg-cpu-ops.h"
152 
153 static const struct TCGCPUOps tricore_tcg_ops = {
154     .initialize = tricore_tcg_init,
155     .synchronize_from_tb = tricore_cpu_synchronize_from_tb,
156     .tlb_fill = tricore_cpu_tlb_fill,
157 };
158 
159 static void tricore_cpu_class_init(ObjectClass *c, void *data)
160 {
161     TriCoreCPUClass *mcc = TRICORE_CPU_CLASS(c);
162     CPUClass *cc = CPU_CLASS(c);
163     DeviceClass *dc = DEVICE_CLASS(c);
164 
165     device_class_set_parent_realize(dc, tricore_cpu_realizefn,
166                                     &mcc->parent_realize);
167 
168     device_class_set_parent_reset(dc, tricore_cpu_reset, &mcc->parent_reset);
169     cc->class_by_name = tricore_cpu_class_by_name;
170     cc->has_work = tricore_cpu_has_work;
171 
172     cc->gdb_read_register = tricore_cpu_gdb_read_register;
173     cc->gdb_write_register = tricore_cpu_gdb_write_register;
174     cc->gdb_num_core_regs = 44;
175     cc->gdb_arch_name = tricore_gdb_arch_name;
176 
177     cc->dump_state = tricore_cpu_dump_state;
178     cc->set_pc = tricore_cpu_set_pc;
179     cc->sysemu_ops = &tricore_sysemu_ops;
180     cc->tcg_ops = &tricore_tcg_ops;
181 }
182 
183 #define DEFINE_TRICORE_CPU_TYPE(cpu_model, initfn) \
184     {                                              \
185         .parent = TYPE_TRICORE_CPU,                \
186         .instance_init = initfn,                   \
187         .name = TRICORE_CPU_TYPE_NAME(cpu_model),  \
188     }
189 
190 static const TypeInfo tricore_cpu_type_infos[] = {
191     {
192         .name = TYPE_TRICORE_CPU,
193         .parent = TYPE_CPU,
194         .instance_size = sizeof(TriCoreCPU),
195         .instance_init = tricore_cpu_initfn,
196         .abstract = true,
197         .class_size = sizeof(TriCoreCPUClass),
198         .class_init = tricore_cpu_class_init,
199     },
200     DEFINE_TRICORE_CPU_TYPE("tc1796", tc1796_initfn),
201     DEFINE_TRICORE_CPU_TYPE("tc1797", tc1797_initfn),
202     DEFINE_TRICORE_CPU_TYPE("tc27x", tc27x_initfn),
203 };
204 
205 DEFINE_TYPES(tricore_cpu_type_infos)
206