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 { 36*f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs); 37ebda3036SJiajie Chen uint64_t val; 38ca61e750SXiaojuan Yang 39ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 40ebda3036SJiajie Chen val = env->gpr[n]; 41ca61e750SXiaojuan Yang } else if (n == 32) { 421fe8ac35SSong Gao /* orig_a0 */ 43ebda3036SJiajie Chen val = 0; 44ca61e750SXiaojuan Yang } else if (n == 33) { 45ebda3036SJiajie Chen val = env->pc; 461fe8ac35SSong Gao } else if (n == 34) { 47ebda3036SJiajie Chen val = env->CSR_BADV; 48ebda3036SJiajie Chen } 49ebda3036SJiajie Chen 50ebda3036SJiajie Chen if (0 <= n && n <= 34) { 51ebda3036SJiajie Chen if (is_la64(env)) { 52ebda3036SJiajie Chen return gdb_get_reg64(mem_buf, val); 53ebda3036SJiajie Chen } else { 54ebda3036SJiajie Chen return gdb_get_reg32(mem_buf, val); 55ebda3036SJiajie Chen } 56ca61e750SXiaojuan Yang } 57ca61e750SXiaojuan Yang return 0; 58ca61e750SXiaojuan Yang } 59ca61e750SXiaojuan Yang 60ca61e750SXiaojuan Yang int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 61ca61e750SXiaojuan Yang { 62*f3b603b9SPhilippe Mathieu-Daudé CPULoongArchState *env = cpu_env(cs); 63ebda3036SJiajie Chen target_ulong tmp; 64ebda3036SJiajie Chen int read_length; 65ca61e750SXiaojuan Yang int length = 0; 66ca61e750SXiaojuan Yang 67ebda3036SJiajie Chen if (is_la64(env)) { 68ebda3036SJiajie Chen tmp = ldq_p(mem_buf); 69ebda3036SJiajie Chen read_length = 8; 70ebda3036SJiajie Chen } else { 71ebda3036SJiajie Chen tmp = ldl_p(mem_buf); 72ebda3036SJiajie Chen read_length = 4; 73ebda3036SJiajie Chen } 74ebda3036SJiajie Chen 75ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 76ca61e750SXiaojuan Yang env->gpr[n] = tmp; 77ebda3036SJiajie Chen length = read_length; 781fe8ac35SSong Gao } else if (n == 33) { 792f6478ffSJiajie Chen set_pc(env, tmp); 80ebda3036SJiajie Chen length = read_length; 81ca61e750SXiaojuan Yang } 82ca61e750SXiaojuan Yang return length; 83ca61e750SXiaojuan Yang } 84ca61e750SXiaojuan Yang 8566260159SAkihiko Odaki static int loongarch_gdb_get_fpu(CPUState *cs, GByteArray *mem_buf, int n) 86ca61e750SXiaojuan Yang { 8766260159SAkihiko Odaki LoongArchCPU *cpu = LOONGARCH_CPU(cs); 8866260159SAkihiko Odaki CPULoongArchState *env = &cpu->env; 8966260159SAkihiko Odaki 90ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 9116f5396cSSong Gao return gdb_get_reg64(mem_buf, env->fpr[n].vreg.D(0)); 9217ffe331SJiajie Chen } else if (32 <= n && n < 40) { 9317ffe331SJiajie Chen return gdb_get_reg8(mem_buf, env->cf[n - 32]); 9417ffe331SJiajie Chen } else if (n == 40) { 95ca61e750SXiaojuan Yang return gdb_get_reg32(mem_buf, env->fcsr0); 96ca61e750SXiaojuan Yang } 97ca61e750SXiaojuan Yang return 0; 98ca61e750SXiaojuan Yang } 99ca61e750SXiaojuan Yang 10066260159SAkihiko Odaki static int loongarch_gdb_set_fpu(CPUState *cs, uint8_t *mem_buf, int n) 101ca61e750SXiaojuan Yang { 10266260159SAkihiko Odaki LoongArchCPU *cpu = LOONGARCH_CPU(cs); 10366260159SAkihiko Odaki CPULoongArchState *env = &cpu->env; 104ca61e750SXiaojuan Yang int length = 0; 105ca61e750SXiaojuan Yang 106ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 10716f5396cSSong Gao env->fpr[n].vreg.D(0) = ldq_p(mem_buf); 108ca61e750SXiaojuan Yang length = 8; 10917ffe331SJiajie Chen } else if (32 <= n && n < 40) { 11017ffe331SJiajie Chen env->cf[n - 32] = ldub_p(mem_buf); 11117ffe331SJiajie Chen length = 1; 11217ffe331SJiajie Chen } else if (n == 40) { 113ca61e750SXiaojuan Yang env->fcsr0 = ldl_p(mem_buf); 114ca61e750SXiaojuan Yang length = 4; 115ca61e750SXiaojuan Yang } 116ca61e750SXiaojuan Yang return length; 117ca61e750SXiaojuan Yang } 118ca61e750SXiaojuan Yang 119ca61e750SXiaojuan Yang void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs) 120ca61e750SXiaojuan Yang { 121ca61e750SXiaojuan Yang gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu, 122ac1e8671SAkihiko Odaki gdb_find_static_feature("loongarch-fpu.xml"), 0); 123ca61e750SXiaojuan Yang } 124