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 15 uint64_t read_fcc(CPULoongArchState *env) 16 { 17 uint64_t ret = 0; 18 19 for (int i = 0; i < 8; ++i) { 20 ret |= (uint64_t)env->cf[i] << (i * 8); 21 } 22 23 return ret; 24 } 25 26 void write_fcc(CPULoongArchState *env, uint64_t val) 27 { 28 for (int i = 0; i < 8; ++i) { 29 env->cf[i] = (val >> (i * 8)) & 1; 30 } 31 } 32 33 int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) 34 { 35 LoongArchCPU *cpu = LOONGARCH_CPU(cs); 36 CPULoongArchState *env = &cpu->env; 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 LoongArchCPU *cpu = LOONGARCH_CPU(cs); 63 CPULoongArchState *env = &cpu->env; 64 target_ulong tmp; 65 int read_length; 66 int length = 0; 67 68 if (is_la64(env)) { 69 tmp = ldq_p(mem_buf); 70 read_length = 8; 71 } else { 72 tmp = ldl_p(mem_buf); 73 read_length = 4; 74 } 75 76 if (0 <= n && n < 32) { 77 env->gpr[n] = tmp; 78 length = read_length; 79 } else if (n == 33) { 80 set_pc(env, tmp); 81 length = read_length; 82 } 83 return length; 84 } 85 86 static int loongarch_gdb_get_fpu(CPULoongArchState *env, 87 GByteArray *mem_buf, int n) 88 { 89 if (0 <= n && n < 32) { 90 return gdb_get_reg64(mem_buf, env->fpr[n].vreg.D(0)); 91 } else if (32 <= n && n < 40) { 92 return gdb_get_reg8(mem_buf, env->cf[n - 32]); 93 } else if (n == 40) { 94 return gdb_get_reg32(mem_buf, env->fcsr0); 95 } 96 return 0; 97 } 98 99 static int loongarch_gdb_set_fpu(CPULoongArchState *env, 100 uint8_t *mem_buf, int n) 101 { 102 int length = 0; 103 104 if (0 <= n && n < 32) { 105 env->fpr[n].vreg.D(0) = ldq_p(mem_buf); 106 length = 8; 107 } else if (32 <= n && n < 40) { 108 env->cf[n - 32] = ldub_p(mem_buf); 109 length = 1; 110 } else if (n == 40) { 111 env->fcsr0 = ldl_p(mem_buf); 112 length = 4; 113 } 114 return length; 115 } 116 117 void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs) 118 { 119 gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu, 120 41, "loongarch-fpu.xml", 0); 121 } 122