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 #define VREG_NUM 32 120 #define REG64_LEN 64 121 122 static int loongarch_gdb_get_vec(CPUState *cs, GByteArray *mem_buf, int n, int vl) 123 { 124 LoongArchCPU *cpu = LOONGARCH_CPU(cs); 125 CPULoongArchState *env = &cpu->env; 126 int i, length = 0; 127 128 if (0 <= n && n < VREG_NUM) { 129 for (i = 0; i < vl / REG64_LEN; i++) { 130 length += gdb_get_reg64(mem_buf, env->fpr[n].vreg.D(i)); 131 } 132 } 133 134 return length; 135 } 136 137 static int loongarch_gdb_set_vec(CPUState *cs, uint8_t *mem_buf, int n, int vl) 138 { 139 LoongArchCPU *cpu = LOONGARCH_CPU(cs); 140 CPULoongArchState *env = &cpu->env; 141 int i, length = 0; 142 143 if (0 <= n && n < VREG_NUM) { 144 for (i = 0; i < vl / REG64_LEN; i++) { 145 env->fpr[n].vreg.D(i) = ldq_le_p(mem_buf + 8 * i); 146 length += 8; 147 } 148 } 149 150 return length; 151 } 152 153 static int loongarch_gdb_get_lsx(CPUState *cs, GByteArray *mem_buf, int n) 154 { 155 return loongarch_gdb_get_vec(cs, mem_buf, n, LSX_LEN); 156 } 157 158 static int loongarch_gdb_set_lsx(CPUState *cs, uint8_t *mem_buf, int n) 159 { 160 return loongarch_gdb_set_vec(cs, mem_buf, n, LSX_LEN); 161 } 162 163 static int loongarch_gdb_get_lasx(CPUState *cs, GByteArray *mem_buf, int n) 164 { 165 return loongarch_gdb_get_vec(cs, mem_buf, n, LASX_LEN); 166 } 167 168 static int loongarch_gdb_set_lasx(CPUState *cs, uint8_t *mem_buf, int n) 169 { 170 return loongarch_gdb_set_vec(cs, mem_buf, n, LASX_LEN); 171 } 172 173 void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs) 174 { 175 LoongArchCPU *cpu = LOONGARCH_CPU(cs); 176 CPULoongArchState *env = &cpu->env; 177 178 if (FIELD_EX32(env->cpucfg[2], CPUCFG2, FP)) { 179 gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu, 180 gdb_find_static_feature("loongarch-fpu.xml"), 0); 181 } 182 183 if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LSX)) { 184 gdb_register_coprocessor(cs, loongarch_gdb_get_lsx, loongarch_gdb_set_lsx, 185 gdb_find_static_feature("loongarch-lsx.xml"), 0); 186 } 187 188 if (FIELD_EX32(env->cpucfg[2], CPUCFG2, LASX)) { 189 gdb_register_coprocessor(cs, loongarch_gdb_get_lasx, loongarch_gdb_set_lasx, 190 gdb_find_static_feature("loongarch-lasx.xml"), 0); 191 } 192 } 193