xref: /openbmc/qemu/target/hexagon/cpu.c (revision ab85156d)
145183ccdSTaylor Simpson /*
245183ccdSTaylor Simpson  *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
345183ccdSTaylor Simpson  *
445183ccdSTaylor Simpson  *  This program is free software; you can redistribute it and/or modify
545183ccdSTaylor Simpson  *  it under the terms of the GNU General Public License as published by
645183ccdSTaylor Simpson  *  the Free Software Foundation; either version 2 of the License, or
745183ccdSTaylor Simpson  *  (at your option) any later version.
845183ccdSTaylor Simpson  *
945183ccdSTaylor Simpson  *  This program is distributed in the hope that it will be useful,
1045183ccdSTaylor Simpson  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
1145183ccdSTaylor Simpson  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1245183ccdSTaylor Simpson  *  GNU General Public License for more details.
1345183ccdSTaylor Simpson  *
1445183ccdSTaylor Simpson  *  You should have received a copy of the GNU General Public License
1545183ccdSTaylor Simpson  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
1645183ccdSTaylor Simpson  */
1745183ccdSTaylor Simpson 
1845183ccdSTaylor Simpson #include "qemu/osdep.h"
1945183ccdSTaylor Simpson #include "qemu/qemu-print.h"
2045183ccdSTaylor Simpson #include "cpu.h"
2145183ccdSTaylor Simpson #include "internal.h"
2245183ccdSTaylor Simpson #include "exec/exec-all.h"
2345183ccdSTaylor Simpson #include "qapi/error.h"
2445183ccdSTaylor Simpson #include "hw/qdev-properties.h"
25c0336c87STaylor Simpson #include "fpu/softfloat-helpers.h"
2645183ccdSTaylor Simpson 
2745183ccdSTaylor Simpson static void hexagon_v67_cpu_init(Object *obj)
2845183ccdSTaylor Simpson {
2945183ccdSTaylor Simpson }
3045183ccdSTaylor Simpson 
3145183ccdSTaylor Simpson static ObjectClass *hexagon_cpu_class_by_name(const char *cpu_model)
3245183ccdSTaylor Simpson {
3345183ccdSTaylor Simpson     ObjectClass *oc;
3445183ccdSTaylor Simpson     char *typename;
3545183ccdSTaylor Simpson     char **cpuname;
3645183ccdSTaylor Simpson 
3745183ccdSTaylor Simpson     cpuname = g_strsplit(cpu_model, ",", 1);
3845183ccdSTaylor Simpson     typename = g_strdup_printf(HEXAGON_CPU_TYPE_NAME("%s"), cpuname[0]);
3945183ccdSTaylor Simpson     oc = object_class_by_name(typename);
4045183ccdSTaylor Simpson     g_strfreev(cpuname);
4145183ccdSTaylor Simpson     g_free(typename);
4245183ccdSTaylor Simpson     if (!oc || !object_class_dynamic_cast(oc, TYPE_HEXAGON_CPU) ||
4345183ccdSTaylor Simpson         object_class_is_abstract(oc)) {
4445183ccdSTaylor Simpson         return NULL;
4545183ccdSTaylor Simpson     }
4645183ccdSTaylor Simpson     return oc;
4745183ccdSTaylor Simpson }
4845183ccdSTaylor Simpson 
4945183ccdSTaylor Simpson static Property hexagon_lldb_compat_property =
5045183ccdSTaylor Simpson     DEFINE_PROP_BOOL("lldb-compat", HexagonCPU, lldb_compat, false);
5145183ccdSTaylor Simpson static Property hexagon_lldb_stack_adjust_property =
5245183ccdSTaylor Simpson     DEFINE_PROP_UNSIGNED("lldb-stack-adjust", HexagonCPU, lldb_stack_adjust,
5345183ccdSTaylor Simpson                          0, qdev_prop_uint32, target_ulong);
5445183ccdSTaylor Simpson 
5545183ccdSTaylor Simpson const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS] = {
5645183ccdSTaylor Simpson    "r0", "r1",  "r2",  "r3",  "r4",   "r5",  "r6",  "r7",
5745183ccdSTaylor Simpson    "r8", "r9",  "r10", "r11", "r12",  "r13", "r14", "r15",
5845183ccdSTaylor Simpson   "r16", "r17", "r18", "r19", "r20",  "r21", "r22", "r23",
5945183ccdSTaylor Simpson   "r24", "r25", "r26", "r27", "r28",  "r29", "r30", "r31",
6045183ccdSTaylor Simpson   "sa0", "lc0", "sa1", "lc1", "p3_0", "c5",  "m0",  "m1",
6145183ccdSTaylor Simpson   "usr", "pc",  "ugp", "gp",  "cs0",  "cs1", "c14", "c15",
6240438b67STaylor Simpson   "c16", "c17", "c18", "c19", "pkt_cnt",  "insn_cnt", "hvx_cnt", "c23",
6345183ccdSTaylor Simpson   "c24", "c25", "c26", "c27", "c28",  "c29", "c30", "c31",
6445183ccdSTaylor Simpson };
6545183ccdSTaylor Simpson 
6645183ccdSTaylor Simpson /*
6745183ccdSTaylor Simpson  * One of the main debugging techniques is to use "-d cpu" and compare against
6845183ccdSTaylor Simpson  * LLDB output when single stepping.  However, the target and qemu put the
6945183ccdSTaylor Simpson  * stacks at different locations.  This is used to compensate so the diff is
7045183ccdSTaylor Simpson  * cleaner.
7145183ccdSTaylor Simpson  */
722d27cebbSTaylor Simpson static target_ulong adjust_stack_ptrs(CPUHexagonState *env, target_ulong addr)
7345183ccdSTaylor Simpson {
747d9ab202STaylor Simpson     HexagonCPU *cpu = env_archcpu(env);
7545183ccdSTaylor Simpson     target_ulong stack_adjust = cpu->lldb_stack_adjust;
7645183ccdSTaylor Simpson     target_ulong stack_start = env->stack_start;
7745183ccdSTaylor Simpson     target_ulong stack_size = 0x10000;
7845183ccdSTaylor Simpson 
7945183ccdSTaylor Simpson     if (stack_adjust == 0) {
8045183ccdSTaylor Simpson         return addr;
8145183ccdSTaylor Simpson     }
8245183ccdSTaylor Simpson 
8345183ccdSTaylor Simpson     if (stack_start + 0x1000 >= addr && addr >= (stack_start - stack_size)) {
8445183ccdSTaylor Simpson         return addr - stack_adjust;
8545183ccdSTaylor Simpson     }
8645183ccdSTaylor Simpson     return addr;
8745183ccdSTaylor Simpson }
8845183ccdSTaylor Simpson 
8945183ccdSTaylor Simpson /* HEX_REG_P3_0 (aka C4) is an alias for the predicate registers */
902d27cebbSTaylor Simpson static target_ulong read_p3_0(CPUHexagonState *env)
9145183ccdSTaylor Simpson {
9245183ccdSTaylor Simpson     int32_t control_reg = 0;
9345183ccdSTaylor Simpson     int i;
9445183ccdSTaylor Simpson     for (i = NUM_PREGS - 1; i >= 0; i--) {
9545183ccdSTaylor Simpson         control_reg <<= 8;
9645183ccdSTaylor Simpson         control_reg |= env->pred[i] & 0xff;
9745183ccdSTaylor Simpson     }
9845183ccdSTaylor Simpson     return control_reg;
9945183ccdSTaylor Simpson }
10045183ccdSTaylor Simpson 
10145183ccdSTaylor Simpson static void print_reg(FILE *f, CPUHexagonState *env, int regnum)
10245183ccdSTaylor Simpson {
10345183ccdSTaylor Simpson     target_ulong value;
10445183ccdSTaylor Simpson 
10545183ccdSTaylor Simpson     if (regnum == HEX_REG_P3_0) {
10645183ccdSTaylor Simpson         value = read_p3_0(env);
10745183ccdSTaylor Simpson     } else {
10845183ccdSTaylor Simpson         value = regnum < 32 ? adjust_stack_ptrs(env, env->gpr[regnum])
10945183ccdSTaylor Simpson                             : env->gpr[regnum];
11045183ccdSTaylor Simpson     }
11145183ccdSTaylor Simpson 
11245183ccdSTaylor Simpson     qemu_fprintf(f, "  %s = 0x" TARGET_FMT_lx "\n",
11345183ccdSTaylor Simpson                  hexagon_regnames[regnum], value);
11445183ccdSTaylor Simpson }
11545183ccdSTaylor Simpson 
116a1559537STaylor Simpson static void print_vreg(FILE *f, CPUHexagonState *env, int regnum,
117a1559537STaylor Simpson                        bool skip_if_zero)
118a1559537STaylor Simpson {
119a1559537STaylor Simpson     if (skip_if_zero) {
120a1559537STaylor Simpson         bool nonzero_found = false;
121a1559537STaylor Simpson         for (int i = 0; i < MAX_VEC_SIZE_BYTES; i++) {
122a1559537STaylor Simpson             if (env->VRegs[regnum].ub[i] != 0) {
123a1559537STaylor Simpson                 nonzero_found = true;
124a1559537STaylor Simpson                 break;
125a1559537STaylor Simpson             }
126a1559537STaylor Simpson         }
127a1559537STaylor Simpson         if (!nonzero_found) {
128a1559537STaylor Simpson             return;
129a1559537STaylor Simpson         }
130a1559537STaylor Simpson     }
131a1559537STaylor Simpson 
132a1559537STaylor Simpson     qemu_fprintf(f, "  v%d = ( ", regnum);
133a1559537STaylor Simpson     qemu_fprintf(f, "0x%02x", env->VRegs[regnum].ub[MAX_VEC_SIZE_BYTES - 1]);
134a1559537STaylor Simpson     for (int i = MAX_VEC_SIZE_BYTES - 2; i >= 0; i--) {
135a1559537STaylor Simpson         qemu_fprintf(f, ", 0x%02x", env->VRegs[regnum].ub[i]);
136a1559537STaylor Simpson     }
137a1559537STaylor Simpson     qemu_fprintf(f, " )\n");
138a1559537STaylor Simpson }
139a1559537STaylor Simpson 
140a1559537STaylor Simpson void hexagon_debug_vreg(CPUHexagonState *env, int regnum)
141a1559537STaylor Simpson {
142a1559537STaylor Simpson     print_vreg(stdout, env, regnum, false);
143a1559537STaylor Simpson }
144a1559537STaylor Simpson 
145a1559537STaylor Simpson static void print_qreg(FILE *f, CPUHexagonState *env, int regnum,
146a1559537STaylor Simpson                        bool skip_if_zero)
147a1559537STaylor Simpson {
148a1559537STaylor Simpson     if (skip_if_zero) {
149a1559537STaylor Simpson         bool nonzero_found = false;
150a1559537STaylor Simpson         for (int i = 0; i < MAX_VEC_SIZE_BYTES / 8; i++) {
151a1559537STaylor Simpson             if (env->QRegs[regnum].ub[i] != 0) {
152a1559537STaylor Simpson                 nonzero_found = true;
153a1559537STaylor Simpson                 break;
154a1559537STaylor Simpson             }
155a1559537STaylor Simpson         }
156a1559537STaylor Simpson         if (!nonzero_found) {
157a1559537STaylor Simpson             return;
158a1559537STaylor Simpson         }
159a1559537STaylor Simpson     }
160a1559537STaylor Simpson 
161a1559537STaylor Simpson     qemu_fprintf(f, "  q%d = ( ", regnum);
162a1559537STaylor Simpson     qemu_fprintf(f, "0x%02x",
163a1559537STaylor Simpson                  env->QRegs[regnum].ub[MAX_VEC_SIZE_BYTES / 8 - 1]);
164a1559537STaylor Simpson     for (int i = MAX_VEC_SIZE_BYTES / 8 - 2; i >= 0; i--) {
165a1559537STaylor Simpson         qemu_fprintf(f, ", 0x%02x", env->QRegs[regnum].ub[i]);
166a1559537STaylor Simpson     }
167a1559537STaylor Simpson     qemu_fprintf(f, " )\n");
168a1559537STaylor Simpson }
169a1559537STaylor Simpson 
170a1559537STaylor Simpson void hexagon_debug_qreg(CPUHexagonState *env, int regnum)
171a1559537STaylor Simpson {
172a1559537STaylor Simpson     print_qreg(stdout, env, regnum, false);
173a1559537STaylor Simpson }
174a1559537STaylor Simpson 
175a1559537STaylor Simpson static void hexagon_dump(CPUHexagonState *env, FILE *f, int flags)
17645183ccdSTaylor Simpson {
1777d9ab202STaylor Simpson     HexagonCPU *cpu = env_archcpu(env);
17845183ccdSTaylor Simpson 
17945183ccdSTaylor Simpson     if (cpu->lldb_compat) {
18045183ccdSTaylor Simpson         /*
18145183ccdSTaylor Simpson          * When comparing with LLDB, it doesn't step through single-cycle
18245183ccdSTaylor Simpson          * hardware loops the same way.  So, we just skip them here
18345183ccdSTaylor Simpson          */
18445183ccdSTaylor Simpson         if (env->gpr[HEX_REG_PC] == env->last_pc_dumped) {
18545183ccdSTaylor Simpson             return;
18645183ccdSTaylor Simpson         }
18745183ccdSTaylor Simpson         env->last_pc_dumped = env->gpr[HEX_REG_PC];
18845183ccdSTaylor Simpson     }
18945183ccdSTaylor Simpson 
19045183ccdSTaylor Simpson     qemu_fprintf(f, "General Purpose Registers = {\n");
19145183ccdSTaylor Simpson     for (int i = 0; i < 32; i++) {
19245183ccdSTaylor Simpson         print_reg(f, env, i);
19345183ccdSTaylor Simpson     }
19445183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_SA0);
19545183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_LC0);
19645183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_SA1);
19745183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_LC1);
19845183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_M0);
19945183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_M1);
20045183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_USR);
20145183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_P3_0);
20245183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_GP);
20345183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_UGP);
20445183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_PC);
20545183ccdSTaylor Simpson #ifdef CONFIG_USER_ONLY
20645183ccdSTaylor Simpson     /*
20745183ccdSTaylor Simpson      * Not modelled in user mode, print junk to minimize the diff's
20845183ccdSTaylor Simpson      * with LLDB output
20945183ccdSTaylor Simpson      */
21045183ccdSTaylor Simpson     qemu_fprintf(f, "  cause = 0x000000db\n");
21145183ccdSTaylor Simpson     qemu_fprintf(f, "  badva = 0x00000000\n");
21245183ccdSTaylor Simpson     qemu_fprintf(f, "  cs0 = 0x00000000\n");
21345183ccdSTaylor Simpson     qemu_fprintf(f, "  cs1 = 0x00000000\n");
21445183ccdSTaylor Simpson #else
21545183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_CAUSE);
21645183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_BADVA);
21745183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_CS0);
21845183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_CS1);
21945183ccdSTaylor Simpson #endif
22045183ccdSTaylor Simpson     qemu_fprintf(f, "}\n");
221a1559537STaylor Simpson 
222a1559537STaylor Simpson     if (flags & CPU_DUMP_FPU) {
223a1559537STaylor Simpson         qemu_fprintf(f, "Vector Registers = {\n");
224a1559537STaylor Simpson         for (int i = 0; i < NUM_VREGS; i++) {
225a1559537STaylor Simpson             print_vreg(f, env, i, true);
226a1559537STaylor Simpson         }
227a1559537STaylor Simpson         for (int i = 0; i < NUM_QREGS; i++) {
228a1559537STaylor Simpson             print_qreg(f, env, i, true);
229a1559537STaylor Simpson         }
230a1559537STaylor Simpson         qemu_fprintf(f, "}\n");
231a1559537STaylor Simpson     }
23245183ccdSTaylor Simpson }
23345183ccdSTaylor Simpson 
23445183ccdSTaylor Simpson static void hexagon_dump_state(CPUState *cs, FILE *f, int flags)
23545183ccdSTaylor Simpson {
23645183ccdSTaylor Simpson     HexagonCPU *cpu = HEXAGON_CPU(cs);
23745183ccdSTaylor Simpson     CPUHexagonState *env = &cpu->env;
23845183ccdSTaylor Simpson 
239a1559537STaylor Simpson     hexagon_dump(env, f, flags);
24045183ccdSTaylor Simpson }
24145183ccdSTaylor Simpson 
24245183ccdSTaylor Simpson void hexagon_debug(CPUHexagonState *env)
24345183ccdSTaylor Simpson {
244a1559537STaylor Simpson     hexagon_dump(env, stdout, CPU_DUMP_FPU);
24545183ccdSTaylor Simpson }
24645183ccdSTaylor Simpson 
24745183ccdSTaylor Simpson static void hexagon_cpu_set_pc(CPUState *cs, vaddr value)
24845183ccdSTaylor Simpson {
24945183ccdSTaylor Simpson     HexagonCPU *cpu = HEXAGON_CPU(cs);
25045183ccdSTaylor Simpson     CPUHexagonState *env = &cpu->env;
25145183ccdSTaylor Simpson     env->gpr[HEX_REG_PC] = value;
25245183ccdSTaylor Simpson }
25345183ccdSTaylor Simpson 
254e4fdf9dfSRichard Henderson static vaddr hexagon_cpu_get_pc(CPUState *cs)
255e4fdf9dfSRichard Henderson {
256e4fdf9dfSRichard Henderson     HexagonCPU *cpu = HEXAGON_CPU(cs);
257e4fdf9dfSRichard Henderson     CPUHexagonState *env = &cpu->env;
258e4fdf9dfSRichard Henderson     return env->gpr[HEX_REG_PC];
259e4fdf9dfSRichard Henderson }
260e4fdf9dfSRichard Henderson 
26145183ccdSTaylor Simpson static void hexagon_cpu_synchronize_from_tb(CPUState *cs,
26245183ccdSTaylor Simpson                                             const TranslationBlock *tb)
26345183ccdSTaylor Simpson {
26445183ccdSTaylor Simpson     HexagonCPU *cpu = HEXAGON_CPU(cs);
26545183ccdSTaylor Simpson     CPUHexagonState *env = &cpu->env;
266fbf59aadSRichard Henderson     env->gpr[HEX_REG_PC] = tb_pc(tb);
26745183ccdSTaylor Simpson }
26845183ccdSTaylor Simpson 
26945183ccdSTaylor Simpson static bool hexagon_cpu_has_work(CPUState *cs)
27045183ccdSTaylor Simpson {
27145183ccdSTaylor Simpson     return true;
27245183ccdSTaylor Simpson }
27345183ccdSTaylor Simpson 
27490157814SRichard Henderson static void hexagon_restore_state_to_opc(CPUState *cs,
27590157814SRichard Henderson                                          const TranslationBlock *tb,
27690157814SRichard Henderson                                          const uint64_t *data)
27745183ccdSTaylor Simpson {
27890157814SRichard Henderson     HexagonCPU *cpu = HEXAGON_CPU(cs);
27990157814SRichard Henderson     CPUHexagonState *env = &cpu->env;
28090157814SRichard Henderson 
28145183ccdSTaylor Simpson     env->gpr[HEX_REG_PC] = data[0];
28245183ccdSTaylor Simpson }
28345183ccdSTaylor Simpson 
284*ab85156dSPeter Maydell static void hexagon_cpu_reset_hold(Object *obj)
28545183ccdSTaylor Simpson {
286*ab85156dSPeter Maydell     CPUState *cs = CPU(obj);
28745183ccdSTaylor Simpson     HexagonCPU *cpu = HEXAGON_CPU(cs);
28845183ccdSTaylor Simpson     HexagonCPUClass *mcc = HEXAGON_CPU_GET_CLASS(cpu);
289c0336c87STaylor Simpson     CPUHexagonState *env = &cpu->env;
29045183ccdSTaylor Simpson 
291*ab85156dSPeter Maydell     if (mcc->parent_phases.hold) {
292*ab85156dSPeter Maydell         mcc->parent_phases.hold(obj);
293*ab85156dSPeter Maydell     }
294c0336c87STaylor Simpson 
295c0336c87STaylor Simpson     set_default_nan_mode(1, &env->fp_status);
296c0336c87STaylor Simpson     set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
29745183ccdSTaylor Simpson }
29845183ccdSTaylor Simpson 
29945183ccdSTaylor Simpson static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
30045183ccdSTaylor Simpson {
30145183ccdSTaylor Simpson     info->print_insn = print_insn_hexagon;
30245183ccdSTaylor Simpson }
30345183ccdSTaylor Simpson 
30445183ccdSTaylor Simpson static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
30545183ccdSTaylor Simpson {
30645183ccdSTaylor Simpson     CPUState *cs = CPU(dev);
30745183ccdSTaylor Simpson     HexagonCPUClass *mcc = HEXAGON_CPU_GET_CLASS(dev);
30845183ccdSTaylor Simpson     Error *local_err = NULL;
30945183ccdSTaylor Simpson 
31045183ccdSTaylor Simpson     cpu_exec_realizefn(cs, &local_err);
31145183ccdSTaylor Simpson     if (local_err != NULL) {
31245183ccdSTaylor Simpson         error_propagate(errp, local_err);
31345183ccdSTaylor Simpson         return;
31445183ccdSTaylor Simpson     }
31545183ccdSTaylor Simpson 
31645183ccdSTaylor Simpson     qemu_init_vcpu(cs);
31745183ccdSTaylor Simpson     cpu_reset(cs);
31845183ccdSTaylor Simpson 
31945183ccdSTaylor Simpson     mcc->parent_realize(dev, errp);
32045183ccdSTaylor Simpson }
32145183ccdSTaylor Simpson 
32245183ccdSTaylor Simpson static void hexagon_cpu_init(Object *obj)
32345183ccdSTaylor Simpson {
32445183ccdSTaylor Simpson     HexagonCPU *cpu = HEXAGON_CPU(obj);
32545183ccdSTaylor Simpson 
32645183ccdSTaylor Simpson     cpu_set_cpustate_pointers(cpu);
32745183ccdSTaylor Simpson     qdev_property_add_static(DEVICE(obj), &hexagon_lldb_compat_property);
32845183ccdSTaylor Simpson     qdev_property_add_static(DEVICE(obj), &hexagon_lldb_stack_adjust_property);
32945183ccdSTaylor Simpson }
33045183ccdSTaylor Simpson 
33145183ccdSTaylor Simpson #include "hw/core/tcg-cpu-ops.h"
33245183ccdSTaylor Simpson 
33311906557SRichard Henderson static const struct TCGCPUOps hexagon_tcg_ops = {
33445183ccdSTaylor Simpson     .initialize = hexagon_translate_init,
33545183ccdSTaylor Simpson     .synchronize_from_tb = hexagon_cpu_synchronize_from_tb,
33690157814SRichard Henderson     .restore_state_to_opc = hexagon_restore_state_to_opc,
33745183ccdSTaylor Simpson };
33845183ccdSTaylor Simpson 
33945183ccdSTaylor Simpson static void hexagon_cpu_class_init(ObjectClass *c, void *data)
34045183ccdSTaylor Simpson {
34145183ccdSTaylor Simpson     HexagonCPUClass *mcc = HEXAGON_CPU_CLASS(c);
34245183ccdSTaylor Simpson     CPUClass *cc = CPU_CLASS(c);
34345183ccdSTaylor Simpson     DeviceClass *dc = DEVICE_CLASS(c);
344*ab85156dSPeter Maydell     ResettableClass *rc = RESETTABLE_CLASS(c);
34545183ccdSTaylor Simpson 
34645183ccdSTaylor Simpson     device_class_set_parent_realize(dc, hexagon_cpu_realize,
34745183ccdSTaylor Simpson                                     &mcc->parent_realize);
34845183ccdSTaylor Simpson 
349*ab85156dSPeter Maydell     resettable_class_set_parent_phases(rc, NULL, hexagon_cpu_reset_hold, NULL,
350*ab85156dSPeter Maydell                                        &mcc->parent_phases);
35145183ccdSTaylor Simpson 
35245183ccdSTaylor Simpson     cc->class_by_name = hexagon_cpu_class_by_name;
35345183ccdSTaylor Simpson     cc->has_work = hexagon_cpu_has_work;
35445183ccdSTaylor Simpson     cc->dump_state = hexagon_dump_state;
35545183ccdSTaylor Simpson     cc->set_pc = hexagon_cpu_set_pc;
356e4fdf9dfSRichard Henderson     cc->get_pc = hexagon_cpu_get_pc;
35745183ccdSTaylor Simpson     cc->gdb_read_register = hexagon_gdb_read_register;
35845183ccdSTaylor Simpson     cc->gdb_write_register = hexagon_gdb_write_register;
359a1559537STaylor Simpson     cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS + NUM_VREGS + NUM_QREGS;
36045183ccdSTaylor Simpson     cc->gdb_stop_before_watchpoint = true;
36145183ccdSTaylor Simpson     cc->disas_set_info = hexagon_cpu_disas_set_info;
36245183ccdSTaylor Simpson     cc->tcg_ops = &hexagon_tcg_ops;
36345183ccdSTaylor Simpson }
36445183ccdSTaylor Simpson 
36545183ccdSTaylor Simpson #define DEFINE_CPU(type_name, initfn)      \
36645183ccdSTaylor Simpson     {                                      \
36745183ccdSTaylor Simpson         .name = type_name,                 \
36845183ccdSTaylor Simpson         .parent = TYPE_HEXAGON_CPU,        \
36945183ccdSTaylor Simpson         .instance_init = initfn            \
37045183ccdSTaylor Simpson     }
37145183ccdSTaylor Simpson 
37245183ccdSTaylor Simpson static const TypeInfo hexagon_cpu_type_infos[] = {
37345183ccdSTaylor Simpson     {
37445183ccdSTaylor Simpson         .name = TYPE_HEXAGON_CPU,
37545183ccdSTaylor Simpson         .parent = TYPE_CPU,
37645183ccdSTaylor Simpson         .instance_size = sizeof(HexagonCPU),
37745183ccdSTaylor Simpson         .instance_init = hexagon_cpu_init,
37845183ccdSTaylor Simpson         .abstract = true,
37945183ccdSTaylor Simpson         .class_size = sizeof(HexagonCPUClass),
38045183ccdSTaylor Simpson         .class_init = hexagon_cpu_class_init,
38145183ccdSTaylor Simpson     },
38245183ccdSTaylor Simpson     DEFINE_CPU(TYPE_HEXAGON_CPU_V67,              hexagon_v67_cpu_init),
38345183ccdSTaylor Simpson };
38445183ccdSTaylor Simpson 
38545183ccdSTaylor Simpson DEFINE_TYPES(hexagon_cpu_type_infos)
386