1ca61e750SXiaojuan Yang /* 2ca61e750SXiaojuan Yang * LOONGARCH gdb server stub 3ca61e750SXiaojuan Yang * 4ca61e750SXiaojuan Yang * Copyright (c) 2021 Loongson Technology Corporation Limited 5ca61e750SXiaojuan Yang * 6ca61e750SXiaojuan Yang * SPDX-License-Identifier: LGPL-2.1+ 7ca61e750SXiaojuan Yang */ 8ca61e750SXiaojuan Yang 9ca61e750SXiaojuan Yang #include "qemu/osdep.h" 10ca61e750SXiaojuan Yang #include "cpu.h" 11ca61e750SXiaojuan Yang #include "internals.h" 12ca61e750SXiaojuan Yang #include "exec/gdbstub.h" 134ea5fe99SAlex Bennée #include "gdbstub/helpers.h" 14008a3b16SSong Gao #include "vec.h" 15ca61e750SXiaojuan Yang 162f149c75SSong Gao uint64_t read_fcc(CPULoongArchState *env) 172f149c75SSong Gao { 182f149c75SSong Gao uint64_t ret = 0; 192f149c75SSong Gao 202f149c75SSong Gao for (int i = 0; i < 8; ++i) { 212f149c75SSong Gao ret |= (uint64_t)env->cf[i] << (i * 8); 222f149c75SSong Gao } 232f149c75SSong Gao 242f149c75SSong Gao return ret; 252f149c75SSong Gao } 262f149c75SSong Gao 272f149c75SSong Gao void write_fcc(CPULoongArchState *env, uint64_t val) 282f149c75SSong Gao { 292f149c75SSong Gao for (int i = 0; i < 8; ++i) { 302f149c75SSong Gao env->cf[i] = (val >> (i * 8)) & 1; 312f149c75SSong Gao } 322f149c75SSong Gao } 332f149c75SSong Gao 34ca61e750SXiaojuan Yang int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) 35ca61e750SXiaojuan Yang { 36f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs); 373cd804c5SMarc-André Lureau 383cd804c5SMarc-André Lureau if (0 <= n && n <= 34) { 39ebda3036SJiajie Chen uint64_t val; 40ca61e750SXiaojuan Yang 413cd804c5SMarc-André Lureau if (n < 32) { 42ebda3036SJiajie Chen val = env->gpr[n]; 43ca61e750SXiaojuan Yang } else if (n == 32) { 441fe8ac35SSong Gao /* orig_a0 */ 45ebda3036SJiajie Chen val = 0; 46ca61e750SXiaojuan Yang } else if (n == 33) { 47ebda3036SJiajie Chen val = env->pc; 483cd804c5SMarc-André Lureau } else /* if (n == 34) */ { 49ebda3036SJiajie Chen val = env->CSR_BADV; 50ebda3036SJiajie Chen } 51ebda3036SJiajie Chen 52ebda3036SJiajie Chen if (is_la64(env)) { 53ebda3036SJiajie Chen return gdb_get_reg64(mem_buf, val); 54ebda3036SJiajie Chen } else { 55ebda3036SJiajie Chen return gdb_get_reg32(mem_buf, val); 56ebda3036SJiajie Chen } 57ca61e750SXiaojuan Yang } 583cd804c5SMarc-André Lureau 59ca61e750SXiaojuan Yang return 0; 60ca61e750SXiaojuan Yang } 61ca61e750SXiaojuan Yang 62ca61e750SXiaojuan Yang int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 63ca61e750SXiaojuan Yang { 64f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs); 65ebda3036SJiajie Chen target_ulong tmp; 66ca61e750SXiaojuan Yang int length = 0; 67ca61e750SXiaojuan Yang 68*7bd4eaa8SBibo Mao if (n < 0 || n > 34) { 69*7bd4eaa8SBibo Mao return 0; 70*7bd4eaa8SBibo Mao } 71*7bd4eaa8SBibo Mao 72ebda3036SJiajie Chen if (is_la64(env)) { 732a99b2afSPhilippe Mathieu-Daudé tmp = ldq_le_p(mem_buf); 74*7bd4eaa8SBibo Mao length = 8; 75ebda3036SJiajie Chen } else { 762a99b2afSPhilippe Mathieu-Daudé tmp = ldl_le_p(mem_buf); 77*7bd4eaa8SBibo Mao length = 4; 78ebda3036SJiajie Chen } 79ebda3036SJiajie Chen 80ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 81ca61e750SXiaojuan Yang env->gpr[n] = tmp; 821fe8ac35SSong Gao } else if (n == 33) { 832f6478ffSJiajie Chen set_pc(env, tmp); 84ca61e750SXiaojuan Yang } 85ca61e750SXiaojuan Yang return length; 86ca61e750SXiaojuan Yang } 87ca61e750SXiaojuan Yang 8866260159SAkihiko Odaki static int loongarch_gdb_get_fpu(CPUState *cs, GByteArray *mem_buf, int n) 89ca61e750SXiaojuan Yang { 9066260159SAkihiko Odaki LoongArchCPU *cpu = LOONGARCH_CPU(cs); 9166260159SAkihiko Odaki CPULoongArchState *env = &cpu->env; 9266260159SAkihiko Odaki 93ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 9416f5396cSSong Gao return gdb_get_reg64(mem_buf, env->fpr[n].vreg.D(0)); 9517ffe331SJiajie Chen } else if (32 <= n && n < 40) { 9617ffe331SJiajie Chen return gdb_get_reg8(mem_buf, env->cf[n - 32]); 9717ffe331SJiajie Chen } else if (n == 40) { 98ca61e750SXiaojuan Yang return gdb_get_reg32(mem_buf, env->fcsr0); 99ca61e750SXiaojuan Yang } 100ca61e750SXiaojuan Yang return 0; 101ca61e750SXiaojuan Yang } 102ca61e750SXiaojuan Yang 10366260159SAkihiko Odaki static int loongarch_gdb_set_fpu(CPUState *cs, uint8_t *mem_buf, int n) 104ca61e750SXiaojuan Yang { 10566260159SAkihiko Odaki LoongArchCPU *cpu = LOONGARCH_CPU(cs); 10666260159SAkihiko Odaki CPULoongArchState *env = &cpu->env; 107ca61e750SXiaojuan Yang int length = 0; 108ca61e750SXiaojuan Yang 109ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 1102a99b2afSPhilippe Mathieu-Daudé env->fpr[n].vreg.D(0) = ldq_le_p(mem_buf); 111ca61e750SXiaojuan Yang length = 8; 11217ffe331SJiajie Chen } else if (32 <= n && n < 40) { 11317ffe331SJiajie Chen env->cf[n - 32] = ldub_p(mem_buf); 11417ffe331SJiajie Chen length = 1; 11517ffe331SJiajie Chen } else if (n == 40) { 1162a99b2afSPhilippe Mathieu-Daudé env->fcsr0 = ldl_le_p(mem_buf); 117ca61e750SXiaojuan Yang length = 4; 118ca61e750SXiaojuan Yang } 119ca61e750SXiaojuan Yang return length; 120ca61e750SXiaojuan Yang } 121ca61e750SXiaojuan Yang 1221c15dd63SSong Gao #define VREG_NUM 32 1231c15dd63SSong Gao #define REG64_LEN 64 1241c15dd63SSong Gao 1251c15dd63SSong Gao static int loongarch_gdb_get_vec(CPUState *cs, GByteArray *mem_buf, int n, int vl) 1261c15dd63SSong Gao { 1271c15dd63SSong Gao LoongArchCPU *cpu = LOONGARCH_CPU(cs); 1281c15dd63SSong Gao CPULoongArchState *env = &cpu->env; 1291c15dd63SSong Gao int i, length = 0; 1301c15dd63SSong Gao 1311c15dd63SSong Gao if (0 <= n && n < VREG_NUM) { 1321c15dd63SSong Gao for (i = 0; i < vl / REG64_LEN; i++) { 1331c15dd63SSong Gao length += gdb_get_reg64(mem_buf, env->fpr[n].vreg.D(i)); 1341c15dd63SSong Gao } 1351c15dd63SSong Gao } 1361c15dd63SSong Gao 1371c15dd63SSong Gao return length; 1381c15dd63SSong Gao } 1391c15dd63SSong Gao 1401c15dd63SSong Gao static int loongarch_gdb_set_vec(CPUState *cs, uint8_t *mem_buf, int n, int vl) 1411c15dd63SSong Gao { 1421c15dd63SSong Gao LoongArchCPU *cpu = LOONGARCH_CPU(cs); 1431c15dd63SSong Gao CPULoongArchState *env = &cpu->env; 1441c15dd63SSong Gao int i, length = 0; 1451c15dd63SSong Gao 1461c15dd63SSong Gao if (0 <= n && n < VREG_NUM) { 1471c15dd63SSong Gao for (i = 0; i < vl / REG64_LEN; i++) { 1481c15dd63SSong Gao env->fpr[n].vreg.D(i) = ldq_le_p(mem_buf + 8 * i); 1491c15dd63SSong Gao length += 8; 1501c15dd63SSong Gao } 1511c15dd63SSong Gao } 1521c15dd63SSong Gao 1531c15dd63SSong Gao return length; 1541c15dd63SSong Gao } 1551c15dd63SSong Gao 1561c15dd63SSong Gao static int loongarch_gdb_get_lsx(CPUState *cs, GByteArray *mem_buf, int n) 1571c15dd63SSong Gao { 1581c15dd63SSong Gao return loongarch_gdb_get_vec(cs, mem_buf, n, LSX_LEN); 1591c15dd63SSong Gao } 1601c15dd63SSong Gao 1611c15dd63SSong Gao static int loongarch_gdb_set_lsx(CPUState *cs, uint8_t *mem_buf, int n) 1621c15dd63SSong Gao { 1631c15dd63SSong Gao return loongarch_gdb_set_vec(cs, mem_buf, n, LSX_LEN); 1641c15dd63SSong Gao } 1651c15dd63SSong Gao 1661c15dd63SSong Gao static int loongarch_gdb_get_lasx(CPUState *cs, GByteArray *mem_buf, int n) 1671c15dd63SSong Gao { 1681c15dd63SSong Gao return loongarch_gdb_get_vec(cs, mem_buf, n, LASX_LEN); 1691c15dd63SSong Gao } 1701c15dd63SSong Gao 1711c15dd63SSong Gao static int loongarch_gdb_set_lasx(CPUState *cs, uint8_t *mem_buf, int n) 1721c15dd63SSong Gao { 1731c15dd63SSong Gao return loongarch_gdb_set_vec(cs, mem_buf, n, LASX_LEN); 1741c15dd63SSong Gao } 1751c15dd63SSong Gao 176ca61e750SXiaojuan Yang void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs) 177ca61e750SXiaojuan Yang { 1781c15dd63SSong Gao LoongArchCPU *cpu = LOONGARCH_CPU(cs); 1791c15dd63SSong Gao CPULoongArchState *env = &cpu->env; 1801c15dd63SSong Gao 1811c15dd63SSong Gao if (FIELD_EX32(env->cpucfg[2], CPUCFG2, FP)) { 182ca61e750SXiaojuan Yang gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu, 183ac1e8671SAkihiko Odaki gdb_find_static_feature("loongarch-fpu.xml"), 0); 184ca61e750SXiaojuan Yang } 1851c15dd63SSong Gao 1861c15dd63SSong Gao if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LSX)) { 1871c15dd63SSong Gao gdb_register_coprocessor(cs, loongarch_gdb_get_lsx, loongarch_gdb_set_lsx, 1881c15dd63SSong Gao gdb_find_static_feature("loongarch-lsx.xml"), 0); 1891c15dd63SSong Gao } 1901c15dd63SSong Gao 1911c15dd63SSong Gao if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LASX)) { 1921c15dd63SSong Gao gdb_register_coprocessor(cs, loongarch_gdb_get_lasx, loongarch_gdb_set_lasx, 1931c15dd63SSong Gao gdb_find_static_feature("loongarch-lasx.xml"), 0); 1941c15dd63SSong Gao } 1951c15dd63SSong Gao } 196