aboutsummaryrefslogtreecommitdiff
path: root/target/hexagon/cpu.c
diff options
context:
space:
mode:
authorTaylor Simpson <tsimpson@quicinc.com>2021-03-17 11:48:57 -0500
committerTaylor Simpson <tsimpson@quicinc.com>2021-11-03 16:01:26 -0500
commita1559537d183bf1f4e2cfef972610c8c9e1a6aa5 (patch)
tree9e4f7493e67621802ca4d0d1395f4ce7010f9ac5 /target/hexagon/cpu.c
parent375bcf389f1e5f8c3bde70b3f8c847fdd73074c0 (diff)
Hexagon HVX (target/hexagon) add Hexagon Vector eXtensions (HVX) to core
HVX is a set of wide vector instructions. Machine state includes vector registers (VRegs) vector predicate registers (QRegs) temporary registers for intermediate values store buffer (masked stores and scatter/gather) Acked-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
Diffstat (limited to 'target/hexagon/cpu.c')
-rw-r--r--target/hexagon/cpu.c78
1 files changed, 74 insertions, 4 deletions
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 3338365c16..989bd767b5 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -113,7 +113,66 @@ static void print_reg(FILE *f, CPUHexagonState *env, int regnum)
hexagon_regnames[regnum], value);
}
-static void hexagon_dump(CPUHexagonState *env, FILE *f)
+static void print_vreg(FILE *f, CPUHexagonState *env, int regnum,
+ bool skip_if_zero)
+{
+ if (skip_if_zero) {
+ bool nonzero_found = false;
+ for (int i = 0; i < MAX_VEC_SIZE_BYTES; i++) {
+ if (env->VRegs[regnum].ub[i] != 0) {
+ nonzero_found = true;
+ break;
+ }
+ }
+ if (!nonzero_found) {
+ return;
+ }
+ }
+
+ qemu_fprintf(f, " v%d = ( ", regnum);
+ qemu_fprintf(f, "0x%02x", env->VRegs[regnum].ub[MAX_VEC_SIZE_BYTES - 1]);
+ for (int i = MAX_VEC_SIZE_BYTES - 2; i >= 0; i--) {
+ qemu_fprintf(f, ", 0x%02x", env->VRegs[regnum].ub[i]);
+ }
+ qemu_fprintf(f, " )\n");
+}
+
+void hexagon_debug_vreg(CPUHexagonState *env, int regnum)
+{
+ print_vreg(stdout, env, regnum, false);
+}
+
+static void print_qreg(FILE *f, CPUHexagonState *env, int regnum,
+ bool skip_if_zero)
+{
+ if (skip_if_zero) {
+ bool nonzero_found = false;
+ for (int i = 0; i < MAX_VEC_SIZE_BYTES / 8; i++) {
+ if (env->QRegs[regnum].ub[i] != 0) {
+ nonzero_found = true;
+ break;
+ }
+ }
+ if (!nonzero_found) {
+ return;
+ }
+ }
+
+ qemu_fprintf(f, " q%d = ( ", regnum);
+ qemu_fprintf(f, "0x%02x",
+ env->QRegs[regnum].ub[MAX_VEC_SIZE_BYTES / 8 - 1]);
+ for (int i = MAX_VEC_SIZE_BYTES / 8 - 2; i >= 0; i--) {
+ qemu_fprintf(f, ", 0x%02x", env->QRegs[regnum].ub[i]);
+ }
+ qemu_fprintf(f, " )\n");
+}
+
+void hexagon_debug_qreg(CPUHexagonState *env, int regnum)
+{
+ print_qreg(stdout, env, regnum, false);
+}
+
+static void hexagon_dump(CPUHexagonState *env, FILE *f, int flags)
{
HexagonCPU *cpu = env_archcpu(env);
@@ -159,6 +218,17 @@ static void hexagon_dump(CPUHexagonState *env, FILE *f)
print_reg(f, env, HEX_REG_CS1);
#endif
qemu_fprintf(f, "}\n");
+
+ if (flags & CPU_DUMP_FPU) {
+ qemu_fprintf(f, "Vector Registers = {\n");
+ for (int i = 0; i < NUM_VREGS; i++) {
+ print_vreg(f, env, i, true);
+ }
+ for (int i = 0; i < NUM_QREGS; i++) {
+ print_qreg(f, env, i, true);
+ }
+ qemu_fprintf(f, "}\n");
+ }
}
static void hexagon_dump_state(CPUState *cs, FILE *f, int flags)
@@ -166,12 +236,12 @@ static void hexagon_dump_state(CPUState *cs, FILE *f, int flags)
HexagonCPU *cpu = HEXAGON_CPU(cs);
CPUHexagonState *env = &cpu->env;
- hexagon_dump(env, f);
+ hexagon_dump(env, f, flags);
}
void hexagon_debug(CPUHexagonState *env)
{
- hexagon_dump(env, stdout);
+ hexagon_dump(env, stdout, CPU_DUMP_FPU);
}
static void hexagon_cpu_set_pc(CPUState *cs, vaddr value)
@@ -292,7 +362,7 @@ static void hexagon_cpu_class_init(ObjectClass *c, void *data)
cc->set_pc = hexagon_cpu_set_pc;
cc->gdb_read_register = hexagon_gdb_read_register;
cc->gdb_write_register = hexagon_gdb_write_register;
- cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS;
+ cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS + NUM_VREGS + NUM_QREGS;
cc->gdb_stop_before_watchpoint = true;
cc->disas_set_info = hexagon_cpu_disas_set_info;
cc->tcg_ops = &hexagon_tcg_ops;