xref: /qemu/target/tricore/cpu.c (revision abff1abf)
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                                             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 static void tricore_cpu_class_init(ObjectClass *c, void *data)
146 {
147     TriCoreCPUClass *mcc = TRICORE_CPU_CLASS(c);
148     CPUClass *cc = CPU_CLASS(c);
149     DeviceClass *dc = DEVICE_CLASS(c);
150 
151     device_class_set_parent_realize(dc, tricore_cpu_realizefn,
152                                     &mcc->parent_realize);
153 
154     device_class_set_parent_reset(dc, tricore_cpu_reset, &mcc->parent_reset);
155     cc->class_by_name = tricore_cpu_class_by_name;
156     cc->has_work = tricore_cpu_has_work;
157 
158     cc->gdb_read_register = tricore_cpu_gdb_read_register;
159     cc->gdb_write_register = tricore_cpu_gdb_write_register;
160     cc->gdb_num_core_regs = 44;
161     cc->gdb_arch_name = tricore_gdb_arch_name;
162 
163     cc->dump_state = tricore_cpu_dump_state;
164     cc->set_pc = tricore_cpu_set_pc;
165     cc->synchronize_from_tb = tricore_cpu_synchronize_from_tb;
166     cc->get_phys_page_debug = tricore_cpu_get_phys_page_debug;
167     cc->tcg_initialize = tricore_tcg_init;
168     cc->tlb_fill = tricore_cpu_tlb_fill;
169 }
170 
171 #define DEFINE_TRICORE_CPU_TYPE(cpu_model, initfn) \
172     {                                              \
173         .parent = TYPE_TRICORE_CPU,                \
174         .instance_init = initfn,                   \
175         .name = TRICORE_CPU_TYPE_NAME(cpu_model),  \
176     }
177 
178 static const TypeInfo tricore_cpu_type_infos[] = {
179     {
180         .name = TYPE_TRICORE_CPU,
181         .parent = TYPE_CPU,
182         .instance_size = sizeof(TriCoreCPU),
183         .instance_init = tricore_cpu_initfn,
184         .abstract = true,
185         .class_size = sizeof(TriCoreCPUClass),
186         .class_init = tricore_cpu_class_init,
187     },
188     DEFINE_TRICORE_CPU_TYPE("tc1796", tc1796_initfn),
189     DEFINE_TRICORE_CPU_TYPE("tc1797", tc1797_initfn),
190     DEFINE_TRICORE_CPU_TYPE("tc27x", tc27x_initfn),
191 };
192 
193 DEFINE_TYPES(tricore_cpu_type_infos)
194