aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHui Li <lihui@loongson.cn>2024-01-25 16:32:35 +0800
committerTiezhu Yang <yangtiezhu@loongson.cn>2024-02-06 18:40:02 +0800
commit1e9569f383a3d5a88ee07d0c2401bd95613c222e (patch)
tree987349cbcb070f5ec779c7f16a71df16fbc4f86f
parent60c95acdaca94eca79b81ec75bfab97826cc0271 (diff)
downloadgdb-1e9569f383a3d5a88ee07d0c2401bd95613c222e.zip
gdb-1e9569f383a3d5a88ee07d0c2401bd95613c222e.tar.gz
gdb-1e9569f383a3d5a88ee07d0c2401bd95613c222e.tar.bz2
gdb: LoongArch: Add vector extensions support
Add LoongArch's vector extensions support, which including 128bit LSX (i.e., Loongson SIMD eXtension) and 256bit LASX (i.e., Loongson Advanced SIMD eXtension). This patch support gdb to fetch/store vector registers. Signed-off-by: Hui Li <lihui@loongson.cn> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
-rw-r--r--gdb/arch/loongarch.c6
-rw-r--r--gdb/arch/loongarch.h4
-rw-r--r--gdb/features/Makefile2
-rw-r--r--gdb/features/loongarch/lasx.c85
-rw-r--r--gdb/features/loongarch/lasx.xml60
-rw-r--r--gdb/features/loongarch/lsx.c82
-rw-r--r--gdb/features/loongarch/lsx.xml59
-rw-r--r--gdb/loongarch-linux-nat.c123
-rw-r--r--gdb/loongarch-linux-tdep.c130
-rw-r--r--gdb/loongarch-tdep.c36
-rw-r--r--gdb/loongarch-tdep.h2
-rw-r--r--gdbserver/linux-loongarch-low.cc52
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 = &regset, .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,
+ &regset, 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 = &regset, .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,
+ &regset, 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 = &regset, .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,
+ &regset, 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 = &regset, .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,
+ &regset, 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
};