/* * TriCore gdb server stub * * Copyright (c) 2019 Bastian Koppelmann, Paderborn University * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include "qemu/osdep.h" #include "qemu-common.h" #include "exec/gdbstub.h" #define LCX_REGNUM 32 #define FCX_REGNUM 33 #define PCXI_REGNUM 34 #define TRICORE_PSW_REGNUM 35 #define TRICORE_PC_REGNUM 36 #define ICR_REGNUM 37 #define ISP_REGNUM 38 #define BTV_REGNUM 39 #define BIV_REGNUM 40 #define SYSCON_REGNUM 41 #define PMUCON0_REGNUM 42 #define DMUCON_REGNUM 43 static uint32_t tricore_cpu_gdb_read_csfr(CPUTriCoreState *env, int n) { switch (n) { case LCX_REGNUM: return env->LCX; case FCX_REGNUM: return env->FCX; case PCXI_REGNUM: return env->PCXI; case TRICORE_PSW_REGNUM: return psw_read(env); case TRICORE_PC_REGNUM: return env->PC; case ICR_REGNUM: return env->ICR; case ISP_REGNUM: return env->ISP; case BTV_REGNUM: return env->BTV; case BIV_REGNUM: return env->BIV; case SYSCON_REGNUM: return env->SYSCON; case PMUCON0_REGNUM: return 0; /* PMUCON0 */ case DMUCON_REGNUM: return 0; /* DMUCON0 */ default: return 0; } } static void tricore_cpu_gdb_write_csfr(CPUTriCoreState *env, int n, uint32_t val) { switch (n) { case LCX_REGNUM: env->LCX = val; break; case FCX_REGNUM: env->FCX = val; break; case PCXI_REGNUM: env->PCXI = val; break; case TRICORE_PSW_REGNUM: psw_write(env, val); break; case TRICORE_PC_REGNUM: env->PC = val; break; case ICR_REGNUM: env->ICR = val; break; case ISP_REGNUM: env->ISP = val; break; case BTV_REGNUM: env->BTV = val; break; case BIV_REGNUM: env->BIV = val; break; case SYSCON_REGNUM: env->SYSCON = val; break; } } int tricore_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) { TriCoreCPU *cpu = TRICORE_CPU(cs); CPUTriCoreState *env = &cpu->env; if (n < 16) { /* data registers */ return gdb_get_reg32(mem_buf, env->gpr_d[n]); } else if (n < 32) { /* address registers */ return gdb_get_reg32(mem_buf, env->gpr_a[n - 16]); } else { /* csfr */ return gdb_get_reg32(mem_buf, tricore_cpu_gdb_read_csfr(env, n)); } return 0; } int tricore_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { TriCoreCPU *cpu = TRICORE_CPU(cs); CPUTriCoreState *env = &cpu->env; uint32_t tmp; tmp = ldl_p(mem_buf); if (n < 16) { /* data registers */ env->gpr_d[n] = tmp; } else if (n < 32) { /* address registers */ env->gpr_d[n - 16] = tmp; } else { tricore_cpu_gdb_write_csfr(env, n, tmp); } return 4; }