1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
26static inline void set_feature(CPUTriCoreState *env, int feature)
27{
28 env->features |= 1ULL << feature;
29}
30
31static gchar *tricore_gdb_arch_name(CPUState *cs)
32{
33 return g_strdup("tricore");
34}
35
36static 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
44static vaddr tricore_cpu_get_pc(CPUState *cs)
45{
46 TriCoreCPU *cpu = TRICORE_CPU(cs);
47 CPUTriCoreState *env = &cpu->env;
48
49 return env->PC;
50}
51
52static void tricore_cpu_synchronize_from_tb(CPUState *cs,
53 const TranslationBlock *tb)
54{
55 TriCoreCPU *cpu = TRICORE_CPU(cs);
56 CPUTriCoreState *env = &cpu->env;
57
58 tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
59 env->PC = tb->pc;
60}
61
62static void tricore_restore_state_to_opc(CPUState *cs,
63 const TranslationBlock *tb,
64 const uint64_t *data)
65{
66 TriCoreCPU *cpu = TRICORE_CPU(cs);
67 CPUTriCoreState *env = &cpu->env;
68
69 env->PC = data[0];
70}
71
72static void tricore_cpu_reset_hold(Object *obj)
73{
74 CPUState *s = CPU(obj);
75 TriCoreCPU *cpu = TRICORE_CPU(s);
76 TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(cpu);
77 CPUTriCoreState *env = &cpu->env;
78
79 if (tcc->parent_phases.hold) {
80 tcc->parent_phases.hold(obj);
81 }
82
83 cpu_state_reset(env);
84}
85
86static bool tricore_cpu_has_work(CPUState *cs)
87{
88 return true;
89}
90
91static void tricore_cpu_realizefn(DeviceState *dev, Error **errp)
92{
93 CPUState *cs = CPU(dev);
94 TriCoreCPU *cpu = TRICORE_CPU(dev);
95 TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(dev);
96 CPUTriCoreState *env = &cpu->env;
97 Error *local_err = NULL;
98
99 cpu_exec_realizefn(cs, &local_err);
100 if (local_err != NULL) {
101 error_propagate(errp, local_err);
102 return;
103 }
104
105
106 if (tricore_feature(env, TRICORE_FEATURE_161)) {
107 set_feature(env, TRICORE_FEATURE_16);
108 }
109
110 if (tricore_feature(env, TRICORE_FEATURE_16)) {
111 set_feature(env, TRICORE_FEATURE_131);
112 }
113 if (tricore_feature(env, TRICORE_FEATURE_131)) {
114 set_feature(env, TRICORE_FEATURE_13);
115 }
116 cpu_reset(cs);
117 qemu_init_vcpu(cs);
118
119 tcc->parent_realize(dev, errp);
120}
121
122
123static void tricore_cpu_initfn(Object *obj)
124{
125 TriCoreCPU *cpu = TRICORE_CPU(obj);
126
127 cpu_set_cpustate_pointers(cpu);
128}
129
130static ObjectClass *tricore_cpu_class_by_name(const char *cpu_model)
131{
132 ObjectClass *oc;
133 char *typename;
134
135 typename = g_strdup_printf(TRICORE_CPU_TYPE_NAME("%s"), cpu_model);
136 oc = object_class_by_name(typename);
137 g_free(typename);
138 if (!oc || !object_class_dynamic_cast(oc, TYPE_TRICORE_CPU) ||
139 object_class_is_abstract(oc)) {
140 return NULL;
141 }
142 return oc;
143}
144
145static void tc1796_initfn(Object *obj)
146{
147 TriCoreCPU *cpu = TRICORE_CPU(obj);
148
149 set_feature(&cpu->env, TRICORE_FEATURE_13);
150}
151
152static void tc1797_initfn(Object *obj)
153{
154 TriCoreCPU *cpu = TRICORE_CPU(obj);
155
156 set_feature(&cpu->env, TRICORE_FEATURE_131);
157}
158
159static void tc27x_initfn(Object *obj)
160{
161 TriCoreCPU *cpu = TRICORE_CPU(obj);
162
163 set_feature(&cpu->env, TRICORE_FEATURE_161);
164}
165
166#include "hw/core/sysemu-cpu-ops.h"
167
168static const struct SysemuCPUOps tricore_sysemu_ops = {
169 .get_phys_page_debug = tricore_cpu_get_phys_page_debug,
170};
171
172#include "hw/core/tcg-cpu-ops.h"
173
174static const struct TCGCPUOps tricore_tcg_ops = {
175 .initialize = tricore_tcg_init,
176 .synchronize_from_tb = tricore_cpu_synchronize_from_tb,
177 .restore_state_to_opc = tricore_restore_state_to_opc,
178 .tlb_fill = tricore_cpu_tlb_fill,
179};
180
181static void tricore_cpu_class_init(ObjectClass *c, void *data)
182{
183 TriCoreCPUClass *mcc = TRICORE_CPU_CLASS(c);
184 CPUClass *cc = CPU_CLASS(c);
185 DeviceClass *dc = DEVICE_CLASS(c);
186 ResettableClass *rc = RESETTABLE_CLASS(c);
187
188 device_class_set_parent_realize(dc, tricore_cpu_realizefn,
189 &mcc->parent_realize);
190
191 resettable_class_set_parent_phases(rc, NULL, tricore_cpu_reset_hold, NULL,
192 &mcc->parent_phases);
193 cc->class_by_name = tricore_cpu_class_by_name;
194 cc->has_work = tricore_cpu_has_work;
195
196 cc->gdb_read_register = tricore_cpu_gdb_read_register;
197 cc->gdb_write_register = tricore_cpu_gdb_write_register;
198 cc->gdb_num_core_regs = 44;
199 cc->gdb_arch_name = tricore_gdb_arch_name;
200
201 cc->dump_state = tricore_cpu_dump_state;
202 cc->set_pc = tricore_cpu_set_pc;
203 cc->get_pc = tricore_cpu_get_pc;
204 cc->sysemu_ops = &tricore_sysemu_ops;
205 cc->tcg_ops = &tricore_tcg_ops;
206}
207
208#define DEFINE_TRICORE_CPU_TYPE(cpu_model, initfn) \
209 { \
210 .parent = TYPE_TRICORE_CPU, \
211 .instance_init = initfn, \
212 .name = TRICORE_CPU_TYPE_NAME(cpu_model), \
213 }
214
215static const TypeInfo tricore_cpu_type_infos[] = {
216 {
217 .name = TYPE_TRICORE_CPU,
218 .parent = TYPE_CPU,
219 .instance_size = sizeof(TriCoreCPU),
220 .instance_init = tricore_cpu_initfn,
221 .abstract = true,
222 .class_size = sizeof(TriCoreCPUClass),
223 .class_init = tricore_cpu_class_init,
224 },
225 DEFINE_TRICORE_CPU_TYPE("tc1796", tc1796_initfn),
226 DEFINE_TRICORE_CPU_TYPE("tc1797", tc1797_initfn),
227 DEFINE_TRICORE_CPU_TYPE("tc27x", tc27x_initfn),
228};
229
230DEFINE_TYPES(tricore_cpu_type_infos)
231