diff options
-rw-r--r-- | gdb/arch/loongarch.c | 6 | ||||
-rw-r--r-- | gdb/arch/loongarch.h | 4 | ||||
-rw-r--r-- | gdb/features/Makefile | 2 | ||||
-rw-r--r-- | gdb/features/loongarch/lasx.c | 85 | ||||
-rw-r--r-- | gdb/features/loongarch/lasx.xml | 60 | ||||
-rw-r--r-- | gdb/features/loongarch/lsx.c | 82 | ||||
-rw-r--r-- | gdb/features/loongarch/lsx.xml | 59 | ||||
-rw-r--r-- | gdb/loongarch-linux-nat.c | 123 | ||||
-rw-r--r-- | gdb/loongarch-linux-tdep.c | 130 | ||||
-rw-r--r-- | gdb/loongarch-tdep.c | 36 | ||||
-rw-r--r-- | gdb/loongarch-tdep.h | 2 | ||||
-rw-r--r-- | gdbserver/linux-loongarch-low.cc | 52 |
12 files changed, 641 insertions, 0 deletions
diff --git a/gdb/arch/loongarch.c b/gdb/arch/loongarch.c index d1a7bad..e9995c9 100644 --- a/gdb/arch/loongarch.c +++ b/gdb/arch/loongarch.c @@ -25,6 +25,8 @@ #include "../features/loongarch/base32.c" #include "../features/loongarch/base64.c" #include "../features/loongarch/fpu.c" +#include "../features/loongarch/lsx.c" +#include "../features/loongarch/lasx.c" #ifndef GDBSERVER #define STATIC_IN_GDB static @@ -63,6 +65,10 @@ loongarch_create_target_description (const struct loongarch_gdbarch_features fea /* For now we only support creating single float and double float. */ regnum = create_feature_loongarch_fpu (tdesc.get (), regnum); + /* For now we only support creating lsx and lasx. */ + regnum = create_feature_loongarch_lsx (tdesc.get (), regnum); + regnum = create_feature_loongarch_lasx (tdesc.get (), regnum); + return tdesc; } diff --git a/gdb/arch/loongarch.h b/gdb/arch/loongarch.h index 1fe75d0..d166f9d 100644 --- a/gdb/arch/loongarch.h +++ b/gdb/arch/loongarch.h @@ -41,6 +41,10 @@ enum loongarch_regnum LOONGARCH_FIRST_FCC_REGNUM = LOONGARCH_FIRST_FP_REGNUM + LOONGARCH_LINUX_NUM_FPREGSET, LOONGARCH_LINUX_NUM_FCC = 8, LOONGARCH_FCSR_REGNUM = LOONGARCH_FIRST_FCC_REGNUM + LOONGARCH_LINUX_NUM_FCC, + LOONGARCH_FIRST_LSX_REGNUM = LOONGARCH_FCSR_REGNUM + 1, + LOONGARCH_LINUX_NUM_LSXREGSET = 32, + LOONGARCH_FIRST_LASX_REGNUM = LOONGARCH_FIRST_LSX_REGNUM + LOONGARCH_LINUX_NUM_LSXREGSET, + LOONGARCH_LINUX_NUM_LASXREGSET = 32, }; enum loongarch_fputype diff --git a/gdb/features/Makefile b/gdb/features/Makefile index cda6a49..7c33c09 100644 --- a/gdb/features/Makefile +++ b/gdb/features/Makefile @@ -237,6 +237,8 @@ FEATURE_XMLFILES = aarch64-core.xml \ loongarch/base32.xml \ loongarch/base64.xml \ loongarch/fpu.xml \ + loongarch/lsx.xml \ + loongarch/lasx.xml \ riscv/rv32e-xregs.xml \ riscv/32bit-cpu.xml \ riscv/32bit-fpu.xml \ diff --git a/gdb/features/loongarch/lasx.c b/gdb/features/loongarch/lasx.c new file mode 100644 index 0000000..52d486e --- /dev/null +++ b/gdb/features/loongarch/lasx.c @@ -0,0 +1,85 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: lasx.xml */ + +#include "gdbsupport/tdesc.h" + +static int +create_feature_loongarch_lasx (struct target_desc *result, long regnum) +{ + struct tdesc_feature *feature; + + feature = tdesc_create_feature (result, "org.gnu.gdb.loongarch.lasx"); + tdesc_type *element_type; + element_type = tdesc_named_type (feature, "ieee_single"); + tdesc_create_vector (feature, "v8f32", element_type, 8); + + element_type = tdesc_named_type (feature, "ieee_double"); + tdesc_create_vector (feature, "v4f64", element_type, 4); + + element_type = tdesc_named_type (feature, "int8"); + tdesc_create_vector (feature, "v32i8", element_type, 32); + + element_type = tdesc_named_type (feature, "int16"); + tdesc_create_vector (feature, "v16i16", element_type, 16); + + element_type = tdesc_named_type (feature, "int32"); + tdesc_create_vector (feature, "v8i32", element_type, 8); + + element_type = tdesc_named_type (feature, "int64"); + tdesc_create_vector (feature, "v4i64", element_type, 4); + + element_type = tdesc_named_type (feature, "uint128"); + tdesc_create_vector (feature, "v2ui128", element_type, 2); + + tdesc_type_with_fields *type_with_fields; + type_with_fields = tdesc_create_union (feature, "lasxv"); + tdesc_type *field_type; + field_type = tdesc_named_type (feature, "v8f32"); + tdesc_add_field (type_with_fields, "v8_float", field_type); + field_type = tdesc_named_type (feature, "v4f64"); + tdesc_add_field (type_with_fields, "v4_double", field_type); + field_type = tdesc_named_type (feature, "v32i8"); + tdesc_add_field (type_with_fields, "v32_int8", field_type); + field_type = tdesc_named_type (feature, "v16i16"); + tdesc_add_field (type_with_fields, "v16_int16", field_type); + field_type = tdesc_named_type (feature, "v8i32"); + tdesc_add_field (type_with_fields, "v8_int32", field_type); + field_type = tdesc_named_type (feature, "v4i64"); + tdesc_add_field (type_with_fields, "v4_int64", field_type); + field_type = tdesc_named_type (feature, "v2ui128"); + tdesc_add_field (type_with_fields, "v2_uint128", field_type); + + tdesc_create_reg (feature, "xr0", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr1", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr2", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr3", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr4", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr5", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr6", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr7", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr8", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr9", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr10", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr11", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr12", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr13", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr14", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr15", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr16", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr17", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr18", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr19", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr20", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr21", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr22", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr23", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr24", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr25", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr26", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr27", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr28", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr29", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr30", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr31", regnum++, 1, "lasx", 256, "lasxv"); + return regnum; +} diff --git a/gdb/features/loongarch/lasx.xml b/gdb/features/loongarch/lasx.xml new file mode 100644 index 0000000..753b982 --- /dev/null +++ b/gdb/features/loongarch/lasx.xml @@ -0,0 +1,60 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2022-2024 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.loongarch.lasx"> + <vector id="v8f32" type="ieee_single" count="8"/> + <vector id="v4f64" type="ieee_double" count="4"/> + <vector id="v32i8" type="int8" count="32"/> + <vector id="v16i16" type="int16" count="16"/> + <vector id="v8i32" type="int32" count="8"/> + <vector id="v4i64" type="int64" count="4"/> + <vector id="v2ui128" type="uint128" count="2"/> + + <union id="lasxv"> + <field name="v8_float" type="v8f32"/> + <field name="v4_double" type="v4f64"/> + <field name="v32_int8" type="v32i8"/> + <field name="v16_int16" type="v16i16"/> + <field name="v8_int32" type="v8i32"/> + <field name="v4_int64" type="v4i64"/> + <field name="v2_uint128" type="v2ui128"/> + </union> + + <reg name="xr0" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr1" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr2" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr3" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr4" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr5" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr6" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr7" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr8" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr9" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr10" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr11" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr12" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr13" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr14" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr15" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr16" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr17" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr18" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr19" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr20" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr21" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr22" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr23" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr24" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr25" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr26" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr27" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr28" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr29" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr30" bitsize="256" type="lasxv" group="lasx"/> + <reg name="xr31" bitsize="256" type="lasxv" group="lasx"/> +</feature> diff --git a/gdb/features/loongarch/lsx.c b/gdb/features/loongarch/lsx.c new file mode 100644 index 0000000..0067c2f --- /dev/null +++ b/gdb/features/loongarch/lsx.c @@ -0,0 +1,82 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: lsx.xml */ + +#include "gdbsupport/tdesc.h" + +static int +create_feature_loongarch_lsx (struct target_desc *result, long regnum) +{ + struct tdesc_feature *feature; + + feature = tdesc_create_feature (result, "org.gnu.gdb.loongarch.lsx"); + tdesc_type *element_type; + element_type = tdesc_named_type (feature, "ieee_single"); + tdesc_create_vector (feature, "v4f32", element_type, 4); + + element_type = tdesc_named_type (feature, "ieee_double"); + tdesc_create_vector (feature, "v2f64", element_type, 2); + + element_type = tdesc_named_type (feature, "int8"); + tdesc_create_vector (feature, "v16i8", element_type, 16); + + element_type = tdesc_named_type (feature, "int16"); + tdesc_create_vector (feature, "v8i16", element_type, 8); + + element_type = tdesc_named_type (feature, "int32"); + tdesc_create_vector (feature, "v4i32", element_type, 4); + + element_type = tdesc_named_type (feature, "int64"); + tdesc_create_vector (feature, "v2i64", element_type, 2); + + tdesc_type_with_fields *type_with_fields; + type_with_fields = tdesc_create_union (feature, "lsxv"); + tdesc_type *field_type; + field_type = tdesc_named_type (feature, "v4f32"); + tdesc_add_field (type_with_fields, "v4_float", field_type); + field_type = tdesc_named_type (feature, "v2f64"); + tdesc_add_field (type_with_fields, "v2_double", field_type); + field_type = tdesc_named_type (feature, "v16i8"); + tdesc_add_field (type_with_fields, "v16_int8", field_type); + field_type = tdesc_named_type (feature, "v8i16"); + tdesc_add_field (type_with_fields, "v8_int16", field_type); + field_type = tdesc_named_type (feature, "v4i32"); + tdesc_add_field (type_with_fields, "v4_int32", field_type); + field_type = tdesc_named_type (feature, "v2i64"); + tdesc_add_field (type_with_fields, "v2_int64", field_type); + field_type = tdesc_named_type (feature, "uint128"); + tdesc_add_field (type_with_fields, "uint128", field_type); + + tdesc_create_reg (feature, "vr0", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr1", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr2", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr3", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr4", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr5", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr6", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr7", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr8", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr9", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr10", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr11", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr12", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr13", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr14", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr15", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr16", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr17", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr18", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr19", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr20", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr21", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr22", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr23", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr24", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr25", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr26", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr27", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr28", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr29", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr30", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr31", regnum++, 1, "lsx", 128, "lsxv"); + return regnum; +} diff --git a/gdb/features/loongarch/lsx.xml b/gdb/features/loongarch/lsx.xml new file mode 100644 index 0000000..e19a404 --- /dev/null +++ b/gdb/features/loongarch/lsx.xml @@ -0,0 +1,59 @@ +<?xml version="1.0"?> +<!-- Copyright (C) 2022-2024 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. --> + +<!DOCTYPE feature SYSTEM "gdb-target.dtd"> +<feature name="org.gnu.gdb.loongarch.lsx"> + <vector id="v4f32" type="ieee_single" count="4"/> + <vector id="v2f64" type="ieee_double" count="2"/> + <vector id="v16i8" type="int8" count="16"/> + <vector id="v8i16" type="int16" count="8"/> + <vector id="v4i32" type="int32" count="4"/> + <vector id="v2i64" type="int64" count="2"/> + + <union id="lsxv"> + <field name="v4_float" type="v4f32"/> + <field name="v2_double" type="v2f64"/> + <field name="v16_int8" type="v16i8"/> + <field name="v8_int16" type="v8i16"/> + <field name="v4_int32" type="v4i32"/> + <field name="v2_int64" type="v2i64"/> + <field name="uint128" type="uint128"/> + </union> + + <reg name="vr0" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr1" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr2" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr3" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr4" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr5" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr6" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr7" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr8" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr9" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr10" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr11" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr12" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr13" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr14" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr15" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr16" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr17" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr18" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr19" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr20" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr21" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr22" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr23" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr24" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr25" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr26" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr27" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr28" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr29" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr30" bitsize="128" type="lsxv" group="lsx"/> + <reg name="vr31" bitsize="128" type="lsxv" group="lsx"/> +</feature> diff --git a/gdb/loongarch-linux-nat.c b/gdb/loongarch-linux-nat.c index fe65b5d..85d0a96 100644 --- a/gdb/loongarch-linux-nat.c +++ b/gdb/loongarch-linux-nat.c @@ -146,6 +146,125 @@ store_fpregs_to_thread (struct regcache *regcache, int regnum, pid_t tid) } } +/* Fill GDB's register array with the Loongson SIMD Extension + register values from the current thread. */ + +static void +fetch_lsxregs_from_thread (struct regcache *regcache, int regnum, pid_t tid) +{ + elf_lsxregset_t regset; + + if ((regnum == -1) + || (regnum >= LOONGARCH_FIRST_LSX_REGNUM && regnum < LOONGARCH_FIRST_LASX_REGNUM)) + { + struct iovec iovec = { .iov_base = ®set, .iov_len = sizeof (regset) }; + + if (ptrace (PTRACE_GETREGSET, tid, NT_LARCH_LSX, (long) &iovec) < 0) + { + /* If kernel dose not support lsx, just return. */ + if (errno == EINVAL) + return; + + perror_with_name (_("Couldn't get NT_LARCH_LSX registers")); + } + else + loongarch_lsxregset.supply_regset (nullptr, regcache, -1, + ®set, sizeof (regset)); + } +} + +/* Store to the current thread the valid Loongson SIMD Extension + register values in the GDB's register array. */ + +static void +store_lsxregs_to_thread (struct regcache *regcache, int regnum, pid_t tid) +{ + elf_lsxregset_t regset; + + if ((regnum == -1) + || (regnum >= LOONGARCH_FIRST_LSX_REGNUM && regnum < LOONGARCH_FIRST_LASX_REGNUM)) + { + struct iovec iovec = { .iov_base = ®set, .iov_len = sizeof (regset) }; + + if (ptrace (PTRACE_GETREGSET, tid, NT_LARCH_LSX, (long) &iovec) < 0) + { + /* If kernel dose not support lsx, just return. */ + if (errno == EINVAL) + return; + + perror_with_name (_("Couldn't get NT_LARCH_LSX registers")); + } + else + { + loongarch_lsxregset.collect_regset (nullptr, regcache, regnum, + ®set, sizeof (regset)); + if (ptrace (PTRACE_SETREGSET, tid, NT_LARCH_LSX, (long) &iovec) < 0) + perror_with_name (_("Couldn't set NT_LARCH_LSX registers")); + } + } +} + +/* Fill GDB's register array with the Loongson Advanced SIMD Extension + register values from the current thread. */ + +static void +fetch_lasxregs_from_thread (struct regcache *regcache, int regnum, pid_t tid) +{ + elf_lasxregset_t regset; + + if ((regnum == -1) + || (regnum >= LOONGARCH_FIRST_LASX_REGNUM + && regnum < LOONGARCH_FIRST_LASX_REGNUM + LOONGARCH_LINUX_NUM_LASXREGSET)) + { + struct iovec iovec = { .iov_base = ®set, .iov_len = sizeof (regset) }; + + if (ptrace (PTRACE_GETREGSET, tid, NT_LARCH_LASX, (long) &iovec) < 0) + { + /* If kernel dose not support lasx, just return. */ + if (errno == EINVAL) + return; + + perror_with_name (_("Couldn't get NT_LARCH_LSX registers")); + } + else + loongarch_lasxregset.supply_regset (nullptr, regcache, -1, + ®set, sizeof (regset)); + } +} + +/* Store to the current thread the valid Loongson Advanced SIMD Extension + register values in the GDB's register array. */ + +static void +store_lasxregs_to_thread (struct regcache *regcache, int regnum, pid_t tid) +{ + elf_lasxregset_t regset; + + if ((regnum == -1) + || (regnum >= LOONGARCH_FIRST_LASX_REGNUM + && regnum < LOONGARCH_FIRST_LASX_REGNUM + LOONGARCH_LINUX_NUM_LASXREGSET)) + { + struct iovec iovec = { .iov_base = ®set, .iov_len = sizeof (regset) }; + + if (ptrace (PTRACE_GETREGSET, tid, NT_LARCH_LASX, (long) &iovec) < 0) + { + /* If kernel dose not support lasx, just return. */ + if (errno == EINVAL) + return; + + perror_with_name (_("Couldn't get NT_LARCH_LSX registers")); + } + else + { + loongarch_lasxregset.collect_regset (nullptr, regcache, regnum, + ®set, sizeof (regset)); + if (ptrace (PTRACE_SETREGSET, tid, NT_LARCH_LASX, (long) &iovec) < 0) + perror_with_name (_("Couldn't set NT_LARCH_LASX registers")); + } + } +} + + /* Implement the "fetch_registers" target_ops method. */ void @@ -156,6 +275,8 @@ loongarch_linux_nat_target::fetch_registers (struct regcache *regcache, fetch_gregs_from_thread(regcache, regnum, tid); fetch_fpregs_from_thread(regcache, regnum, tid); + fetch_lsxregs_from_thread(regcache, regnum, tid); + fetch_lasxregs_from_thread(regcache, regnum, tid); } /* Implement the "store_registers" target_ops method. */ @@ -168,6 +289,8 @@ loongarch_linux_nat_target::store_registers (struct regcache *regcache, store_gregs_to_thread (regcache, regnum, tid); store_fpregs_to_thread(regcache, regnum, tid); + store_lsxregs_to_thread(regcache, regnum, tid); + store_lasxregs_to_thread(regcache, regnum, tid); } /* Return the address in the core dump or inferior of register REGNO. */ diff --git a/gdb/loongarch-linux-tdep.c b/gdb/loongarch-linux-tdep.c index 47f36a1..726b671 100644 --- a/gdb/loongarch-linux-tdep.c +++ b/gdb/loongarch-linux-tdep.c @@ -215,6 +215,129 @@ const struct regset loongarch_fpregset = loongarch_fill_fpregset, }; +/* Unpack elf_lsxregset_t into GDB's register cache. */ + +static void +loongarch_supply_lsxregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *lsxrs, size_t len) +{ + int lsxrsize = register_size (regcache->arch (), LOONGARCH_FIRST_LSX_REGNUM); + const gdb_byte *buf = nullptr; + + if (regnum == -1) + { + for (int i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++) + { + buf = (const gdb_byte*) lsxrs + lsxrsize * i; + regcache->raw_supply (LOONGARCH_FIRST_LSX_REGNUM + i, (const void *) buf); + } + + } + else if (regnum >= LOONGARCH_FIRST_LSX_REGNUM && regnum < LOONGARCH_FIRST_LASX_REGNUM) + { + buf = (const gdb_byte*) lsxrs + lsxrsize * (regnum - LOONGARCH_FIRST_LSX_REGNUM); + regcache->raw_supply (regnum, (const void *) buf); + } +} + +/* Pack the GDB's register cache value into an elf_lsxregset_t. */ + +static void +loongarch_fill_lsxregset (const struct regset *regset, + const struct regcache *regcache, int regnum, + void *lsxrs, size_t len) +{ + int lsxrsize = register_size (regcache->arch (), LOONGARCH_FIRST_LSX_REGNUM); + gdb_byte *buf = nullptr; + + if (regnum == -1) + { + for (int i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++) + { + buf = (gdb_byte *) lsxrs + lsxrsize * i; + regcache->raw_collect (LOONGARCH_FIRST_LSX_REGNUM + i, (void *) buf); + } + } + else if (regnum >= LOONGARCH_FIRST_LSX_REGNUM && regnum < LOONGARCH_FIRST_LASX_REGNUM) + { + buf = (gdb_byte *) lsxrs + lsxrsize * (regnum - LOONGARCH_FIRST_LSX_REGNUM); + regcache->raw_collect (regnum, (void *) buf); + } +} + +/* Define the Loongson SIMD Extension register regset. */ + +const struct regset loongarch_lsxregset = +{ + nullptr, + loongarch_supply_lsxregset, + loongarch_fill_lsxregset, +}; + +/* Unpack elf_lasxregset_t into GDB's register cache. */ + +static void +loongarch_supply_lasxregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *lasxrs, size_t len) +{ + int lasxrsize = register_size (regcache->arch (), LOONGARCH_FIRST_LASX_REGNUM); + const gdb_byte *buf = nullptr; + + if (regnum == -1) + { + for (int i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++) + { + buf = (const gdb_byte*) lasxrs + lasxrsize * i; + regcache->raw_supply (LOONGARCH_FIRST_LASX_REGNUM + i, (const void *) buf); + } + + } + else if (regnum >= LOONGARCH_FIRST_LASX_REGNUM + && regnum < LOONGARCH_FIRST_LASX_REGNUM + LOONGARCH_LINUX_NUM_LASXREGSET) + { + buf = (const gdb_byte*) lasxrs + lasxrsize * (regnum - LOONGARCH_FIRST_LASX_REGNUM); + regcache->raw_supply (regnum, (const void *) buf); + } +} + +/* Pack the GDB's register cache value into an elf_lasxregset_t. */ + +static void +loongarch_fill_lasxregset (const struct regset *regset, + const struct regcache *regcache, int regnum, + void *lasxrs, size_t len) +{ + int lasxrsize = register_size (regcache->arch (), LOONGARCH_FIRST_LASX_REGNUM); + gdb_byte *buf = nullptr; + + if (regnum == -1) + { + for (int i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++) + { + buf = (gdb_byte *) lasxrs + lasxrsize * i; + regcache->raw_collect (LOONGARCH_FIRST_LASX_REGNUM + i, (void *) buf); + } + } + else if (regnum >= LOONGARCH_FIRST_LASX_REGNUM + && regnum < LOONGARCH_FIRST_LASX_REGNUM + LOONGARCH_LINUX_NUM_LASXREGSET) + + { + buf = (gdb_byte *) lasxrs + lasxrsize * (regnum - LOONGARCH_FIRST_LASX_REGNUM); + regcache->raw_collect (regnum, (void *) buf); + } +} + +/* Define the Loongson Advanced SIMD Extension register regset. */ + +const struct regset loongarch_lasxregset = +{ + nullptr, + loongarch_supply_lasxregset, + loongarch_fill_lasxregset, +}; + /* Implement the "init" method of struct tramp_frame. */ #define LOONGARCH_RT_SIGFRAME_UCONTEXT_OFFSET 128 @@ -269,10 +392,17 @@ loongarch_iterate_over_regset_sections (struct gdbarch *gdbarch, int fcsrsize = register_size (gdbarch, LOONGARCH_FCSR_REGNUM); int fpsize = fprsize * LOONGARCH_LINUX_NUM_FPREGSET + fccsize * LOONGARCH_LINUX_NUM_FCC + fcsrsize; + int lsxrsize = register_size (gdbarch, LOONGARCH_FIRST_LSX_REGNUM); + int lasxrsize = register_size (gdbarch, LOONGARCH_FIRST_LASX_REGNUM); cb (".reg", LOONGARCH_LINUX_NUM_GREGSET * gprsize, LOONGARCH_LINUX_NUM_GREGSET * gprsize, &loongarch_gregset, nullptr, cb_data); cb (".reg2", fpsize, fpsize, &loongarch_fpregset, nullptr, cb_data); + cb (".reg-loongarch-lsx", lsxrsize, lsxrsize, + &loongarch_lsxregset, nullptr, cb_data); + cb (".reg-loongarch-lasx", lasxrsize, lasxrsize, + &loongarch_lasxregset, nullptr, cb_data); + } /* The following value is derived from __NR_rt_sigreturn in diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c index 6d1df85..f56e80f 100644 --- a/gdb/loongarch-tdep.c +++ b/gdb/loongarch-tdep.c @@ -1650,6 +1650,14 @@ loongarch_register_reggroup_p (struct gdbarch *gdbarch, int regnum, if (group == float_reggroup) return 0; + if (LOONGARCH_FIRST_LSX_REGNUM <= regnum + && regnum < LOONGARCH_FIRST_LASX_REGNUM + LOONGARCH_LINUX_NUM_LASXREGSET) + return group == vector_reggroup; + + /* Only $vrx / $xrx in vector_reggroup */ + if (group == vector_reggroup) + return 0; + int ret = tdesc_register_in_reggroup_p (gdbarch, regnum, group); if (ret != -1) return ret; @@ -1707,6 +1715,34 @@ loongarch_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) if (!valid_p) return nullptr; + const struct tdesc_feature *feature_lsx + = tdesc_find_feature (tdesc, "org.gnu.gdb.loongarch.lsx"); + if (feature_lsx == nullptr) + return nullptr; + + /* Validate the description provides the lsx registers and + allocate their numbers. */ + regnum = LOONGARCH_FIRST_LSX_REGNUM; + for (int i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++) + valid_p &= tdesc_numbered_register (feature_lsx, tdesc_data.get (), regnum++, + loongarch_v_normal_name[i] + 1); + if (!valid_p) + return nullptr; + + const struct tdesc_feature *feature_lasx + = tdesc_find_feature (tdesc, "org.gnu.gdb.loongarch.lasx"); + if (feature_lasx == nullptr) + return nullptr; + + /* Validate the description provides the lasx registers and + allocate their numbers. */ + regnum = LOONGARCH_FIRST_LASX_REGNUM; + for (int i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++) + valid_p &= tdesc_numbered_register (feature_lasx, tdesc_data.get (), regnum++, + loongarch_x_normal_name[i] + 1); + if (!valid_p) + return nullptr; + /* LoongArch code is always little-endian. */ info.byte_order_for_code = BFD_ENDIAN_LITTLE; diff --git a/gdb/loongarch-tdep.h b/gdb/loongarch-tdep.h index 06ce2bc..6e0e798 100644 --- a/gdb/loongarch-tdep.h +++ b/gdb/loongarch-tdep.h @@ -30,6 +30,8 @@ /* Register set definitions. */ extern const struct regset loongarch_gregset; extern const struct regset loongarch_fpregset; +extern const struct regset loongarch_lsxregset; +extern const struct regset loongarch_lasxregset; /* Target-dependent structure in gdbarch. */ struct loongarch_gdbarch_tdep : gdbarch_tdep_base diff --git a/gdbserver/linux-loongarch-low.cc b/gdbserver/linux-loongarch-low.cc index c7328b2..f33c5a6 100644 --- a/gdbserver/linux-loongarch-low.cc +++ b/gdbserver/linux-loongarch-low.cc @@ -177,12 +177,64 @@ loongarch_store_fpregset (struct regcache *regcache, const void *buf) supply_register (regcache, LOONGARCH_FCSR_REGNUM, regbuf); } +/* Collect lsx regs from REGCACHE into BUF. */ + +static void +loongarch_fill_lsxregset (struct regcache *regcache, void *buf) +{ + elf_lsxregset_t *regset = (elf_lsxregset_t *) buf; + int i; + + for (i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++) + collect_register (regcache, LOONGARCH_FIRST_LSX_REGNUM + i, *regset + i); +} + +/* Supply lsx regs from BUF into REGCACHE. */ + +static void +loongarch_store_lsxregset (struct regcache *regcache, const void *buf) +{ + const elf_lsxregset_t *regset = (const elf_lsxregset_t *) buf; + int i; + + for (i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++) + supply_register (regcache, LOONGARCH_FIRST_LSX_REGNUM + i, *regset + i); +} + +/* Collect lasx regs from REGCACHE into BUF. */ + +static void +loongarch_fill_lasxregset (struct regcache *regcache, void *buf) +{ + elf_lasxregset_t *regset = (elf_lasxregset_t *) buf; + int i; + + for (i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++) + collect_register (regcache, LOONGARCH_FIRST_LASX_REGNUM + i, *regset + i); +} + +/* Supply lasx regs from BUF into REGCACHE. */ + +static void +loongarch_store_lasxregset (struct regcache *regcache, const void *buf) +{ + const elf_lasxregset_t *regset = (const elf_lasxregset_t *) buf; + int i; + + for (i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++) + supply_register (regcache, LOONGARCH_FIRST_LASX_REGNUM + i, *regset + i); +} + /* LoongArch/Linux regsets. */ static struct regset_info loongarch_regsets[] = { { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS, sizeof (elf_gregset_t), GENERAL_REGS, loongarch_fill_gregset, loongarch_store_gregset }, { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_FPREGSET, sizeof (elf_fpregset_t), FP_REGS, loongarch_fill_fpregset, loongarch_store_fpregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_LARCH_LSX, sizeof (elf_lsxregset_t), + OPTIONAL_REGS, loongarch_fill_lsxregset, loongarch_store_lsxregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_LARCH_LASX, sizeof (elf_lasxregset_t), + OPTIONAL_REGS, loongarch_fill_lasxregset, loongarch_store_lasxregset }, NULL_REGSET }; |