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" 13ca61e750SXiaojuan Yang 14*2f149c75SSong Gao uint64_t read_fcc(CPULoongArchState *env) 15*2f149c75SSong Gao { 16*2f149c75SSong Gao uint64_t ret = 0; 17*2f149c75SSong Gao 18*2f149c75SSong Gao for (int i = 0; i < 8; ++i) { 19*2f149c75SSong Gao ret |= (uint64_t)env->cf[i] << (i * 8); 20*2f149c75SSong Gao } 21*2f149c75SSong Gao 22*2f149c75SSong Gao return ret; 23*2f149c75SSong Gao } 24*2f149c75SSong Gao 25*2f149c75SSong Gao void write_fcc(CPULoongArchState *env, uint64_t val) 26*2f149c75SSong Gao { 27*2f149c75SSong Gao for (int i = 0; i < 8; ++i) { 28*2f149c75SSong Gao env->cf[i] = (val >> (i * 8)) & 1; 29*2f149c75SSong Gao } 30*2f149c75SSong Gao } 31*2f149c75SSong Gao 32ca61e750SXiaojuan Yang int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) 33ca61e750SXiaojuan Yang { 34ca61e750SXiaojuan Yang LoongArchCPU *cpu = LOONGARCH_CPU(cs); 35ca61e750SXiaojuan Yang CPULoongArchState *env = &cpu->env; 36ca61e750SXiaojuan Yang 37ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 38ca61e750SXiaojuan Yang return gdb_get_regl(mem_buf, env->gpr[n]); 39ca61e750SXiaojuan Yang } else if (n == 32) { 401fe8ac35SSong Gao /* orig_a0 */ 411fe8ac35SSong Gao return gdb_get_regl(mem_buf, 0); 42ca61e750SXiaojuan Yang } else if (n == 33) { 431fe8ac35SSong Gao return gdb_get_regl(mem_buf, env->pc); 441fe8ac35SSong Gao } else if (n == 34) { 45fffca8f2SSong Gao return gdb_get_regl(mem_buf, env->CSR_BADV); 46ca61e750SXiaojuan Yang } 47ca61e750SXiaojuan Yang return 0; 48ca61e750SXiaojuan Yang } 49ca61e750SXiaojuan Yang 50ca61e750SXiaojuan Yang int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 51ca61e750SXiaojuan Yang { 52ca61e750SXiaojuan Yang LoongArchCPU *cpu = LOONGARCH_CPU(cs); 53ca61e750SXiaojuan Yang CPULoongArchState *env = &cpu->env; 54ca61e750SXiaojuan Yang target_ulong tmp = ldtul_p(mem_buf); 55ca61e750SXiaojuan Yang int length = 0; 56ca61e750SXiaojuan Yang 57ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 58ca61e750SXiaojuan Yang env->gpr[n] = tmp; 59ca61e750SXiaojuan Yang length = sizeof(target_ulong); 601fe8ac35SSong Gao } else if (n == 33) { 61ca61e750SXiaojuan Yang env->pc = tmp; 62ca61e750SXiaojuan Yang length = sizeof(target_ulong); 63ca61e750SXiaojuan Yang } 64ca61e750SXiaojuan Yang return length; 65ca61e750SXiaojuan Yang } 66ca61e750SXiaojuan Yang 67ca61e750SXiaojuan Yang static int loongarch_gdb_get_fpu(CPULoongArchState *env, 68ca61e750SXiaojuan Yang GByteArray *mem_buf, int n) 69ca61e750SXiaojuan Yang { 70ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 71ca61e750SXiaojuan Yang return gdb_get_reg64(mem_buf, env->fpr[n]); 72*2f149c75SSong Gao } else if (n == 32) { 73*2f149c75SSong Gao uint64_t val = read_fcc(env); 74*2f149c75SSong Gao return gdb_get_reg64(mem_buf, val); 75*2f149c75SSong Gao } else if (n == 33) { 76ca61e750SXiaojuan Yang return gdb_get_reg32(mem_buf, env->fcsr0); 77ca61e750SXiaojuan Yang } 78ca61e750SXiaojuan Yang return 0; 79ca61e750SXiaojuan Yang } 80ca61e750SXiaojuan Yang 81ca61e750SXiaojuan Yang static int loongarch_gdb_set_fpu(CPULoongArchState *env, 82ca61e750SXiaojuan Yang uint8_t *mem_buf, int n) 83ca61e750SXiaojuan Yang { 84ca61e750SXiaojuan Yang int length = 0; 85ca61e750SXiaojuan Yang 86ca61e750SXiaojuan Yang if (0 <= n && n < 32) { 87ca61e750SXiaojuan Yang env->fpr[n] = ldq_p(mem_buf); 88ca61e750SXiaojuan Yang length = 8; 89*2f149c75SSong Gao } else if (n == 32) { 90*2f149c75SSong Gao uint64_t val = ldq_p(mem_buf); 91*2f149c75SSong Gao write_fcc(env, val); 92*2f149c75SSong Gao length = 8; 93*2f149c75SSong Gao } else if (n == 33) { 94ca61e750SXiaojuan Yang env->fcsr0 = ldl_p(mem_buf); 95ca61e750SXiaojuan Yang length = 4; 96ca61e750SXiaojuan Yang } 97ca61e750SXiaojuan Yang return length; 98ca61e750SXiaojuan Yang } 99ca61e750SXiaojuan Yang 100ca61e750SXiaojuan Yang void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs) 101ca61e750SXiaojuan Yang { 102ca61e750SXiaojuan Yang gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu, 103d182c390SSong Gao 41, "loongarch-fpu.xml", 0); 104ca61e750SXiaojuan Yang } 105