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