xref: /openbmc/qemu/target/hexagon/cpu.c (revision fc2622f6)
145183ccdSTaylor Simpson /*
2*fc2622f6STaylor Simpson  *  Copyright(c) 2019-2023 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"
26ba445655SAnton Johansson #include "tcg/tcg.h"
2745183ccdSTaylor Simpson 
28*fc2622f6STaylor Simpson static void hexagon_v67_cpu_init(Object *obj) { }
29*fc2622f6STaylor Simpson static void hexagon_v68_cpu_init(Object *obj) { }
30*fc2622f6STaylor Simpson static void hexagon_v69_cpu_init(Object *obj) { }
31*fc2622f6STaylor Simpson static void hexagon_v71_cpu_init(Object *obj) { }
32*fc2622f6STaylor Simpson static void hexagon_v73_cpu_init(Object *obj) { }
3345183ccdSTaylor Simpson 
3445183ccdSTaylor Simpson static ObjectClass *hexagon_cpu_class_by_name(const char *cpu_model)
3545183ccdSTaylor Simpson {
3645183ccdSTaylor Simpson     ObjectClass *oc;
3745183ccdSTaylor Simpson     char *typename;
3845183ccdSTaylor Simpson     char **cpuname;
3945183ccdSTaylor Simpson 
4045183ccdSTaylor Simpson     cpuname = g_strsplit(cpu_model, ",", 1);
4145183ccdSTaylor Simpson     typename = g_strdup_printf(HEXAGON_CPU_TYPE_NAME("%s"), cpuname[0]);
4245183ccdSTaylor Simpson     oc = object_class_by_name(typename);
4345183ccdSTaylor Simpson     g_strfreev(cpuname);
4445183ccdSTaylor Simpson     g_free(typename);
4545183ccdSTaylor Simpson     if (!oc || !object_class_dynamic_cast(oc, TYPE_HEXAGON_CPU) ||
4645183ccdSTaylor Simpson         object_class_is_abstract(oc)) {
4745183ccdSTaylor Simpson         return NULL;
4845183ccdSTaylor Simpson     }
4945183ccdSTaylor Simpson     return oc;
5045183ccdSTaylor Simpson }
5145183ccdSTaylor Simpson 
5245183ccdSTaylor Simpson static Property hexagon_lldb_compat_property =
5345183ccdSTaylor Simpson     DEFINE_PROP_BOOL("lldb-compat", HexagonCPU, lldb_compat, false);
5445183ccdSTaylor Simpson static Property hexagon_lldb_stack_adjust_property =
5545183ccdSTaylor Simpson     DEFINE_PROP_UNSIGNED("lldb-stack-adjust", HexagonCPU, lldb_stack_adjust,
5645183ccdSTaylor Simpson                          0, qdev_prop_uint32, target_ulong);
5745183ccdSTaylor Simpson 
5845183ccdSTaylor Simpson const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS] = {
5945183ccdSTaylor Simpson    "r0", "r1",  "r2",  "r3",  "r4",   "r5",  "r6",  "r7",
6045183ccdSTaylor Simpson    "r8", "r9",  "r10", "r11", "r12",  "r13", "r14", "r15",
6145183ccdSTaylor Simpson   "r16", "r17", "r18", "r19", "r20",  "r21", "r22", "r23",
6245183ccdSTaylor Simpson   "r24", "r25", "r26", "r27", "r28",  "r29", "r30", "r31",
6345183ccdSTaylor Simpson   "sa0", "lc0", "sa1", "lc1", "p3_0", "c5",  "m0",  "m1",
6445183ccdSTaylor Simpson   "usr", "pc",  "ugp", "gp",  "cs0",  "cs1", "c14", "c15",
6540438b67STaylor Simpson   "c16", "c17", "c18", "c19", "pkt_cnt",  "insn_cnt", "hvx_cnt", "c23",
6645183ccdSTaylor Simpson   "c24", "c25", "c26", "c27", "c28",  "c29", "c30", "c31",
6745183ccdSTaylor Simpson };
6845183ccdSTaylor Simpson 
6945183ccdSTaylor Simpson /*
7045183ccdSTaylor Simpson  * One of the main debugging techniques is to use "-d cpu" and compare against
7145183ccdSTaylor Simpson  * LLDB output when single stepping.  However, the target and qemu put the
7245183ccdSTaylor Simpson  * stacks at different locations.  This is used to compensate so the diff is
7345183ccdSTaylor Simpson  * cleaner.
7445183ccdSTaylor Simpson  */
752d27cebbSTaylor Simpson static target_ulong adjust_stack_ptrs(CPUHexagonState *env, target_ulong addr)
7645183ccdSTaylor Simpson {
777d9ab202STaylor Simpson     HexagonCPU *cpu = env_archcpu(env);
7845183ccdSTaylor Simpson     target_ulong stack_adjust = cpu->lldb_stack_adjust;
7945183ccdSTaylor Simpson     target_ulong stack_start = env->stack_start;
8045183ccdSTaylor Simpson     target_ulong stack_size = 0x10000;
8145183ccdSTaylor Simpson 
8245183ccdSTaylor Simpson     if (stack_adjust == 0) {
8345183ccdSTaylor Simpson         return addr;
8445183ccdSTaylor Simpson     }
8545183ccdSTaylor Simpson 
8645183ccdSTaylor Simpson     if (stack_start + 0x1000 >= addr && addr >= (stack_start - stack_size)) {
8745183ccdSTaylor Simpson         return addr - stack_adjust;
8845183ccdSTaylor Simpson     }
8945183ccdSTaylor Simpson     return addr;
9045183ccdSTaylor Simpson }
9145183ccdSTaylor Simpson 
9272895676SMukilan Thiyagarajan /* HEX_REG_P3_0_ALIASED (aka C4) is an alias for the predicate registers */
932d27cebbSTaylor Simpson static target_ulong read_p3_0(CPUHexagonState *env)
9445183ccdSTaylor Simpson {
9545183ccdSTaylor Simpson     int32_t control_reg = 0;
9645183ccdSTaylor Simpson     int i;
9745183ccdSTaylor Simpson     for (i = NUM_PREGS - 1; i >= 0; i--) {
9845183ccdSTaylor Simpson         control_reg <<= 8;
9945183ccdSTaylor Simpson         control_reg |= env->pred[i] & 0xff;
10045183ccdSTaylor Simpson     }
10145183ccdSTaylor Simpson     return control_reg;
10245183ccdSTaylor Simpson }
10345183ccdSTaylor Simpson 
10445183ccdSTaylor Simpson static void print_reg(FILE *f, CPUHexagonState *env, int regnum)
10545183ccdSTaylor Simpson {
10645183ccdSTaylor Simpson     target_ulong value;
10745183ccdSTaylor Simpson 
10872895676SMukilan Thiyagarajan     if (regnum == HEX_REG_P3_0_ALIASED) {
10945183ccdSTaylor Simpson         value = read_p3_0(env);
11045183ccdSTaylor Simpson     } else {
11145183ccdSTaylor Simpson         value = regnum < 32 ? adjust_stack_ptrs(env, env->gpr[regnum])
11245183ccdSTaylor Simpson                             : env->gpr[regnum];
11345183ccdSTaylor Simpson     }
11445183ccdSTaylor Simpson 
11545183ccdSTaylor Simpson     qemu_fprintf(f, "  %s = 0x" TARGET_FMT_lx "\n",
11645183ccdSTaylor Simpson                  hexagon_regnames[regnum], value);
11745183ccdSTaylor Simpson }
11845183ccdSTaylor Simpson 
119a1559537STaylor Simpson static void print_vreg(FILE *f, CPUHexagonState *env, int regnum,
120a1559537STaylor Simpson                        bool skip_if_zero)
121a1559537STaylor Simpson {
122a1559537STaylor Simpson     if (skip_if_zero) {
123a1559537STaylor Simpson         bool nonzero_found = false;
124a1559537STaylor Simpson         for (int i = 0; i < MAX_VEC_SIZE_BYTES; i++) {
125a1559537STaylor Simpson             if (env->VRegs[regnum].ub[i] != 0) {
126a1559537STaylor Simpson                 nonzero_found = true;
127a1559537STaylor Simpson                 break;
128a1559537STaylor Simpson             }
129a1559537STaylor Simpson         }
130a1559537STaylor Simpson         if (!nonzero_found) {
131a1559537STaylor Simpson             return;
132a1559537STaylor Simpson         }
133a1559537STaylor Simpson     }
134a1559537STaylor Simpson 
135a1559537STaylor Simpson     qemu_fprintf(f, "  v%d = ( ", regnum);
136a1559537STaylor Simpson     qemu_fprintf(f, "0x%02x", env->VRegs[regnum].ub[MAX_VEC_SIZE_BYTES - 1]);
137a1559537STaylor Simpson     for (int i = MAX_VEC_SIZE_BYTES - 2; i >= 0; i--) {
138a1559537STaylor Simpson         qemu_fprintf(f, ", 0x%02x", env->VRegs[regnum].ub[i]);
139a1559537STaylor Simpson     }
140a1559537STaylor Simpson     qemu_fprintf(f, " )\n");
141a1559537STaylor Simpson }
142a1559537STaylor Simpson 
143a1559537STaylor Simpson void hexagon_debug_vreg(CPUHexagonState *env, int regnum)
144a1559537STaylor Simpson {
145a1559537STaylor Simpson     print_vreg(stdout, env, regnum, false);
146a1559537STaylor Simpson }
147a1559537STaylor Simpson 
148a1559537STaylor Simpson static void print_qreg(FILE *f, CPUHexagonState *env, int regnum,
149a1559537STaylor Simpson                        bool skip_if_zero)
150a1559537STaylor Simpson {
151a1559537STaylor Simpson     if (skip_if_zero) {
152a1559537STaylor Simpson         bool nonzero_found = false;
153a1559537STaylor Simpson         for (int i = 0; i < MAX_VEC_SIZE_BYTES / 8; i++) {
154a1559537STaylor Simpson             if (env->QRegs[regnum].ub[i] != 0) {
155a1559537STaylor Simpson                 nonzero_found = true;
156a1559537STaylor Simpson                 break;
157a1559537STaylor Simpson             }
158a1559537STaylor Simpson         }
159a1559537STaylor Simpson         if (!nonzero_found) {
160a1559537STaylor Simpson             return;
161a1559537STaylor Simpson         }
162a1559537STaylor Simpson     }
163a1559537STaylor Simpson 
164a1559537STaylor Simpson     qemu_fprintf(f, "  q%d = ( ", regnum);
165a1559537STaylor Simpson     qemu_fprintf(f, "0x%02x",
166a1559537STaylor Simpson                  env->QRegs[regnum].ub[MAX_VEC_SIZE_BYTES / 8 - 1]);
167a1559537STaylor Simpson     for (int i = MAX_VEC_SIZE_BYTES / 8 - 2; i >= 0; i--) {
168a1559537STaylor Simpson         qemu_fprintf(f, ", 0x%02x", env->QRegs[regnum].ub[i]);
169a1559537STaylor Simpson     }
170a1559537STaylor Simpson     qemu_fprintf(f, " )\n");
171a1559537STaylor Simpson }
172a1559537STaylor Simpson 
173a1559537STaylor Simpson void hexagon_debug_qreg(CPUHexagonState *env, int regnum)
174a1559537STaylor Simpson {
175a1559537STaylor Simpson     print_qreg(stdout, env, regnum, false);
176a1559537STaylor Simpson }
177a1559537STaylor Simpson 
178a1559537STaylor Simpson static void hexagon_dump(CPUHexagonState *env, FILE *f, int flags)
17945183ccdSTaylor Simpson {
1807d9ab202STaylor Simpson     HexagonCPU *cpu = env_archcpu(env);
18145183ccdSTaylor Simpson 
18245183ccdSTaylor Simpson     if (cpu->lldb_compat) {
18345183ccdSTaylor Simpson         /*
18445183ccdSTaylor Simpson          * When comparing with LLDB, it doesn't step through single-cycle
18545183ccdSTaylor Simpson          * hardware loops the same way.  So, we just skip them here
18645183ccdSTaylor Simpson          */
18745183ccdSTaylor Simpson         if (env->gpr[HEX_REG_PC] == env->last_pc_dumped) {
18845183ccdSTaylor Simpson             return;
18945183ccdSTaylor Simpson         }
19045183ccdSTaylor Simpson         env->last_pc_dumped = env->gpr[HEX_REG_PC];
19145183ccdSTaylor Simpson     }
19245183ccdSTaylor Simpson 
19345183ccdSTaylor Simpson     qemu_fprintf(f, "General Purpose Registers = {\n");
19445183ccdSTaylor Simpson     for (int i = 0; i < 32; i++) {
19545183ccdSTaylor Simpson         print_reg(f, env, i);
19645183ccdSTaylor Simpson     }
19745183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_SA0);
19845183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_LC0);
19945183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_SA1);
20045183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_LC1);
20145183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_M0);
20245183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_M1);
20345183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_USR);
20472895676SMukilan Thiyagarajan     print_reg(f, env, HEX_REG_P3_0_ALIASED);
20545183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_GP);
20645183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_UGP);
20745183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_PC);
20845183ccdSTaylor Simpson #ifdef CONFIG_USER_ONLY
20945183ccdSTaylor Simpson     /*
21045183ccdSTaylor Simpson      * Not modelled in user mode, print junk to minimize the diff's
21145183ccdSTaylor Simpson      * with LLDB output
21245183ccdSTaylor Simpson      */
21345183ccdSTaylor Simpson     qemu_fprintf(f, "  cause = 0x000000db\n");
21445183ccdSTaylor Simpson     qemu_fprintf(f, "  badva = 0x00000000\n");
21545183ccdSTaylor Simpson     qemu_fprintf(f, "  cs0 = 0x00000000\n");
21645183ccdSTaylor Simpson     qemu_fprintf(f, "  cs1 = 0x00000000\n");
21745183ccdSTaylor Simpson #else
21845183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_CAUSE);
21945183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_BADVA);
22045183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_CS0);
22145183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_CS1);
22245183ccdSTaylor Simpson #endif
22345183ccdSTaylor Simpson     qemu_fprintf(f, "}\n");
224a1559537STaylor Simpson 
225a1559537STaylor Simpson     if (flags & CPU_DUMP_FPU) {
226a1559537STaylor Simpson         qemu_fprintf(f, "Vector Registers = {\n");
227a1559537STaylor Simpson         for (int i = 0; i < NUM_VREGS; i++) {
228a1559537STaylor Simpson             print_vreg(f, env, i, true);
229a1559537STaylor Simpson         }
230a1559537STaylor Simpson         for (int i = 0; i < NUM_QREGS; i++) {
231a1559537STaylor Simpson             print_qreg(f, env, i, true);
232a1559537STaylor Simpson         }
233a1559537STaylor Simpson         qemu_fprintf(f, "}\n");
234a1559537STaylor Simpson     }
23545183ccdSTaylor Simpson }
23645183ccdSTaylor Simpson 
23745183ccdSTaylor Simpson static void hexagon_dump_state(CPUState *cs, FILE *f, int flags)
23845183ccdSTaylor Simpson {
23945183ccdSTaylor Simpson     HexagonCPU *cpu = HEXAGON_CPU(cs);
24045183ccdSTaylor Simpson     CPUHexagonState *env = &cpu->env;
24145183ccdSTaylor Simpson 
242a1559537STaylor Simpson     hexagon_dump(env, f, flags);
24345183ccdSTaylor Simpson }
24445183ccdSTaylor Simpson 
24545183ccdSTaylor Simpson void hexagon_debug(CPUHexagonState *env)
24645183ccdSTaylor Simpson {
247a1559537STaylor Simpson     hexagon_dump(env, stdout, CPU_DUMP_FPU);
24845183ccdSTaylor Simpson }
24945183ccdSTaylor Simpson 
25045183ccdSTaylor Simpson static void hexagon_cpu_set_pc(CPUState *cs, vaddr value)
25145183ccdSTaylor Simpson {
25245183ccdSTaylor Simpson     HexagonCPU *cpu = HEXAGON_CPU(cs);
25345183ccdSTaylor Simpson     CPUHexagonState *env = &cpu->env;
25445183ccdSTaylor Simpson     env->gpr[HEX_REG_PC] = value;
25545183ccdSTaylor Simpson }
25645183ccdSTaylor Simpson 
257e4fdf9dfSRichard Henderson static vaddr hexagon_cpu_get_pc(CPUState *cs)
258e4fdf9dfSRichard Henderson {
259e4fdf9dfSRichard Henderson     HexagonCPU *cpu = HEXAGON_CPU(cs);
260e4fdf9dfSRichard Henderson     CPUHexagonState *env = &cpu->env;
261e4fdf9dfSRichard Henderson     return env->gpr[HEX_REG_PC];
262e4fdf9dfSRichard Henderson }
263e4fdf9dfSRichard Henderson 
26445183ccdSTaylor Simpson static void hexagon_cpu_synchronize_from_tb(CPUState *cs,
26545183ccdSTaylor Simpson                                             const TranslationBlock *tb)
26645183ccdSTaylor Simpson {
26745183ccdSTaylor Simpson     HexagonCPU *cpu = HEXAGON_CPU(cs);
26845183ccdSTaylor Simpson     CPUHexagonState *env = &cpu->env;
269ba445655SAnton Johansson     tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
270ba445655SAnton Johansson     env->gpr[HEX_REG_PC] = tb->pc;
27145183ccdSTaylor Simpson }
27245183ccdSTaylor Simpson 
27345183ccdSTaylor Simpson static bool hexagon_cpu_has_work(CPUState *cs)
27445183ccdSTaylor Simpson {
27545183ccdSTaylor Simpson     return true;
27645183ccdSTaylor Simpson }
27745183ccdSTaylor Simpson 
27890157814SRichard Henderson static void hexagon_restore_state_to_opc(CPUState *cs,
27990157814SRichard Henderson                                          const TranslationBlock *tb,
28090157814SRichard Henderson                                          const uint64_t *data)
28145183ccdSTaylor Simpson {
28290157814SRichard Henderson     HexagonCPU *cpu = HEXAGON_CPU(cs);
28390157814SRichard Henderson     CPUHexagonState *env = &cpu->env;
28490157814SRichard Henderson 
28545183ccdSTaylor Simpson     env->gpr[HEX_REG_PC] = data[0];
28645183ccdSTaylor Simpson }
28745183ccdSTaylor Simpson 
288ab85156dSPeter Maydell static void hexagon_cpu_reset_hold(Object *obj)
28945183ccdSTaylor Simpson {
290ab85156dSPeter Maydell     CPUState *cs = CPU(obj);
29145183ccdSTaylor Simpson     HexagonCPU *cpu = HEXAGON_CPU(cs);
29245183ccdSTaylor Simpson     HexagonCPUClass *mcc = HEXAGON_CPU_GET_CLASS(cpu);
293c0336c87STaylor Simpson     CPUHexagonState *env = &cpu->env;
29445183ccdSTaylor Simpson 
295ab85156dSPeter Maydell     if (mcc->parent_phases.hold) {
296ab85156dSPeter Maydell         mcc->parent_phases.hold(obj);
297ab85156dSPeter Maydell     }
298c0336c87STaylor Simpson 
299c0336c87STaylor Simpson     set_default_nan_mode(1, &env->fp_status);
300c0336c87STaylor Simpson     set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
30145183ccdSTaylor Simpson }
30245183ccdSTaylor Simpson 
30345183ccdSTaylor Simpson static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
30445183ccdSTaylor Simpson {
30545183ccdSTaylor Simpson     info->print_insn = print_insn_hexagon;
30645183ccdSTaylor Simpson }
30745183ccdSTaylor Simpson 
30845183ccdSTaylor Simpson static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
30945183ccdSTaylor Simpson {
31045183ccdSTaylor Simpson     CPUState *cs = CPU(dev);
31145183ccdSTaylor Simpson     HexagonCPUClass *mcc = HEXAGON_CPU_GET_CLASS(dev);
31245183ccdSTaylor Simpson     Error *local_err = NULL;
31345183ccdSTaylor Simpson 
31445183ccdSTaylor Simpson     cpu_exec_realizefn(cs, &local_err);
31545183ccdSTaylor Simpson     if (local_err != NULL) {
31645183ccdSTaylor Simpson         error_propagate(errp, local_err);
31745183ccdSTaylor Simpson         return;
31845183ccdSTaylor Simpson     }
31945183ccdSTaylor Simpson 
32045183ccdSTaylor Simpson     qemu_init_vcpu(cs);
32145183ccdSTaylor Simpson     cpu_reset(cs);
32245183ccdSTaylor Simpson 
32345183ccdSTaylor Simpson     mcc->parent_realize(dev, errp);
32445183ccdSTaylor Simpson }
32545183ccdSTaylor Simpson 
32645183ccdSTaylor Simpson static void hexagon_cpu_init(Object *obj)
32745183ccdSTaylor Simpson {
32845183ccdSTaylor Simpson     HexagonCPU *cpu = HEXAGON_CPU(obj);
32945183ccdSTaylor Simpson 
33045183ccdSTaylor Simpson     cpu_set_cpustate_pointers(cpu);
33145183ccdSTaylor Simpson     qdev_property_add_static(DEVICE(obj), &hexagon_lldb_compat_property);
33245183ccdSTaylor Simpson     qdev_property_add_static(DEVICE(obj), &hexagon_lldb_stack_adjust_property);
33345183ccdSTaylor Simpson }
33445183ccdSTaylor Simpson 
33545183ccdSTaylor Simpson #include "hw/core/tcg-cpu-ops.h"
33645183ccdSTaylor Simpson 
33711906557SRichard Henderson static const struct TCGCPUOps hexagon_tcg_ops = {
33845183ccdSTaylor Simpson     .initialize = hexagon_translate_init,
33945183ccdSTaylor Simpson     .synchronize_from_tb = hexagon_cpu_synchronize_from_tb,
34090157814SRichard Henderson     .restore_state_to_opc = hexagon_restore_state_to_opc,
34145183ccdSTaylor Simpson };
34245183ccdSTaylor Simpson 
34345183ccdSTaylor Simpson static void hexagon_cpu_class_init(ObjectClass *c, void *data)
34445183ccdSTaylor Simpson {
34545183ccdSTaylor Simpson     HexagonCPUClass *mcc = HEXAGON_CPU_CLASS(c);
34645183ccdSTaylor Simpson     CPUClass *cc = CPU_CLASS(c);
34745183ccdSTaylor Simpson     DeviceClass *dc = DEVICE_CLASS(c);
348ab85156dSPeter Maydell     ResettableClass *rc = RESETTABLE_CLASS(c);
34945183ccdSTaylor Simpson 
35045183ccdSTaylor Simpson     device_class_set_parent_realize(dc, hexagon_cpu_realize,
35145183ccdSTaylor Simpson                                     &mcc->parent_realize);
35245183ccdSTaylor Simpson 
353ab85156dSPeter Maydell     resettable_class_set_parent_phases(rc, NULL, hexagon_cpu_reset_hold, NULL,
354ab85156dSPeter Maydell                                        &mcc->parent_phases);
35545183ccdSTaylor Simpson 
35645183ccdSTaylor Simpson     cc->class_by_name = hexagon_cpu_class_by_name;
35745183ccdSTaylor Simpson     cc->has_work = hexagon_cpu_has_work;
35845183ccdSTaylor Simpson     cc->dump_state = hexagon_dump_state;
35945183ccdSTaylor Simpson     cc->set_pc = hexagon_cpu_set_pc;
360e4fdf9dfSRichard Henderson     cc->get_pc = hexagon_cpu_get_pc;
36145183ccdSTaylor Simpson     cc->gdb_read_register = hexagon_gdb_read_register;
36245183ccdSTaylor Simpson     cc->gdb_write_register = hexagon_gdb_write_register;
363a1559537STaylor Simpson     cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS + NUM_VREGS + NUM_QREGS;
36445183ccdSTaylor Simpson     cc->gdb_stop_before_watchpoint = true;
36545183ccdSTaylor Simpson     cc->disas_set_info = hexagon_cpu_disas_set_info;
36645183ccdSTaylor Simpson     cc->tcg_ops = &hexagon_tcg_ops;
36745183ccdSTaylor Simpson }
36845183ccdSTaylor Simpson 
36945183ccdSTaylor Simpson #define DEFINE_CPU(type_name, initfn)      \
37045183ccdSTaylor Simpson     {                                      \
37145183ccdSTaylor Simpson         .name = type_name,                 \
37245183ccdSTaylor Simpson         .parent = TYPE_HEXAGON_CPU,        \
37345183ccdSTaylor Simpson         .instance_init = initfn            \
37445183ccdSTaylor Simpson     }
37545183ccdSTaylor Simpson 
37645183ccdSTaylor Simpson static const TypeInfo hexagon_cpu_type_infos[] = {
37745183ccdSTaylor Simpson     {
37845183ccdSTaylor Simpson         .name = TYPE_HEXAGON_CPU,
37945183ccdSTaylor Simpson         .parent = TYPE_CPU,
38045183ccdSTaylor Simpson         .instance_size = sizeof(HexagonCPU),
38145183ccdSTaylor Simpson         .instance_init = hexagon_cpu_init,
38245183ccdSTaylor Simpson         .abstract = true,
38345183ccdSTaylor Simpson         .class_size = sizeof(HexagonCPUClass),
38445183ccdSTaylor Simpson         .class_init = hexagon_cpu_class_init,
38545183ccdSTaylor Simpson     },
38645183ccdSTaylor Simpson     DEFINE_CPU(TYPE_HEXAGON_CPU_V67,              hexagon_v67_cpu_init),
387*fc2622f6STaylor Simpson     DEFINE_CPU(TYPE_HEXAGON_CPU_V68,              hexagon_v68_cpu_init),
388*fc2622f6STaylor Simpson     DEFINE_CPU(TYPE_HEXAGON_CPU_V69,              hexagon_v69_cpu_init),
389*fc2622f6STaylor Simpson     DEFINE_CPU(TYPE_HEXAGON_CPU_V71,              hexagon_v71_cpu_init),
390*fc2622f6STaylor Simpson     DEFINE_CPU(TYPE_HEXAGON_CPU_V73,              hexagon_v73_cpu_init),
39145183ccdSTaylor Simpson };
39245183ccdSTaylor Simpson 
39345183ccdSTaylor Simpson DEFINE_TYPES(hexagon_cpu_type_infos)
394