master
c 279 lines 8.02 KB
Raw
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/translation-block.h"
24 #include "qemu/error-report.h"
25 #include "tcg/debug-assert.h"
26 #include "accel/tcg/cpu-ops.h"
27 #include "disas/capstone.h"
28
29 static inline void set_feature(CPUTriCoreState *env, int feature)
30 {
31 env->features |= 1ULL << feature;
32 }
33
34 static const gchar *tricore_gdb_arch_name(CPUState *cs)
35 {
36 return "tricore";
37 }
38
39 static void tricore_disas_set_info(const CPUState *cpu, disassemble_info *info)
40 {
41 CPUTriCoreState *env = cpu_env((CPUState *)cpu);
42
43 info->endian = BFD_ENDIAN_LITTLE;
44 info->cap_arch = CS_ARCH_TRICORE;
45 info->cap_insn_unit = 4;
46 info->cap_insn_split = 4;
47
48 /*
49 * Possible capstone bug: the isa levels are not additive.
50 * Work around by settiing only one.
51 * Note that TriCore 1.3.0 is the earliest we support.
52 */
53 if (tricore_has_feature(env, TRICORE_FEATURE_162)) {
54 info->cap_mode = CS_MODE_TRICORE_162;
55 } else if (tricore_has_feature(env, TRICORE_FEATURE_161)) {
56 info->cap_mode = CS_MODE_TRICORE_161;
57 } else if (tricore_has_feature(env, TRICORE_FEATURE_16)) {
58 info->cap_mode = CS_MODE_TRICORE_160;
59 } else if (tricore_has_feature(env, TRICORE_FEATURE_131)) {
60 info->cap_mode = CS_MODE_TRICORE_131;
61 } else if (tricore_has_feature(env, TRICORE_FEATURE_13)) {
62 info->cap_mode = CS_MODE_TRICORE_130;
63 } else {
64 g_assert_not_reached();
65 }
66 }
67
68 static void tricore_cpu_set_pc(CPUState *cs, vaddr value)
69 {
70 cpu_env(cs)->PC = value & ~1;
71 }
72
73 static vaddr tricore_cpu_get_pc(CPUState *cs)
74 {
75 return cpu_env(cs)->PC;
76 }
77
78 static TCGTBCPUState tricore_get_tb_cpu_state(CPUState *cs)
79 {
80 CPUTriCoreState *env = cpu_env(cs);
81
82 return (TCGTBCPUState){
83 .pc = env->PC,
84 .flags = FIELD_DP32(0, TB_FLAGS, PRIV, extract32(env->PSW, 10, 2)),
85 };
86 }
87
88 static void tricore_cpu_synchronize_from_tb(CPUState *cs,
89 const TranslationBlock *tb)
90 {
91 tcg_debug_assert(!tcg_cflags_has(cs, CF_PCREL));
92 cpu_env(cs)->PC = tb->pc;
93 }
94
95 static void tricore_restore_state_to_opc(CPUState *cs,
96 const TranslationBlock *tb,
97 const uint64_t *data)
98 {
99 cpu_env(cs)->PC = data[0];
100 }
101
102 static void tricore_cpu_reset_hold(Object *obj, ResetType type)
103 {
104 CPUState *cs = CPU(obj);
105 TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(obj);
106
107 if (tcc->parent_phases.hold) {
108 tcc->parent_phases.hold(obj, type);
109 }
110
111 cpu_state_reset(cpu_env(cs));
112 }
113
114 static bool tricore_cpu_has_work(CPUState *cs)
115 {
116 return true;
117 }
118
119 static int tricore_cpu_mmu_index(CPUState *cs, bool ifetch)
120 {
121 return 0;
122 }
123
124 static void tricore_cpu_realizefn(DeviceState *dev, Error **errp)
125 {
126 CPUState *cs = CPU(dev);
127 TriCoreCPU *cpu = TRICORE_CPU(dev);
128 TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(dev);
129 CPUTriCoreState *env = &cpu->env;
130 Error *local_err = NULL;
131
132 cpu_common_realize(cs, &local_err);
133 if (local_err != NULL) {
134 error_propagate(errp, local_err);
135 return;
136 }
137
138 /* Some features automatically imply others */
139 if (tricore_has_feature(env, TRICORE_FEATURE_162)) {
140 set_feature(env, TRICORE_FEATURE_161);
141 }
142
143 if (tricore_has_feature(env, TRICORE_FEATURE_161)) {
144 set_feature(env, TRICORE_FEATURE_16);
145 }
146
147 if (tricore_has_feature(env, TRICORE_FEATURE_16)) {
148 set_feature(env, TRICORE_FEATURE_131);
149 }
150 if (tricore_has_feature(env, TRICORE_FEATURE_131)) {
151 set_feature(env, TRICORE_FEATURE_13);
152 }
153 cpu_reset(cs);
154 qemu_init_vcpu(cs);
155
156 tcc->parent_realize(dev, errp);
157 }
158
159 static ObjectClass *tricore_cpu_class_by_name(const char *cpu_model)
160 {
161 ObjectClass *oc;
162 char *typename;
163
164 typename = g_strdup_printf(TRICORE_CPU_TYPE_NAME("%s"), cpu_model);
165 oc = object_class_by_name(typename);
166 g_free(typename);
167
168 return oc;
169 }
170
171 static void tc1796_initfn(Object *obj)
172 {
173 TriCoreCPU *cpu = TRICORE_CPU(obj);
174
175 set_feature(&cpu->env, TRICORE_FEATURE_13);
176 }
177
178 static void tc1797_initfn(Object *obj)
179 {
180 TriCoreCPU *cpu = TRICORE_CPU(obj);
181
182 set_feature(&cpu->env, TRICORE_FEATURE_131);
183 }
184
185 static void tc27x_initfn(Object *obj)
186 {
187 TriCoreCPU *cpu = TRICORE_CPU(obj);
188
189 set_feature(&cpu->env, TRICORE_FEATURE_161);
190 }
191
192 static void tc37x_initfn(Object *obj)
193 {
194 TriCoreCPU *cpu = TRICORE_CPU(obj);
195
196 set_feature(&cpu->env, TRICORE_FEATURE_162);
197 }
198
199 static bool tricore_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
200 {
201 /* Interrupts are not implemented */
202 return false;
203 }
204
205 #include "hw/core/sysemu-cpu-ops.h"
206
207 static const struct SysemuCPUOps tricore_sysemu_ops = {
208 .has_work = tricore_cpu_has_work,
209 .get_phys_addr_debug = tricore_cpu_get_phys_addr_debug,
210 };
211
212 static const TCGCPUOps tricore_tcg_ops = {
213 /* MTTCG not yet supported: require strict ordering */
214 .guest_default_memory_order = TCG_MO_ALL,
215 .mttcg_supported = false,
216 .initialize = tricore_tcg_init,
217 .translate_code = tricore_translate_code,
218 .get_tb_cpu_state = tricore_get_tb_cpu_state,
219 .synchronize_from_tb = tricore_cpu_synchronize_from_tb,
220 .restore_state_to_opc = tricore_restore_state_to_opc,
221 .mmu_index = tricore_cpu_mmu_index,
222 .tlb_fill = tricore_cpu_tlb_fill,
223 .pointer_wrap = cpu_pointer_wrap_uint32,
224 .cpu_exec_interrupt = tricore_cpu_exec_interrupt,
225 .cpu_exec_halt = tricore_cpu_has_work,
226 .cpu_exec_reset = cpu_reset,
227 };
228
229 static void tricore_cpu_class_init(ObjectClass *c, const void *data)
230 {
231 TriCoreCPUClass *mcc = TRICORE_CPU_CLASS(c);
232 CPUClass *cc = CPU_CLASS(c);
233 DeviceClass *dc = DEVICE_CLASS(c);
234 ResettableClass *rc = RESETTABLE_CLASS(c);
235
236 device_class_set_parent_realize(dc, tricore_cpu_realizefn,
237 &mcc->parent_realize);
238
239 resettable_class_set_parent_phases(rc, NULL, tricore_cpu_reset_hold, NULL,
240 &mcc->parent_phases);
241 cc->class_by_name = tricore_cpu_class_by_name;
242
243 cc->gdb_read_register = tricore_cpu_gdb_read_register;
244 cc->gdb_write_register = tricore_cpu_gdb_write_register;
245 cc->gdb_num_core_regs = 44;
246 cc->gdb_arch_name = tricore_gdb_arch_name;
247 cc->disas_set_info = tricore_disas_set_info;
248
249 cc->dump_state = tricore_cpu_dump_state;
250 cc->set_pc = tricore_cpu_set_pc;
251 cc->get_pc = tricore_cpu_get_pc;
252 cc->sysemu_ops = &tricore_sysemu_ops;
253 cc->tcg_ops = &tricore_tcg_ops;
254 }
255
256 #define DEFINE_TRICORE_CPU_TYPE(cpu_model, initfn) \
257 { \
258 .parent = TYPE_TRICORE_CPU, \
259 .instance_init = initfn, \
260 .name = TRICORE_CPU_TYPE_NAME(cpu_model), \
261 }
262
263 static const TypeInfo tricore_cpu_type_infos[] = {
264 {
265 .name = TYPE_TRICORE_CPU,
266 .parent = TYPE_CPU,
267 .instance_size = sizeof(TriCoreCPU),
268 .instance_align = __alignof(TriCoreCPU),
269 .abstract = true,
270 .class_size = sizeof(TriCoreCPUClass),
271 .class_init = tricore_cpu_class_init,
272 },
273 DEFINE_TRICORE_CPU_TYPE("tc1796", tc1796_initfn),
274 DEFINE_TRICORE_CPU_TYPE("tc1797", tc1797_initfn),
275 DEFINE_TRICORE_CPU_TYPE("tc27x", tc27x_initfn),
276 DEFINE_TRICORE_CPU_TYPE("tc37x", tc37x_initfn),
277 };
278
279 DEFINE_TYPES(tricore_cpu_type_infos)