| /* |
| * Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include "qemu/osdep.h" |
| #include "gdbstub/helpers.h" |
| #include "cpu.h" |
| #include "internal.h" |
| |
| int hexagon_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) |
| { |
| CPUHexagonState *env = cpu_env(cs); |
| |
| if (n == HEX_REG_P3_0_ALIASED) { |
| uint32_t p3_0 = 0; |
| for (int i = 0; i < NUM_PREGS; i++) { |
| p3_0 = deposit32(p3_0, i * 8, 8, env->pred[i]); |
| } |
| return gdb_get_regl(mem_buf, p3_0); |
| } |
| |
| if (n < TOTAL_PER_THREAD_REGS) { |
| return gdb_get_regl(mem_buf, env->gpr[n]); |
| } |
| |
| n -= TOTAL_PER_THREAD_REGS; |
| |
| if (n < NUM_PREGS) { |
| return gdb_get_reg8(mem_buf, env->pred[n]); |
| } |
| |
| n -= NUM_PREGS; |
| |
| g_assert_not_reached(); |
| } |
| |
| int hexagon_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) |
| { |
| CPUHexagonState *env = cpu_env(cs); |
| |
| if (n == HEX_REG_P3_0_ALIASED) { |
| uint32_t p3_0 = ldtul_p(mem_buf); |
| for (int i = 0; i < NUM_PREGS; i++) { |
| env->pred[i] = extract32(p3_0, i * 8, 8); |
| } |
| return sizeof(target_ulong); |
| } |
| |
| if (n < TOTAL_PER_THREAD_REGS) { |
| env->gpr[n] = ldtul_p(mem_buf); |
| return sizeof(target_ulong); |
| } |
| |
| n -= TOTAL_PER_THREAD_REGS; |
| |
| if (n < NUM_PREGS) { |
| env->pred[n] = ldtul_p(mem_buf) & 0xff; |
| return sizeof(uint8_t); |
| } |
| |
| n -= NUM_PREGS; |
| |
| g_assert_not_reached(); |
| } |
| |
| static int gdb_get_vreg(CPUHexagonState *env, GByteArray *mem_buf, int n) |
| { |
| int total = 0; |
| int i; |
| for (i = 0; i < ARRAY_SIZE(env->VRegs[n].uw); i++) { |
| total += gdb_get_regl(mem_buf, env->VRegs[n].uw[i]); |
| } |
| return total; |
| } |
| |
| static int gdb_get_qreg(CPUHexagonState *env, GByteArray *mem_buf, int n) |
| { |
| int total = 0; |
| int i; |
| for (i = 0; i < ARRAY_SIZE(env->QRegs[n].uw); i++) { |
| total += gdb_get_regl(mem_buf, env->QRegs[n].uw[i]); |
| } |
| return total; |
| } |
| |
| int hexagon_hvx_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) |
| { |
| HexagonCPU *cpu = HEXAGON_CPU(cs); |
| CPUHexagonState *env = &cpu->env; |
| |
| if (n < NUM_VREGS) { |
| return gdb_get_vreg(env, mem_buf, n); |
| } |
| n -= NUM_VREGS; |
| |
| if (n < NUM_QREGS) { |
| return gdb_get_qreg(env, mem_buf, n); |
| } |
| |
| g_assert_not_reached(); |
| } |
| |
| static int gdb_put_vreg(CPUHexagonState *env, uint8_t *mem_buf, int n) |
| { |
| int i; |
| for (i = 0; i < ARRAY_SIZE(env->VRegs[n].uw); i++) { |
| env->VRegs[n].uw[i] = ldtul_p(mem_buf); |
| mem_buf += 4; |
| } |
| return MAX_VEC_SIZE_BYTES; |
| } |
| |
| static int gdb_put_qreg(CPUHexagonState *env, uint8_t *mem_buf, int n) |
| { |
| int i; |
| for (i = 0; i < ARRAY_SIZE(env->QRegs[n].uw); i++) { |
| env->QRegs[n].uw[i] = ldtul_p(mem_buf); |
| mem_buf += 4; |
| } |
| return MAX_VEC_SIZE_BYTES / 8; |
| } |
| |
| int hexagon_hvx_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) |
| { |
| HexagonCPU *cpu = HEXAGON_CPU(cs); |
| CPUHexagonState *env = &cpu->env; |
| |
| if (n < NUM_VREGS) { |
| return gdb_put_vreg(env, mem_buf, n); |
| } |
| n -= NUM_VREGS; |
| |
| if (n < NUM_QREGS) { |
| return gdb_put_qreg(env, mem_buf, n); |
| } |
| |
| g_assert_not_reached(); |
| } |