* [PATCH 1/2] gdb: LoongArch: Add vector extensions support
2024-01-25 8:32 [PATCH 0/2] gdb: LoongArch: Add vector & lbt extensions support Hui Li
@ 2024-01-25 8:32 ` Hui Li
2024-01-25 8:32 ` [PATCH 2/2] gdb: LoongArch: Add LBT extension support Hui Li
2024-02-06 10:54 ` [PATCH 0/2] gdb: LoongArch: Add vector & lbt extensions support Tiezhu Yang
2 siblings, 0 replies; 4+ messages in thread
From: Hui Li @ 2024-01-25 8:32 UTC (permalink / raw)
To: gdb-patches, Tiezhu Yang
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>
---
gdb/arch/loongarch.c | 6 ++
gdb/arch/loongarch.h | 4 +
gdb/features/Makefile | 2 +
gdb/features/loongarch/lasx.c | 85 ++++++++++++++++++++
gdb/features/loongarch/lasx.xml | 60 ++++++++++++++
gdb/features/loongarch/lsx.c | 82 +++++++++++++++++++
gdb/features/loongarch/lsx.xml | 59 ++++++++++++++
gdb/loongarch-linux-nat.c | 123 +++++++++++++++++++++++++++++
gdb/loongarch-linux-tdep.c | 130 +++++++++++++++++++++++++++++++
gdb/loongarch-tdep.c | 36 +++++++++
gdb/loongarch-tdep.h | 2 +
gdbserver/linux-loongarch-low.cc | 52 +++++++++++++
12 files changed, 641 insertions(+)
create mode 100644 gdb/features/loongarch/lasx.c
create mode 100644 gdb/features/loongarch/lasx.xml
create mode 100644 gdb/features/loongarch/lsx.c
create mode 100644 gdb/features/loongarch/lsx.xml
diff --git a/gdb/arch/loongarch.c b/gdb/arch/loongarch.c
index d1a7bad4d58..e9995c9fe0f 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 1fe75d016de..d166f9d5eb9 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 cda6a49d563..7c33c093375 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 00000000000..52d486ecb09
--- /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 00000000000..753b982c651
--- /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 00000000000..0067c2fe385
--- /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 00000000000..e19a404dfd5
--- /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 fe65b5dfa30..85d0a9619c0 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 47f36a18931..726b6716270 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 6d1df8599eb..f56e80f15b8 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 06ce2bc3640..6e0e798e6c8 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 c7328b2121e..f33c5a67882 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
};
--
2.38.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 2/2] gdb: LoongArch: Add LBT extension support
2024-01-25 8:32 [PATCH 0/2] gdb: LoongArch: Add vector & lbt extensions support Hui Li
2024-01-25 8:32 ` [PATCH 1/2] gdb: LoongArch: Add vector " Hui Li
@ 2024-01-25 8:32 ` Hui Li
2024-02-06 10:54 ` [PATCH 0/2] gdb: LoongArch: Add vector & lbt extensions support Tiezhu Yang
2 siblings, 0 replies; 4+ messages in thread
From: Hui Li @ 2024-01-25 8:32 UTC (permalink / raw)
To: gdb-patches, Tiezhu Yang
From: Feiyang Chen <chenfeiyang@loongson.cn>
Loongson Binary Translation (LBT) is used to accelerate binary
translation, which contains 4 scratch registers (scr0 to scr3),
x86/ARM eflags (eflags) and x87 fpu stack pointer (ftop). This
patch support gdb to fetch/store these registers.
Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn> # Framework
Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn> # Detail Optimizes
Signed-off-by: Hui Li <lihui@loongson.cn> # Error Fixes
---
gdb/arch/loongarch.c | 4 ++
gdb/arch/loongarch.h | 8 +++
gdb/features/Makefile | 1 +
gdb/features/loongarch/lbt.c | 19 ++++++
gdb/features/loongarch/lbt.xml | 16 +++++
gdb/loongarch-linux-nat.c | 66 +++++++++++++++++++
gdb/loongarch-linux-tdep.c | 107 +++++++++++++++++++++++++++++++
gdb/loongarch-tdep.c | 18 ++++++
gdb/loongarch-tdep.h | 1 +
gdbserver/linux-loongarch-low.cc | 43 +++++++++++++
10 files changed, 283 insertions(+)
create mode 100644 gdb/features/loongarch/lbt.c
create mode 100644 gdb/features/loongarch/lbt.xml
diff --git a/gdb/arch/loongarch.c b/gdb/arch/loongarch.c
index e9995c9fe0f..22f2d3936ca 100644
--- a/gdb/arch/loongarch.c
+++ b/gdb/arch/loongarch.c
@@ -27,6 +27,7 @@
#include "../features/loongarch/fpu.c"
#include "../features/loongarch/lsx.c"
#include "../features/loongarch/lasx.c"
+#include "../features/loongarch/lbt.c"
#ifndef GDBSERVER
#define STATIC_IN_GDB static
@@ -69,6 +70,9 @@ loongarch_create_target_description (const struct loongarch_gdbarch_features fea
regnum = create_feature_loongarch_lsx (tdesc.get (), regnum);
regnum = create_feature_loongarch_lasx (tdesc.get (), regnum);
+ /* For now we only support creating scr registers, eflags and ftop. */
+ regnum = create_feature_loongarch_lbt (tdesc.get (), regnum);
+
return tdesc;
}
diff --git a/gdb/arch/loongarch.h b/gdb/arch/loongarch.h
index d166f9d5eb9..4b7ab054ea0 100644
--- a/gdb/arch/loongarch.h
+++ b/gdb/arch/loongarch.h
@@ -45,6 +45,12 @@ enum loongarch_regnum
LOONGARCH_LINUX_NUM_LSXREGSET = 32,
LOONGARCH_FIRST_LASX_REGNUM = LOONGARCH_FIRST_LSX_REGNUM + LOONGARCH_LINUX_NUM_LSXREGSET,
LOONGARCH_LINUX_NUM_LASXREGSET = 32,
+
+ LOONGARCH_FIRST_SCR_REGNUM = LOONGARCH_FIRST_LASX_REGNUM + LOONGARCH_LINUX_NUM_LASXREGSET,
+ LOONGARCH_LINUX_NUM_SCR = 4,
+ LOONGARCH_LAST_SCR_REGNUM = LOONGARCH_FIRST_SCR_REGNUM + LOONGARCH_LINUX_NUM_SCR - 1,
+ LOONGARCH_EFLAGS_REGNUM = LOONGARCH_LAST_SCR_REGNUM + 1,
+ LOONGARCH_FTOP_REGNUM = LOONGARCH_EFLAGS_REGNUM + 1,
};
enum loongarch_fputype
@@ -53,6 +59,8 @@ enum loongarch_fputype
DOUBLE_FLOAT = 2,
};
+ #define LOONGARCH_LBT_REGS_SIZE (8 * LOONGARCH_LINUX_NUM_SCR + 4 + 4)
+
/* The set of LoongArch architectural features that we track that impact how
we configure the actual gdbarch instance. We hold one of these in the
gdbarch_tdep structure, and use it to distinguish between different
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index 7c33c093375..ddf4ec295a9 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -239,6 +239,7 @@ FEATURE_XMLFILES = aarch64-core.xml \
loongarch/fpu.xml \
loongarch/lsx.xml \
loongarch/lasx.xml \
+ loongarch/lbt.xml \
riscv/rv32e-xregs.xml \
riscv/32bit-cpu.xml \
riscv/32bit-fpu.xml \
diff --git a/gdb/features/loongarch/lbt.c b/gdb/features/loongarch/lbt.c
new file mode 100644
index 00000000000..869c86248c4
--- /dev/null
+++ b/gdb/features/loongarch/lbt.c
@@ -0,0 +1,19 @@
+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
+ Original: lbt.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_loongarch_lbt (struct target_desc *result, long regnum)
+{
+ struct tdesc_feature *feature;
+
+ feature = tdesc_create_feature (result, "org.gnu.gdb.loongarch.lbt");
+ tdesc_create_reg (feature, "scr0", regnum++, 1, "lbt", 64, "uint64");
+ tdesc_create_reg (feature, "scr1", regnum++, 1, "lbt", 64, "uint64");
+ tdesc_create_reg (feature, "scr2", regnum++, 1, "lbt", 64, "uint64");
+ tdesc_create_reg (feature, "scr3", regnum++, 1, "lbt", 64, "uint64");
+ tdesc_create_reg (feature, "eflags", regnum++, 1, "lbt", 32, "uint32");
+ tdesc_create_reg (feature, "ftop", regnum++, 1, "lbt", 32, "uint32");
+ return regnum;
+}
diff --git a/gdb/features/loongarch/lbt.xml b/gdb/features/loongarch/lbt.xml
new file mode 100644
index 00000000000..6526ee6068f
--- /dev/null
+++ b/gdb/features/loongarch/lbt.xml
@@ -0,0 +1,16 @@
+<?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.lbt">
+ <reg name="scr0" bitsize="64" type="uint64" group="lbt"/>
+ <reg name="scr1" bitsize="64" type="uint64" group="lbt"/>
+ <reg name="scr2" bitsize="64" type="uint64" group="lbt"/>
+ <reg name="scr3" bitsize="64" type="uint64" group="lbt"/>
+ <reg name="eflags" bitsize="32" type="uint32" group="lbt"/>
+ <reg name="ftop" bitsize="32" type="uint32" group="lbt"/>
+</feature>
diff --git a/gdb/loongarch-linux-nat.c b/gdb/loongarch-linux-nat.c
index 85d0a9619c0..9bceb8a5953 100644
--- a/gdb/loongarch-linux-nat.c
+++ b/gdb/loongarch-linux-nat.c
@@ -265,6 +265,70 @@ store_lasxregs_to_thread (struct regcache *regcache, int regnum, pid_t tid)
}
+/* Fill GDB's register array with the lbt register values
+ from the current thread. */
+
+static void
+fetch_lbt_from_thread (struct regcache *regcache, int regnum, pid_t tid)
+{
+ gdb_byte regset[LOONGARCH_LBT_REGS_SIZE];
+
+ if (regnum == -1
+ || (regnum >= LOONGARCH_FIRST_SCR_REGNUM
+ && regnum <= LOONGARCH_FTOP_REGNUM))
+ {
+ struct iovec iov;
+
+ iov.iov_base = regset;
+ iov.iov_len = LOONGARCH_LBT_REGS_SIZE;
+
+ if (ptrace (PTRACE_GETREGSET, tid, NT_LARCH_LBT, (long) &iov) < 0)
+ {
+ /* If kernel dose not support lbt, just return. */
+ if (errno == EINVAL)
+ return;
+ perror_with_name (_("Couldn't get NT_LARCH_LBT registers"));
+ }
+ else
+ loongarch_lbtregset.supply_regset (nullptr, regcache, -1,
+ regset, LOONGARCH_LBT_REGS_SIZE);
+ }
+}
+
+/* Store to the current thread the valid lbt register values
+ in the GDB's register array. */
+
+static void
+store_lbt_to_thread (struct regcache *regcache, int regnum, pid_t tid)
+{
+ gdb_byte regset[LOONGARCH_LBT_REGS_SIZE];
+
+ if (regnum == -1
+ || (regnum >= LOONGARCH_FIRST_SCR_REGNUM
+ && regnum <= LOONGARCH_FTOP_REGNUM))
+ {
+ struct iovec iov;
+
+ iov.iov_base = regset;
+ iov.iov_len = LOONGARCH_LBT_REGS_SIZE;
+
+ if (ptrace (PTRACE_GETREGSET, tid, NT_LARCH_LBT, (long) &iov) < 0)
+ {
+ /* If kernel dose not support lbt, just return. */
+ if (errno == EINVAL)
+ return;
+ perror_with_name (_("Couldn't get NT_LARCH_LBT registers"));
+ }
+ else
+ {
+ loongarch_lbtregset.collect_regset (nullptr, regcache, regnum,
+ regset, LOONGARCH_LBT_REGS_SIZE);
+ if (ptrace (PTRACE_SETREGSET, tid, NT_LARCH_LBT, (long) &iov) < 0)
+ perror_with_name (_("Couldn't set NT_LARCH_LBT registers"));
+ }
+ }
+}
+
/* Implement the "fetch_registers" target_ops method. */
void
@@ -277,6 +341,7 @@ loongarch_linux_nat_target::fetch_registers (struct regcache *regcache,
fetch_fpregs_from_thread(regcache, regnum, tid);
fetch_lsxregs_from_thread(regcache, regnum, tid);
fetch_lasxregs_from_thread(regcache, regnum, tid);
+ fetch_lbt_from_thread (regcache, regnum, tid);
}
/* Implement the "store_registers" target_ops method. */
@@ -291,6 +356,7 @@ loongarch_linux_nat_target::store_registers (struct regcache *regcache,
store_fpregs_to_thread(regcache, regnum, tid);
store_lsxregs_to_thread(regcache, regnum, tid);
store_lasxregs_to_thread(regcache, regnum, tid);
+ store_lbt_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 726b6716270..0e82c09b4ff 100644
--- a/gdb/loongarch-linux-tdep.c
+++ b/gdb/loongarch-linux-tdep.c
@@ -338,6 +338,107 @@ const struct regset loongarch_lasxregset =
loongarch_fill_lasxregset,
};
+/* Unpack an lbt regset into GDB's register cache. */
+
+static void
+loongarch_supply_lbtregset (const struct regset *regset,
+ struct regcache *regcache, int regnum,
+ const void *regs, size_t len)
+{
+ int scrsize = register_size (regcache->arch (), LOONGARCH_FIRST_SCR_REGNUM);
+ int eflagssize = register_size (regcache->arch (), LOONGARCH_EFLAGS_REGNUM);
+ const gdb_byte *buf = nullptr;
+
+ if (regnum == -1)
+ {
+ for (int i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++)
+ {
+ buf = (const gdb_byte *) regs + scrsize * i;
+ regcache->raw_supply (LOONGARCH_FIRST_SCR_REGNUM + i,
+ (const void *) buf);
+ }
+
+ buf = (const gdb_byte*) regs + scrsize * LOONGARCH_LINUX_NUM_SCR;
+ regcache->raw_supply (LOONGARCH_EFLAGS_REGNUM, (const void *) buf);
+
+ buf = (const gdb_byte*) regs
+ + scrsize * LOONGARCH_LINUX_NUM_SCR
+ + eflagssize;
+ regcache->raw_supply (LOONGARCH_FTOP_REGNUM, (const void *) buf);
+ }
+ else if (regnum >= LOONGARCH_FIRST_SCR_REGNUM
+ && regnum <= LOONGARCH_LAST_SCR_REGNUM)
+ {
+ buf = (const gdb_byte*) regs
+ + scrsize * (regnum - LOONGARCH_FIRST_SCR_REGNUM);
+ regcache->raw_supply (regnum, (const void *) buf);
+ }
+ else if (regnum == LOONGARCH_EFLAGS_REGNUM)
+ {
+ buf = (const gdb_byte*) regs + scrsize * LOONGARCH_LINUX_NUM_SCR;
+ regcache->raw_supply (regnum, (const void *) buf);
+ }
+ else if (regnum == LOONGARCH_FTOP_REGNUM)
+ {
+ buf = (const gdb_byte*) regs
+ + scrsize * LOONGARCH_LINUX_NUM_SCR
+ + eflagssize;
+ regcache->raw_supply (regnum, (const void *) buf);
+ }
+}
+
+/* Pack the GDB's register cache value into an lbt regset. */
+
+static void
+loongarch_fill_lbtregset (const struct regset *regset,
+ const struct regcache *regcache, int regnum,
+ void *regs, size_t len)
+{
+ int scrsize = register_size (regcache->arch (), LOONGARCH_FIRST_SCR_REGNUM);
+ int eflagssize = register_size (regcache->arch (), LOONGARCH_EFLAGS_REGNUM);
+ gdb_byte *buf = nullptr;
+
+ if (regnum == -1)
+ {
+ for (int i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++)
+ {
+ buf = (gdb_byte *) regs + scrsize * i;
+ regcache->raw_collect (LOONGARCH_FIRST_SCR_REGNUM + i, (void *) buf);
+ }
+
+ buf = (gdb_byte *) regs + scrsize * LOONGARCH_LINUX_NUM_SCR;
+ regcache->raw_collect (LOONGARCH_EFLAGS_REGNUM, (void *) buf);
+
+ buf = (gdb_byte *) regs + scrsize * LOONGARCH_LINUX_NUM_SCR + eflagssize;
+ regcache->raw_collect (LOONGARCH_FTOP_REGNUM, (void *) buf);
+ }
+ else if (regnum >= LOONGARCH_FIRST_SCR_REGNUM
+ && regnum <= LOONGARCH_LAST_SCR_REGNUM)
+ {
+ buf = (gdb_byte *) regs + scrsize * (regnum - LOONGARCH_FIRST_SCR_REGNUM);
+ regcache->raw_collect (regnum, (void *) buf);
+ }
+ else if (regnum == LOONGARCH_EFLAGS_REGNUM)
+ {
+ buf = (gdb_byte *) regs + scrsize * LOONGARCH_LINUX_NUM_SCR;
+ regcache->raw_collect (regnum, (void *) buf);
+ }
+ else if (regnum == LOONGARCH_FTOP_REGNUM)
+ {
+ buf = (gdb_byte *) regs + scrsize * LOONGARCH_LINUX_NUM_SCR + eflagssize;
+ regcache->raw_collect (regnum, (void *) buf);
+ }
+}
+
+/* Define the lbt register regset. */
+
+const struct regset loongarch_lbtregset =
+{
+ nullptr,
+ loongarch_supply_lbtregset,
+ loongarch_fill_lbtregset,
+};
+
/* Implement the "init" method of struct tramp_frame. */
#define LOONGARCH_RT_SIGFRAME_UCONTEXT_OFFSET 128
@@ -394,6 +495,10 @@ loongarch_iterate_over_regset_sections (struct gdbarch *gdbarch,
fccsize * LOONGARCH_LINUX_NUM_FCC + fcsrsize;
int lsxrsize = register_size (gdbarch, LOONGARCH_FIRST_LSX_REGNUM);
int lasxrsize = register_size (gdbarch, LOONGARCH_FIRST_LASX_REGNUM);
+ int scrsize = register_size (gdbarch, LOONGARCH_FIRST_SCR_REGNUM);
+ int eflagssize = register_size (gdbarch, LOONGARCH_EFLAGS_REGNUM);
+ int ftopsize = register_size (gdbarch, LOONGARCH_FTOP_REGNUM);
+ int lbtsize = scrsize * LOONGARCH_LINUX_NUM_SCR + eflagssize + ftopsize;
cb (".reg", LOONGARCH_LINUX_NUM_GREGSET * gprsize,
LOONGARCH_LINUX_NUM_GREGSET * gprsize, &loongarch_gregset, nullptr, cb_data);
@@ -402,6 +507,8 @@ loongarch_iterate_over_regset_sections (struct gdbarch *gdbarch,
&loongarch_lsxregset, nullptr, cb_data);
cb (".reg-loongarch-lasx", lasxrsize, lasxrsize,
&loongarch_lasxregset, nullptr, cb_data);
+ cb (".reg-loongarch-lbt", lbtsize, lbtsize,
+ &loongarch_lbtregset, nullptr, cb_data);
}
diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c
index f56e80f15b8..0f4622a55be 100644
--- a/gdb/loongarch-tdep.c
+++ b/gdb/loongarch-tdep.c
@@ -1743,6 +1743,24 @@ loongarch_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
if (!valid_p)
return nullptr;
+ const struct tdesc_feature *feature_lbt
+ = tdesc_find_feature (tdesc, "org.gnu.gdb.loongarch.lbt");
+ if (feature_lbt == nullptr)
+ return nullptr;
+
+ /* Validate the description provides the lbt registers and
+ allocate their numbers. */
+ regnum = LOONGARCH_FIRST_SCR_REGNUM;
+ for (int i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++)
+ valid_p &= tdesc_numbered_register (feature_lbt, tdesc_data.get (), regnum++,
+ loongarch_cr_normal_name[i] + 1);
+ valid_p &= tdesc_numbered_register (feature_lbt, tdesc_data.get (), regnum++,
+ "eflags");
+ valid_p &= tdesc_numbered_register (feature_lbt, tdesc_data.get (), regnum++,
+ "ftop");
+ 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 6e0e798e6c8..bfe398898c0 100644
--- a/gdb/loongarch-tdep.h
+++ b/gdb/loongarch-tdep.h
@@ -32,6 +32,7 @@ extern const struct regset loongarch_gregset;
extern const struct regset loongarch_fpregset;
extern const struct regset loongarch_lsxregset;
extern const struct regset loongarch_lasxregset;
+extern const struct regset loongarch_lbtregset;
/* 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 f33c5a67882..f1e1deb878b 100644
--- a/gdbserver/linux-loongarch-low.cc
+++ b/gdbserver/linux-loongarch-low.cc
@@ -225,6 +225,47 @@ loongarch_store_lasxregset (struct regcache *regcache, const void *buf)
supply_register (regcache, LOONGARCH_FIRST_LASX_REGNUM + i, *regset + i);
}
+/* Collect lbt regs from REGCACHE into BUF. */
+
+static void
+loongarch_fill_lbtregset (struct regcache *regcache, void *buf)
+{
+ gdb_byte *regbuf = (gdb_byte*)buf;
+ int scrsize = register_size (regcache->tdesc, LOONGARCH_FIRST_SCR_REGNUM);
+ int eflagssize = register_size (regcache->tdesc, LOONGARCH_EFLAGS_REGNUM);
+ int i;
+
+ for (i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++)
+ collect_register (regcache, LOONGARCH_FIRST_SCR_REGNUM + i, regbuf + scrsize * i);
+
+ collect_register (regcache, LOONGARCH_EFLAGS_REGNUM,
+ regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize);
+ collect_register (regcache, LOONGARCH_FTOP_REGNUM,
+ regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize + eflagssize);
+
+}
+
+/* Supply lbt regs from BUF into REGCACHE. */
+
+static void
+loongarch_store_lbtregset (struct regcache *regcache, const void *buf)
+{
+
+ gdb_byte *regbuf = (gdb_byte*)buf;
+ int scrsize = register_size (regcache->tdesc, LOONGARCH_FIRST_SCR_REGNUM);
+ int eflagssize = register_size (regcache->tdesc, LOONGARCH_EFLAGS_REGNUM);
+ int i;
+
+ for (i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++)
+ supply_register (regcache, LOONGARCH_FIRST_SCR_REGNUM + i, regbuf + scrsize * i);
+
+ supply_register (regcache, LOONGARCH_EFLAGS_REGNUM,
+ regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize);
+ supply_register (regcache, LOONGARCH_FTOP_REGNUM,
+ regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize + eflagssize);
+
+}
+
/* LoongArch/Linux regsets. */
static struct regset_info loongarch_regsets[] = {
{ PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS, sizeof (elf_gregset_t),
@@ -235,6 +276,8 @@ static struct regset_info loongarch_regsets[] = {
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 },
+ { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_LARCH_LBT, LOONGARCH_LBT_REGS_SIZE,
+ OPTIONAL_REGS, loongarch_fill_lbtregset, loongarch_store_lbtregset },
NULL_REGSET
};
--
2.38.1
^ permalink raw reply [flat|nested] 4+ messages in thread