1 /* 2 * LOONGARCH gdb server stub 3 * 4 * Copyright (c) 2021 Loongson Technology Corporation Limited 5 * 6 * SPDX-License-Identifier: LGPL-2.1+ 7 */ 8 9 #include "qemu/osdep.h" 10 #include "cpu.h" 11 #include "internals.h" 12 #include "exec/gdbstub.h" 13 #include "gdbstub/helpers.h" 14 #include "vec.h" 15 16 uint64_t read_fcc(CPULoongArchState *env) 17 { 18 uint64_t ret = 0; 19 20 for (int i = 0; i < 8; ++i) { 21 ret |= (uint64_t)env->cf[i] << (i * 8); 22 } 23 24 return ret; 25 } 26 27 void write_fcc(CPULoongArchState *env, uint64_t val) 28 { 29 for (int i = 0; i < 8; ++i) { 30 env->cf[i] = (val >> (i * 8)) & 1; 31 } 32 } 33 34 int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) 35 { 36 CPULoongArchState *env = cpu_env(cs); 37 uint64_t val; 38 39 if (0 <= n && n < 32) { 40 val = env->gpr[n]; 41 } else if (n == 32) { 42 /* orig_a0 */ 43 val = 0; 44 } else if (n == 33) { 45 val = env->pc; 46 } else if (n == 34) { 47 val = env->CSR_BADV; 48 } 49 50 if (0 <= n && n <= 34) { 51 if (is_la64(env)) { 52 return gdb_get_reg64(mem_buf, val); 53 } else { 54 return gdb_get_reg32(mem_buf, val); 55 } 56 } 57 return 0; 58 } 59 60 int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 61 { 62 CPULoongArchState *env = cpu_env(cs); 63 target_ulong tmp; 64 int read_length; 65 int length = 0; 66 67 if (is_la64(env)) { 68 tmp = ldq_p(mem_buf); 69 read_length = 8; 70 } else { 71 tmp = ldl_p(mem_buf); 72 read_length = 4; 73 } 74 75 if (0 <= n && n < 32) { 76 env->gpr[n] = tmp; 77 length = read_length; 78 } else if (n == 33) { 79 set_pc(env, tmp); 80 length = read_length; 81 } 82 return length; 83 } 84 85 static int loongarch_gdb_get_fpu(CPUState *cs, GByteArray *mem_buf, int n) 86 { 87 LoongArchCPU *cpu = LOONGARCH_CPU(cs); 88 CPULoongArchState *env = &cpu->env; 89 90 if (0 <= n && n < 32) { 91 return gdb_get_reg64(mem_buf, env->fpr[n].vreg.D(0)); 92 } else if (32 <= n && n < 40) { 93 return gdb_get_reg8(mem_buf, env->cf[n - 32]); 94 } else if (n == 40) { 95 return gdb_get_reg32(mem_buf, env->fcsr0); 96 } 97 return 0; 98 } 99 100 static int loongarch_gdb_set_fpu(CPUState *cs, uint8_t *mem_buf, int n) 101 { 102 LoongArchCPU *cpu = LOONGARCH_CPU(cs); 103 CPULoongArchState *env = &cpu->env; 104 int length = 0; 105 106 if (0 <= n && n < 32) { 107 env->fpr[n].vreg.D(0) = ldq_p(mem_buf); 108 length = 8; 109 } else if (32 <= n && n < 40) { 110 env->cf[n - 32] = ldub_p(mem_buf); 111 length = 1; 112 } else if (n == 40) { 113 env->fcsr0 = ldl_p(mem_buf); 114 length = 4; 115 } 116 return length; 117 } 118 119 void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs) 120 { 121 gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu, 122 gdb_find_static_feature("loongarch-fpu.xml"), 0); 123 } 124