xref: /openbmc/qemu/target/hexagon/cpu.c (revision d5be19f5)
145183ccdSTaylor Simpson /*
2fc2622f6STaylor 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"
27b647652eSTaylor Simpson #include "exec/gdbstub.h"
2845183ccdSTaylor Simpson 
29fc2622f6STaylor Simpson static void hexagon_v67_cpu_init(Object *obj) { }
30fc2622f6STaylor Simpson static void hexagon_v68_cpu_init(Object *obj) { }
31fc2622f6STaylor Simpson static void hexagon_v69_cpu_init(Object *obj) { }
32fc2622f6STaylor Simpson static void hexagon_v71_cpu_init(Object *obj) { }
33fc2622f6STaylor Simpson static void hexagon_v73_cpu_init(Object *obj) { }
3445183ccdSTaylor Simpson 
35f0e0c984SMatheus Tavares Bernardino static void hexagon_cpu_list_entry(gpointer data, gpointer user_data)
36f0e0c984SMatheus Tavares Bernardino {
37f0e0c984SMatheus Tavares Bernardino     ObjectClass *oc = data;
38f0e0c984SMatheus Tavares Bernardino     char *name = g_strdup(object_class_get_name(oc));
39f0e0c984SMatheus Tavares Bernardino     if (g_str_has_suffix(name, HEXAGON_CPU_TYPE_SUFFIX)) {
40f0e0c984SMatheus Tavares Bernardino         name[strlen(name) - strlen(HEXAGON_CPU_TYPE_SUFFIX)] = '\0';
41f0e0c984SMatheus Tavares Bernardino     }
42f0e0c984SMatheus Tavares Bernardino     qemu_printf("  %s\n", name);
43f0e0c984SMatheus Tavares Bernardino     g_free(name);
44f0e0c984SMatheus Tavares Bernardino }
45f0e0c984SMatheus Tavares Bernardino 
46f0e0c984SMatheus Tavares Bernardino void hexagon_cpu_list(void)
47f0e0c984SMatheus Tavares Bernardino {
48f0e0c984SMatheus Tavares Bernardino     GSList *list;
49f0e0c984SMatheus Tavares Bernardino     list = object_class_get_list_sorted(TYPE_HEXAGON_CPU, false);
50f0e0c984SMatheus Tavares Bernardino     qemu_printf("Available CPUs:\n");
51f0e0c984SMatheus Tavares Bernardino     g_slist_foreach(list, hexagon_cpu_list_entry, NULL);
52f0e0c984SMatheus Tavares Bernardino     g_slist_free(list);
53f0e0c984SMatheus Tavares Bernardino }
54f0e0c984SMatheus Tavares Bernardino 
5545183ccdSTaylor Simpson static ObjectClass *hexagon_cpu_class_by_name(const char *cpu_model)
5645183ccdSTaylor Simpson {
5745183ccdSTaylor Simpson     ObjectClass *oc;
5845183ccdSTaylor Simpson     char *typename;
5945183ccdSTaylor Simpson     char **cpuname;
6045183ccdSTaylor Simpson 
6145183ccdSTaylor Simpson     cpuname = g_strsplit(cpu_model, ",", 1);
6245183ccdSTaylor Simpson     typename = g_strdup_printf(HEXAGON_CPU_TYPE_NAME("%s"), cpuname[0]);
6345183ccdSTaylor Simpson     oc = object_class_by_name(typename);
6445183ccdSTaylor Simpson     g_strfreev(cpuname);
6545183ccdSTaylor Simpson     g_free(typename);
66*d5be19f5SPhilippe Mathieu-Daudé 
6745183ccdSTaylor Simpson     return oc;
6845183ccdSTaylor Simpson }
6945183ccdSTaylor Simpson 
7045183ccdSTaylor Simpson static Property hexagon_lldb_compat_property =
7145183ccdSTaylor Simpson     DEFINE_PROP_BOOL("lldb-compat", HexagonCPU, lldb_compat, false);
7245183ccdSTaylor Simpson static Property hexagon_lldb_stack_adjust_property =
7345183ccdSTaylor Simpson     DEFINE_PROP_UNSIGNED("lldb-stack-adjust", HexagonCPU, lldb_stack_adjust,
7445183ccdSTaylor Simpson                          0, qdev_prop_uint32, target_ulong);
75d54c5615STaylor Simpson static Property hexagon_short_circuit_property =
76d54c5615STaylor Simpson     DEFINE_PROP_BOOL("short-circuit", HexagonCPU, short_circuit, true);
7745183ccdSTaylor Simpson 
7845183ccdSTaylor Simpson const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS] = {
7945183ccdSTaylor Simpson    "r0", "r1",  "r2",  "r3",  "r4",   "r5",  "r6",  "r7",
8045183ccdSTaylor Simpson    "r8", "r9",  "r10", "r11", "r12",  "r13", "r14", "r15",
8145183ccdSTaylor Simpson   "r16", "r17", "r18", "r19", "r20",  "r21", "r22", "r23",
8245183ccdSTaylor Simpson   "r24", "r25", "r26", "r27", "r28",  "r29", "r30", "r31",
8345183ccdSTaylor Simpson   "sa0", "lc0", "sa1", "lc1", "p3_0", "c5",  "m0",  "m1",
8445183ccdSTaylor Simpson   "usr", "pc",  "ugp", "gp",  "cs0",  "cs1", "c14", "c15",
8540438b67STaylor Simpson   "c16", "c17", "c18", "c19", "pkt_cnt",  "insn_cnt", "hvx_cnt", "c23",
8645183ccdSTaylor Simpson   "c24", "c25", "c26", "c27", "c28",  "c29", "c30", "c31",
8745183ccdSTaylor Simpson };
8845183ccdSTaylor Simpson 
8945183ccdSTaylor Simpson /*
9045183ccdSTaylor Simpson  * One of the main debugging techniques is to use "-d cpu" and compare against
9145183ccdSTaylor Simpson  * LLDB output when single stepping.  However, the target and qemu put the
9245183ccdSTaylor Simpson  * stacks at different locations.  This is used to compensate so the diff is
9345183ccdSTaylor Simpson  * cleaner.
9445183ccdSTaylor Simpson  */
952d27cebbSTaylor Simpson static target_ulong adjust_stack_ptrs(CPUHexagonState *env, target_ulong addr)
9645183ccdSTaylor Simpson {
977d9ab202STaylor Simpson     HexagonCPU *cpu = env_archcpu(env);
9845183ccdSTaylor Simpson     target_ulong stack_adjust = cpu->lldb_stack_adjust;
9945183ccdSTaylor Simpson     target_ulong stack_start = env->stack_start;
10045183ccdSTaylor Simpson     target_ulong stack_size = 0x10000;
10145183ccdSTaylor Simpson 
10245183ccdSTaylor Simpson     if (stack_adjust == 0) {
10345183ccdSTaylor Simpson         return addr;
10445183ccdSTaylor Simpson     }
10545183ccdSTaylor Simpson 
10645183ccdSTaylor Simpson     if (stack_start + 0x1000 >= addr && addr >= (stack_start - stack_size)) {
10745183ccdSTaylor Simpson         return addr - stack_adjust;
10845183ccdSTaylor Simpson     }
10945183ccdSTaylor Simpson     return addr;
11045183ccdSTaylor Simpson }
11145183ccdSTaylor Simpson 
11272895676SMukilan Thiyagarajan /* HEX_REG_P3_0_ALIASED (aka C4) is an alias for the predicate registers */
1132d27cebbSTaylor Simpson static target_ulong read_p3_0(CPUHexagonState *env)
11445183ccdSTaylor Simpson {
11545183ccdSTaylor Simpson     int32_t control_reg = 0;
11645183ccdSTaylor Simpson     int i;
11745183ccdSTaylor Simpson     for (i = NUM_PREGS - 1; i >= 0; i--) {
11845183ccdSTaylor Simpson         control_reg <<= 8;
11945183ccdSTaylor Simpson         control_reg |= env->pred[i] & 0xff;
12045183ccdSTaylor Simpson     }
12145183ccdSTaylor Simpson     return control_reg;
12245183ccdSTaylor Simpson }
12345183ccdSTaylor Simpson 
12445183ccdSTaylor Simpson static void print_reg(FILE *f, CPUHexagonState *env, int regnum)
12545183ccdSTaylor Simpson {
12645183ccdSTaylor Simpson     target_ulong value;
12745183ccdSTaylor Simpson 
12872895676SMukilan Thiyagarajan     if (regnum == HEX_REG_P3_0_ALIASED) {
12945183ccdSTaylor Simpson         value = read_p3_0(env);
13045183ccdSTaylor Simpson     } else {
13145183ccdSTaylor Simpson         value = regnum < 32 ? adjust_stack_ptrs(env, env->gpr[regnum])
13245183ccdSTaylor Simpson                             : env->gpr[regnum];
13345183ccdSTaylor Simpson     }
13445183ccdSTaylor Simpson 
13545183ccdSTaylor Simpson     qemu_fprintf(f, "  %s = 0x" TARGET_FMT_lx "\n",
13645183ccdSTaylor Simpson                  hexagon_regnames[regnum], value);
13745183ccdSTaylor Simpson }
13845183ccdSTaylor Simpson 
139a1559537STaylor Simpson static void print_vreg(FILE *f, CPUHexagonState *env, int regnum,
140a1559537STaylor Simpson                        bool skip_if_zero)
141a1559537STaylor Simpson {
142a1559537STaylor Simpson     if (skip_if_zero) {
143a1559537STaylor Simpson         bool nonzero_found = false;
144a1559537STaylor Simpson         for (int i = 0; i < MAX_VEC_SIZE_BYTES; i++) {
145a1559537STaylor Simpson             if (env->VRegs[regnum].ub[i] != 0) {
146a1559537STaylor Simpson                 nonzero_found = true;
147a1559537STaylor Simpson                 break;
148a1559537STaylor Simpson             }
149a1559537STaylor Simpson         }
150a1559537STaylor Simpson         if (!nonzero_found) {
151a1559537STaylor Simpson             return;
152a1559537STaylor Simpson         }
153a1559537STaylor Simpson     }
154a1559537STaylor Simpson 
155a1559537STaylor Simpson     qemu_fprintf(f, "  v%d = ( ", regnum);
156a1559537STaylor Simpson     qemu_fprintf(f, "0x%02x", env->VRegs[regnum].ub[MAX_VEC_SIZE_BYTES - 1]);
157a1559537STaylor Simpson     for (int i = MAX_VEC_SIZE_BYTES - 2; i >= 0; i--) {
158a1559537STaylor Simpson         qemu_fprintf(f, ", 0x%02x", env->VRegs[regnum].ub[i]);
159a1559537STaylor Simpson     }
160a1559537STaylor Simpson     qemu_fprintf(f, " )\n");
161a1559537STaylor Simpson }
162a1559537STaylor Simpson 
163a1559537STaylor Simpson void hexagon_debug_vreg(CPUHexagonState *env, int regnum)
164a1559537STaylor Simpson {
165a1559537STaylor Simpson     print_vreg(stdout, env, regnum, false);
166a1559537STaylor Simpson }
167a1559537STaylor Simpson 
168a1559537STaylor Simpson static void print_qreg(FILE *f, CPUHexagonState *env, int regnum,
169a1559537STaylor Simpson                        bool skip_if_zero)
170a1559537STaylor Simpson {
171a1559537STaylor Simpson     if (skip_if_zero) {
172a1559537STaylor Simpson         bool nonzero_found = false;
173a1559537STaylor Simpson         for (int i = 0; i < MAX_VEC_SIZE_BYTES / 8; i++) {
174a1559537STaylor Simpson             if (env->QRegs[regnum].ub[i] != 0) {
175a1559537STaylor Simpson                 nonzero_found = true;
176a1559537STaylor Simpson                 break;
177a1559537STaylor Simpson             }
178a1559537STaylor Simpson         }
179a1559537STaylor Simpson         if (!nonzero_found) {
180a1559537STaylor Simpson             return;
181a1559537STaylor Simpson         }
182a1559537STaylor Simpson     }
183a1559537STaylor Simpson 
184a1559537STaylor Simpson     qemu_fprintf(f, "  q%d = ( ", regnum);
185a1559537STaylor Simpson     qemu_fprintf(f, "0x%02x",
186a1559537STaylor Simpson                  env->QRegs[regnum].ub[MAX_VEC_SIZE_BYTES / 8 - 1]);
187a1559537STaylor Simpson     for (int i = MAX_VEC_SIZE_BYTES / 8 - 2; i >= 0; i--) {
188a1559537STaylor Simpson         qemu_fprintf(f, ", 0x%02x", env->QRegs[regnum].ub[i]);
189a1559537STaylor Simpson     }
190a1559537STaylor Simpson     qemu_fprintf(f, " )\n");
191a1559537STaylor Simpson }
192a1559537STaylor Simpson 
193a1559537STaylor Simpson void hexagon_debug_qreg(CPUHexagonState *env, int regnum)
194a1559537STaylor Simpson {
195a1559537STaylor Simpson     print_qreg(stdout, env, regnum, false);
196a1559537STaylor Simpson }
197a1559537STaylor Simpson 
198a1559537STaylor Simpson static void hexagon_dump(CPUHexagonState *env, FILE *f, int flags)
19945183ccdSTaylor Simpson {
2007d9ab202STaylor Simpson     HexagonCPU *cpu = env_archcpu(env);
20145183ccdSTaylor Simpson 
20245183ccdSTaylor Simpson     if (cpu->lldb_compat) {
20345183ccdSTaylor Simpson         /*
20445183ccdSTaylor Simpson          * When comparing with LLDB, it doesn't step through single-cycle
20545183ccdSTaylor Simpson          * hardware loops the same way.  So, we just skip them here
20645183ccdSTaylor Simpson          */
20745183ccdSTaylor Simpson         if (env->gpr[HEX_REG_PC] == env->last_pc_dumped) {
20845183ccdSTaylor Simpson             return;
20945183ccdSTaylor Simpson         }
21045183ccdSTaylor Simpson         env->last_pc_dumped = env->gpr[HEX_REG_PC];
21145183ccdSTaylor Simpson     }
21245183ccdSTaylor Simpson 
21345183ccdSTaylor Simpson     qemu_fprintf(f, "General Purpose Registers = {\n");
21445183ccdSTaylor Simpson     for (int i = 0; i < 32; i++) {
21545183ccdSTaylor Simpson         print_reg(f, env, i);
21645183ccdSTaylor Simpson     }
21745183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_SA0);
21845183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_LC0);
21945183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_SA1);
22045183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_LC1);
22145183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_M0);
22245183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_M1);
22345183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_USR);
22472895676SMukilan Thiyagarajan     print_reg(f, env, HEX_REG_P3_0_ALIASED);
22545183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_GP);
22645183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_UGP);
22745183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_PC);
22845183ccdSTaylor Simpson #ifdef CONFIG_USER_ONLY
22945183ccdSTaylor Simpson     /*
23045183ccdSTaylor Simpson      * Not modelled in user mode, print junk to minimize the diff's
23145183ccdSTaylor Simpson      * with LLDB output
23245183ccdSTaylor Simpson      */
23345183ccdSTaylor Simpson     qemu_fprintf(f, "  cause = 0x000000db\n");
23445183ccdSTaylor Simpson     qemu_fprintf(f, "  badva = 0x00000000\n");
23545183ccdSTaylor Simpson     qemu_fprintf(f, "  cs0 = 0x00000000\n");
23645183ccdSTaylor Simpson     qemu_fprintf(f, "  cs1 = 0x00000000\n");
23745183ccdSTaylor Simpson #else
23845183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_CAUSE);
23945183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_BADVA);
24045183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_CS0);
24145183ccdSTaylor Simpson     print_reg(f, env, HEX_REG_CS1);
24245183ccdSTaylor Simpson #endif
24345183ccdSTaylor Simpson     qemu_fprintf(f, "}\n");
244a1559537STaylor Simpson 
245a1559537STaylor Simpson     if (flags & CPU_DUMP_FPU) {
246a1559537STaylor Simpson         qemu_fprintf(f, "Vector Registers = {\n");
247a1559537STaylor Simpson         for (int i = 0; i < NUM_VREGS; i++) {
248a1559537STaylor Simpson             print_vreg(f, env, i, true);
249a1559537STaylor Simpson         }
250a1559537STaylor Simpson         for (int i = 0; i < NUM_QREGS; i++) {
251a1559537STaylor Simpson             print_qreg(f, env, i, true);
252a1559537STaylor Simpson         }
253a1559537STaylor Simpson         qemu_fprintf(f, "}\n");
254a1559537STaylor Simpson     }
25545183ccdSTaylor Simpson }
25645183ccdSTaylor Simpson 
25745183ccdSTaylor Simpson static void hexagon_dump_state(CPUState *cs, FILE *f, int flags)
25845183ccdSTaylor Simpson {
25945183ccdSTaylor Simpson     HexagonCPU *cpu = HEXAGON_CPU(cs);
26045183ccdSTaylor Simpson     CPUHexagonState *env = &cpu->env;
26145183ccdSTaylor Simpson 
262a1559537STaylor Simpson     hexagon_dump(env, f, flags);
26345183ccdSTaylor Simpson }
26445183ccdSTaylor Simpson 
26545183ccdSTaylor Simpson void hexagon_debug(CPUHexagonState *env)
26645183ccdSTaylor Simpson {
267a1559537STaylor Simpson     hexagon_dump(env, stdout, CPU_DUMP_FPU);
26845183ccdSTaylor Simpson }
26945183ccdSTaylor Simpson 
27045183ccdSTaylor Simpson static void hexagon_cpu_set_pc(CPUState *cs, vaddr value)
27145183ccdSTaylor Simpson {
27245183ccdSTaylor Simpson     HexagonCPU *cpu = HEXAGON_CPU(cs);
27345183ccdSTaylor Simpson     CPUHexagonState *env = &cpu->env;
27445183ccdSTaylor Simpson     env->gpr[HEX_REG_PC] = value;
27545183ccdSTaylor Simpson }
27645183ccdSTaylor Simpson 
277e4fdf9dfSRichard Henderson static vaddr hexagon_cpu_get_pc(CPUState *cs)
278e4fdf9dfSRichard Henderson {
279e4fdf9dfSRichard Henderson     HexagonCPU *cpu = HEXAGON_CPU(cs);
280e4fdf9dfSRichard Henderson     CPUHexagonState *env = &cpu->env;
281e4fdf9dfSRichard Henderson     return env->gpr[HEX_REG_PC];
282e4fdf9dfSRichard Henderson }
283e4fdf9dfSRichard Henderson 
28445183ccdSTaylor Simpson static void hexagon_cpu_synchronize_from_tb(CPUState *cs,
28545183ccdSTaylor Simpson                                             const TranslationBlock *tb)
28645183ccdSTaylor Simpson {
28745183ccdSTaylor Simpson     HexagonCPU *cpu = HEXAGON_CPU(cs);
28845183ccdSTaylor Simpson     CPUHexagonState *env = &cpu->env;
289ba445655SAnton Johansson     tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
290ba445655SAnton Johansson     env->gpr[HEX_REG_PC] = tb->pc;
29145183ccdSTaylor Simpson }
29245183ccdSTaylor Simpson 
29345183ccdSTaylor Simpson static bool hexagon_cpu_has_work(CPUState *cs)
29445183ccdSTaylor Simpson {
29545183ccdSTaylor Simpson     return true;
29645183ccdSTaylor Simpson }
29745183ccdSTaylor Simpson 
29890157814SRichard Henderson static void hexagon_restore_state_to_opc(CPUState *cs,
29990157814SRichard Henderson                                          const TranslationBlock *tb,
30090157814SRichard Henderson                                          const uint64_t *data)
30145183ccdSTaylor Simpson {
30290157814SRichard Henderson     HexagonCPU *cpu = HEXAGON_CPU(cs);
30390157814SRichard Henderson     CPUHexagonState *env = &cpu->env;
30490157814SRichard Henderson 
30545183ccdSTaylor Simpson     env->gpr[HEX_REG_PC] = data[0];
30645183ccdSTaylor Simpson }
30745183ccdSTaylor Simpson 
308ab85156dSPeter Maydell static void hexagon_cpu_reset_hold(Object *obj)
30945183ccdSTaylor Simpson {
310ab85156dSPeter Maydell     CPUState *cs = CPU(obj);
31145183ccdSTaylor Simpson     HexagonCPU *cpu = HEXAGON_CPU(cs);
31245183ccdSTaylor Simpson     HexagonCPUClass *mcc = HEXAGON_CPU_GET_CLASS(cpu);
313c0336c87STaylor Simpson     CPUHexagonState *env = &cpu->env;
31445183ccdSTaylor Simpson 
315ab85156dSPeter Maydell     if (mcc->parent_phases.hold) {
316ab85156dSPeter Maydell         mcc->parent_phases.hold(obj);
317ab85156dSPeter Maydell     }
318c0336c87STaylor Simpson 
319c0336c87STaylor Simpson     set_default_nan_mode(1, &env->fp_status);
320c0336c87STaylor Simpson     set_float_detect_tininess(float_tininess_before_rounding, &env->fp_status);
32145183ccdSTaylor Simpson }
32245183ccdSTaylor Simpson 
32345183ccdSTaylor Simpson static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
32445183ccdSTaylor Simpson {
32545183ccdSTaylor Simpson     info->print_insn = print_insn_hexagon;
32645183ccdSTaylor Simpson }
32745183ccdSTaylor Simpson 
32845183ccdSTaylor Simpson static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
32945183ccdSTaylor Simpson {
33045183ccdSTaylor Simpson     CPUState *cs = CPU(dev);
33145183ccdSTaylor Simpson     HexagonCPUClass *mcc = HEXAGON_CPU_GET_CLASS(dev);
33245183ccdSTaylor Simpson     Error *local_err = NULL;
33345183ccdSTaylor Simpson 
33445183ccdSTaylor Simpson     cpu_exec_realizefn(cs, &local_err);
33545183ccdSTaylor Simpson     if (local_err != NULL) {
33645183ccdSTaylor Simpson         error_propagate(errp, local_err);
33745183ccdSTaylor Simpson         return;
33845183ccdSTaylor Simpson     }
33945183ccdSTaylor Simpson 
340b647652eSTaylor Simpson     gdb_register_coprocessor(cs, hexagon_hvx_gdb_read_register,
341b647652eSTaylor Simpson                              hexagon_hvx_gdb_write_register,
342b647652eSTaylor Simpson                              NUM_VREGS + NUM_QREGS,
343b647652eSTaylor Simpson                              "hexagon-hvx.xml", 0);
344b647652eSTaylor Simpson 
34545183ccdSTaylor Simpson     qemu_init_vcpu(cs);
34645183ccdSTaylor Simpson     cpu_reset(cs);
34745183ccdSTaylor Simpson 
34845183ccdSTaylor Simpson     mcc->parent_realize(dev, errp);
34945183ccdSTaylor Simpson }
35045183ccdSTaylor Simpson 
35145183ccdSTaylor Simpson static void hexagon_cpu_init(Object *obj)
35245183ccdSTaylor Simpson {
35345183ccdSTaylor Simpson     qdev_property_add_static(DEVICE(obj), &hexagon_lldb_compat_property);
35445183ccdSTaylor Simpson     qdev_property_add_static(DEVICE(obj), &hexagon_lldb_stack_adjust_property);
355d54c5615STaylor Simpson     qdev_property_add_static(DEVICE(obj), &hexagon_short_circuit_property);
35645183ccdSTaylor Simpson }
35745183ccdSTaylor Simpson 
35845183ccdSTaylor Simpson #include "hw/core/tcg-cpu-ops.h"
35945183ccdSTaylor Simpson 
36011906557SRichard Henderson static const struct TCGCPUOps hexagon_tcg_ops = {
36145183ccdSTaylor Simpson     .initialize = hexagon_translate_init,
36245183ccdSTaylor Simpson     .synchronize_from_tb = hexagon_cpu_synchronize_from_tb,
36390157814SRichard Henderson     .restore_state_to_opc = hexagon_restore_state_to_opc,
36445183ccdSTaylor Simpson };
36545183ccdSTaylor Simpson 
36645183ccdSTaylor Simpson static void hexagon_cpu_class_init(ObjectClass *c, void *data)
36745183ccdSTaylor Simpson {
36845183ccdSTaylor Simpson     HexagonCPUClass *mcc = HEXAGON_CPU_CLASS(c);
36945183ccdSTaylor Simpson     CPUClass *cc = CPU_CLASS(c);
37045183ccdSTaylor Simpson     DeviceClass *dc = DEVICE_CLASS(c);
371ab85156dSPeter Maydell     ResettableClass *rc = RESETTABLE_CLASS(c);
37245183ccdSTaylor Simpson 
37345183ccdSTaylor Simpson     device_class_set_parent_realize(dc, hexagon_cpu_realize,
37445183ccdSTaylor Simpson                                     &mcc->parent_realize);
37545183ccdSTaylor Simpson 
376ab85156dSPeter Maydell     resettable_class_set_parent_phases(rc, NULL, hexagon_cpu_reset_hold, NULL,
377ab85156dSPeter Maydell                                        &mcc->parent_phases);
37845183ccdSTaylor Simpson 
37945183ccdSTaylor Simpson     cc->class_by_name = hexagon_cpu_class_by_name;
38045183ccdSTaylor Simpson     cc->has_work = hexagon_cpu_has_work;
38145183ccdSTaylor Simpson     cc->dump_state = hexagon_dump_state;
38245183ccdSTaylor Simpson     cc->set_pc = hexagon_cpu_set_pc;
383e4fdf9dfSRichard Henderson     cc->get_pc = hexagon_cpu_get_pc;
38445183ccdSTaylor Simpson     cc->gdb_read_register = hexagon_gdb_read_register;
38545183ccdSTaylor Simpson     cc->gdb_write_register = hexagon_gdb_write_register;
386ab930e80SMatheus Tavares Bernardino     cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS;
38745183ccdSTaylor Simpson     cc->gdb_stop_before_watchpoint = true;
388ab930e80SMatheus Tavares Bernardino     cc->gdb_core_xml_file = "hexagon-core.xml";
38945183ccdSTaylor Simpson     cc->disas_set_info = hexagon_cpu_disas_set_info;
39045183ccdSTaylor Simpson     cc->tcg_ops = &hexagon_tcg_ops;
39145183ccdSTaylor Simpson }
39245183ccdSTaylor Simpson 
39345183ccdSTaylor Simpson #define DEFINE_CPU(type_name, initfn)      \
39445183ccdSTaylor Simpson     {                                      \
39545183ccdSTaylor Simpson         .name = type_name,                 \
39645183ccdSTaylor Simpson         .parent = TYPE_HEXAGON_CPU,        \
39745183ccdSTaylor Simpson         .instance_init = initfn            \
39845183ccdSTaylor Simpson     }
39945183ccdSTaylor Simpson 
40045183ccdSTaylor Simpson static const TypeInfo hexagon_cpu_type_infos[] = {
40145183ccdSTaylor Simpson     {
40245183ccdSTaylor Simpson         .name = TYPE_HEXAGON_CPU,
40345183ccdSTaylor Simpson         .parent = TYPE_CPU,
40445183ccdSTaylor Simpson         .instance_size = sizeof(HexagonCPU),
405f669c992SRichard Henderson         .instance_align = __alignof(HexagonCPU),
40645183ccdSTaylor Simpson         .instance_init = hexagon_cpu_init,
40745183ccdSTaylor Simpson         .abstract = true,
40845183ccdSTaylor Simpson         .class_size = sizeof(HexagonCPUClass),
40945183ccdSTaylor Simpson         .class_init = hexagon_cpu_class_init,
41045183ccdSTaylor Simpson     },
41145183ccdSTaylor Simpson     DEFINE_CPU(TYPE_HEXAGON_CPU_V67,              hexagon_v67_cpu_init),
412fc2622f6STaylor Simpson     DEFINE_CPU(TYPE_HEXAGON_CPU_V68,              hexagon_v68_cpu_init),
413fc2622f6STaylor Simpson     DEFINE_CPU(TYPE_HEXAGON_CPU_V69,              hexagon_v69_cpu_init),
414fc2622f6STaylor Simpson     DEFINE_CPU(TYPE_HEXAGON_CPU_V71,              hexagon_v71_cpu_init),
415fc2622f6STaylor Simpson     DEFINE_CPU(TYPE_HEXAGON_CPU_V73,              hexagon_v73_cpu_init),
41645183ccdSTaylor Simpson };
41745183ccdSTaylor Simpson 
41845183ccdSTaylor Simpson DEFINE_TYPES(hexagon_cpu_type_infos)
419