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" 13*4ea5fe99SAlex Bennée #include "gdbstub/helpers.h" 14ca61e750SXiaojuan Yang 152f149c75SSong Gao uint64_t read_fcc(CPULoongArchState *env) 162f149c75SSong Gao { 172f149c75SSong Gao uint64_t ret = 0; 182f149c75SSong Gao 192f149c75SSong Gao for (int i = 0; i < 8; ++i) { 202f149c75SSong Gao ret |= (uint64_t)env->cf[i] << (i * 8); 212f149c75SSong Gao } 222f149c75SSong Gao 232f149c75SSong Gao return ret; 242f149c75SSong Gao } 252f149c75SSong Gao 262f149c75SSong Gao void write_fcc(CPULoongArchState *env, uint64_t val) 272f149c75SSong Gao { 282f149c75SSong Gao for (int i = 0; i < 8; ++i) { 292f149c75SSong Gao env->cf[i] = (val >> (i * 8)) & 1; 302f149c75SSong Gao } 312f149c75SSong Gao } 322f149c75SSong Gao 33ca61e750SXiaojuan Yang int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) 34ca61e750SXiaojuan Yang { 35ca61e750SXiaojuan Yang LoongArchCPU *cpu = LOONGARCH_CPU(cs); 36ca61e750SXiaojuan Yang CPULoongArchState *env = &cpu->env; 37ca61e750SXiaojuan Yang 38ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 39ca61e750SXiaojuan Yang return gdb_get_regl(mem_buf, env->gpr[n]); 40ca61e750SXiaojuan Yang } else if (n == 32) { 411fe8ac35SSong Gao /* orig_a0 */ 421fe8ac35SSong Gao return gdb_get_regl(mem_buf, 0); 43ca61e750SXiaojuan Yang } else if (n == 33) { 441fe8ac35SSong Gao return gdb_get_regl(mem_buf, env->pc); 451fe8ac35SSong Gao } else if (n == 34) { 46fffca8f2SSong Gao return gdb_get_regl(mem_buf, env->CSR_BADV); 47ca61e750SXiaojuan Yang } 48ca61e750SXiaojuan Yang return 0; 49ca61e750SXiaojuan Yang } 50ca61e750SXiaojuan Yang 51ca61e750SXiaojuan Yang int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 52ca61e750SXiaojuan Yang { 53ca61e750SXiaojuan Yang LoongArchCPU *cpu = LOONGARCH_CPU(cs); 54ca61e750SXiaojuan Yang CPULoongArchState *env = &cpu->env; 55ca61e750SXiaojuan Yang target_ulong tmp = ldtul_p(mem_buf); 56ca61e750SXiaojuan Yang int length = 0; 57ca61e750SXiaojuan Yang 58ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 59ca61e750SXiaojuan Yang env->gpr[n] = tmp; 60ca61e750SXiaojuan Yang length = sizeof(target_ulong); 611fe8ac35SSong Gao } else if (n == 33) { 62ca61e750SXiaojuan Yang env->pc = tmp; 63ca61e750SXiaojuan Yang length = sizeof(target_ulong); 64ca61e750SXiaojuan Yang } 65ca61e750SXiaojuan Yang return length; 66ca61e750SXiaojuan Yang } 67ca61e750SXiaojuan Yang 68ca61e750SXiaojuan Yang static int loongarch_gdb_get_fpu(CPULoongArchState *env, 69ca61e750SXiaojuan Yang GByteArray *mem_buf, int n) 70ca61e750SXiaojuan Yang { 71ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 72ca61e750SXiaojuan Yang return gdb_get_reg64(mem_buf, env->fpr[n]); 732f149c75SSong Gao } else if (n == 32) { 742f149c75SSong Gao uint64_t val = read_fcc(env); 752f149c75SSong Gao return gdb_get_reg64(mem_buf, val); 762f149c75SSong Gao } else if (n == 33) { 77ca61e750SXiaojuan Yang return gdb_get_reg32(mem_buf, env->fcsr0); 78ca61e750SXiaojuan Yang } 79ca61e750SXiaojuan Yang return 0; 80ca61e750SXiaojuan Yang } 81ca61e750SXiaojuan Yang 82ca61e750SXiaojuan Yang static int loongarch_gdb_set_fpu(CPULoongArchState *env, 83ca61e750SXiaojuan Yang uint8_t *mem_buf, int n) 84ca61e750SXiaojuan Yang { 85ca61e750SXiaojuan Yang int length = 0; 86ca61e750SXiaojuan Yang 87ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 88ca61e750SXiaojuan Yang env->fpr[n] = ldq_p(mem_buf); 89ca61e750SXiaojuan Yang length = 8; 902f149c75SSong Gao } else if (n == 32) { 912f149c75SSong Gao uint64_t val = ldq_p(mem_buf); 922f149c75SSong Gao write_fcc(env, val); 932f149c75SSong Gao length = 8; 942f149c75SSong Gao } else if (n == 33) { 95ca61e750SXiaojuan Yang env->fcsr0 = ldl_p(mem_buf); 96ca61e750SXiaojuan Yang length = 4; 97ca61e750SXiaojuan Yang } 98ca61e750SXiaojuan Yang return length; 99ca61e750SXiaojuan Yang } 100ca61e750SXiaojuan Yang 101ca61e750SXiaojuan Yang void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs) 102ca61e750SXiaojuan Yang { 103ca61e750SXiaojuan Yang gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu, 104d182c390SSong Gao 41, "loongarch-fpu.xml", 0); 105ca61e750SXiaojuan Yang } 106