Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFC PATCH] gdb/py: Add pretty printer for __mfp8 for aarch64
@ 2025-11-18 14:14 Ezra.Sitorus
  2025-11-18 17:12 ` Andrew Burgess
  2025-11-18 18:42 ` Tom Tromey
  0 siblings, 2 replies; 9+ messages in thread
From: Ezra.Sitorus @ 2025-11-18 14:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: luis.machado.foss, pedro, Ezra Sitorus

From: Ezra Sitorus <ezra.sitorus@arm.com>

__mfp8/mfloat8_t is encoded as unsigned int in DWARF so we are unable to
print out variables of this type properly. As a result, this patch adds
a python pretty printer to display these values. To use:

import gdb.printer
gdb.printer.register_aarch64_fp8_printer(gdb.current_objfile())

To view which pretty printers are registered, you can check by doing:

info pretty-printer

As for precision, I've followed ceil(1 + p * log10(b)) from
gdb/target-float.c, which gives 2 figures for E5M2 and 3 for E4M3. The
pretty printer's calculation is tested for correctness in the new test
cases by matching the output string with expected values. The values
come from running a program that converts the FP8 values to FP16 and
displaying them with the number of figures from above on Arm FVP
(Shrinkwrap) with FP8 support. The only exception to this are the
special cases (inf, nan, and extra figures for E4M3).

In general, I've tried to follow the same style for displaying floats in
gdb. NaNs display their payload so I've kept that for E5M2, but in the
case of E4M3 I only use nan as there's only one.

Ezra
---
 gdb/data-directory/Makefile.in           |   1 +
 gdb/python/lib/gdb/printer/__init__.py   |   6 +
 gdb/python/lib/gdb/printer/aarch64.py    |  83 ++++++++++++++
 gdb/testsuite/gdb.python/aarch64-fp8.c   |  48 ++++++++
 gdb/testsuite/gdb.python/aarch64-fp8.exp | 137 +++++++++++++++++++++++
 gdb/testsuite/gdb.python/aarch64-fp8.py  |  18 +++
 gdb/testsuite/lib/gdb.exp                |  48 ++++++++
 7 files changed, 341 insertions(+)
 create mode 100644 gdb/python/lib/gdb/printer/aarch64.py
 create mode 100644 gdb/testsuite/gdb.python/aarch64-fp8.c
 create mode 100644 gdb/testsuite/gdb.python/aarch64-fp8.exp
 create mode 100644 gdb/testsuite/gdb.python/aarch64-fp8.py

diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in
index 2ca2b8e7e5f..097b3de670b 100644
--- a/gdb/data-directory/Makefile.in
+++ b/gdb/data-directory/Makefile.in
@@ -123,6 +123,7 @@ PYTHON_FILE_LIST = \
 	gdb/function/as_string.py \
 	gdb/function/caller_is.py \
 	gdb/function/strfns.py \
+	gdb/printer/aarch64.py \
 	gdb/printer/__init__.py
 
 @HAVE_PYTHON_TRUE@PYTHON_FILES = $(PYTHON_FILE_LIST)
diff --git a/gdb/python/lib/gdb/printer/__init__.py b/gdb/python/lib/gdb/printer/__init__.py
index 854ff3acee0..77720674e42 100644
--- a/gdb/python/lib/gdb/printer/__init__.py
+++ b/gdb/python/lib/gdb/printer/__init__.py
@@ -12,3 +12,9 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+def register_aarch64_fp8_printers(obj):
+    from .aarch64 import internal_register_aarch64_fp8_printers
+
+    internal_register_aarch64_fp8_printers(obj)
diff --git a/gdb/python/lib/gdb/printer/aarch64.py b/gdb/python/lib/gdb/printer/aarch64.py
new file mode 100644
index 00000000000..c7d9334598b
--- /dev/null
+++ b/gdb/python/lib/gdb/printer/aarch64.py
@@ -0,0 +1,83 @@
+# Copyright (C) 2008-2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+import gdb
+import gdb.printing
+
+
+# ceil(1 + p * log10(b))
+# This means that the number of significant figures for e5m2 = 2
+# and for e4m3 = 3
+
+
+class aarch64_mfp8_printer(gdb.ValuePrinter):
+    # Print aarch64 mfp8 formats
+
+    def __init__(self, val):
+        self.__val = val
+
+    def convert_to_float(self, s, e, m, m_bits, bias):
+        sign = -1.0 if s == 1 else 1.0
+        if e == 0 and m == 0:
+            return sign * 0.0
+
+        m_new = float(m) / (2**m_bits)
+        if e == 0 and m != 0:
+            e_new = float(1 - bias)
+        else:
+            e_new = float(e - bias)
+            m_new = 1 + m_new
+
+        return sign * m_new * (2.0**e_new)
+
+    def print_e4m3(self):
+        bias = 7
+        s = self.__val >> 7
+        e = (self.__val >> 3) & 0b1111
+        m = self.__val & 0b111
+
+        if e == 0b1111 and m == 0b111:
+            sign_str = "-" if s == 1 else ""
+            return sign_str + "nan"
+        return "{0:.3g}".format(self.convert_to_float(s, e, m, 3, bias))
+
+    def print_e5m2(self):
+        bias = 15
+        s = self.__val >> 7
+        e = (self.__val >> 2) & 0b11111
+        m = self.__val & 0b11
+
+        if e == 0b11111:
+            sign_str = "-" if s == 1 else ""
+            if m == 0:
+                return sign_str + "inf"
+            return sign_str + "nan(" + str(m) + ")"
+
+        return "{0:.2g}".format(self.convert_to_float(s, e, m, 2, bias))
+
+    def to_string(self):
+        return "{ e4m3: " + self.print_e4m3() + ", e5m2: " + self.print_e5m2() + " }"
+
+
+def build_pretty_printer():
+    pp = gdb.printing.RegexpCollectionPrettyPrinter("aarch64-fp8")
+    pp.add_printer("mfp8", "^__mfp8.*$", aarch64_mfp8_printer)
+    pp.add_printer("mfloat8_t", "^mfloat8_t.*$", aarch64_mfp8_printer)
+    return pp
+
+
+def internal_register_aarch64_fp8_printers(obj):
+    gdb.printing.register_pretty_printer(obj, build_pretty_printer())
diff --git a/gdb/testsuite/gdb.python/aarch64-fp8.c b/gdb/testsuite/gdb.python/aarch64-fp8.c
new file mode 100644
index 00000000000..efc5374682a
--- /dev/null
+++ b/gdb/testsuite/gdb.python/aarch64-fp8.c
@@ -0,0 +1,48 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2024-2025 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <arm_neon.h>
+
+#define MFLOAT8(X) (((union { uint8_t x; mfloat8_t y; }){ X }).y)
+
+int
+main (void)
+{
+  for (int i = 0; i < 256; i++)
+    {
+      mfloat8_t foo = MFLOAT8 (i);
+      int junk = 0; /* break1 */
+    }
+
+  struct bar
+  {
+    mfloat8_t x;
+    mfloat8_t y;
+    mfloat8_t a;
+    mfloat8_t b;
+  } bar = { MFLOAT8 (1), MFLOAT8 (2), MFLOAT8 (3), MFLOAT8 (4) };
+
+  mfloat8x16_t baz
+      = { MFLOAT8 (0),  MFLOAT8 (1),  MFLOAT8 (2),  MFLOAT8 (3),
+	  MFLOAT8 (4),  MFLOAT8 (5),  MFLOAT8 (6),  MFLOAT8 (7),
+	  MFLOAT8 (8),  MFLOAT8 (9),  MFLOAT8 (10), MFLOAT8 (11),
+	  MFLOAT8 (12), MFLOAT8 (13), MFLOAT8 (14), MFLOAT8 (15) };
+
+  /* break2 */
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.python/aarch64-fp8.exp b/gdb/testsuite/gdb.python/aarch64-fp8.exp
new file mode 100644
index 00000000000..1f1a172f68e
--- /dev/null
+++ b/gdb/testsuite/gdb.python/aarch64-fp8.exp
@@ -0,0 +1,137 @@
+# Copyright 2025 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test pretty printing of fixed-width fp8 types for AArch64.
+
+load_lib gdb-python.exp
+require allow_python_tests is_aarch64_target
+
+standard_testfile
+if {
+    [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \
+        [list debug additional_flags=-march=armv9.2-a+fp8]]} {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+set e5m2_expected_vals {
+  0 1.5e-05 3.1e-05 4.6e-05 6.1e-05 7.6e-05 9.2e-05 0.00011 \
+  0.00012 0.00015 0.00018 0.00021 0.00024 0.00031 0.00037 0.00043 \
+  0.00049 0.00061 0.00073 0.00085 0.00098 0.0012 0.0015 0.0017 \
+  0.002 0.0024 0.0029 0.0034 0.0039 0.0049 0.0059 0.0068 \
+  0.0078 0.0098 0.012 0.014 0.016 0.02 0.023 0.027 \
+  0.031 0.039 0.047 0.055 0.062 0.078 0.094 0.11 \
+  0.12 0.16 0.19 0.22 0.25 0.31 0.38 0.44 \
+  0.5 0.62 0.75 0.88 1 1.2 1.5 1.8 \
+  2 2.5 3 3.5 4 5 6 7 \
+  8 10 12 14 16 20 24 28 \
+  32 40 48 56 64 80 96 1.1e\\+02 \
+  1.3e\\+02 1.6e\\+02 1.9e\\+02 2.2e\\+02 2.6e\\+02 3.2e\\+02 3.8e\\+02 4.5e\\+02 \
+  5.1e\\+02 6.4e\\+02 7.7e\\+02 9e\\+02 1e\\+03 1.3e\\+03 1.5e\\+03 1.8e\\+03 \
+  2e\\+03 2.6e\\+03 3.1e\\+03 3.6e\\+03 4.1e\\+03 5.1e\\+03 6.1e\\+03 7.2e\\+03 \
+  8.2e\\+03 1e\\+04 1.2e\\+04 1.4e\\+04 1.6e\\+04 2e\\+04 2.5e\\+04 2.9e\\+04 \
+  3.3e\\+04 4.1e\\+04 4.9e\\+04 5.7e\\+04 inf nan\\(1\\) nan\\(2\\) nan\\(3\\) \
+  -0 -1.5e-05 -3.1e-05 -4.6e-05 -6.1e-05 -7.6e-05 -9.2e-05 -0.00011 \
+  -0.00012 -0.00015 -0.00018 -0.00021 -0.00024 -0.00031 -0.00037 -0.00043 \
+  -0.00049 -0.00061 -0.00073 -0.00085 -0.00098 -0.0012 -0.0015 -0.0017 \
+  -0.002 -0.0024 -0.0029 -0.0034 -0.0039 -0.0049 -0.0059 -0.0068 \
+  -0.0078 -0.0098 -0.012 -0.014 -0.016 -0.02 -0.023 -0.027 \
+  -0.031 -0.039 -0.047 -0.055 -0.062 -0.078 -0.094 -0.11 \
+  -0.12 -0.16 -0.19 -0.22 -0.25 -0.31 -0.38 -0.44 \
+  -0.5 -0.62 -0.75 -0.88 -1 -1.2 -1.5 -1.8 \
+  -2 -2.5 -3 -3.5 -4 -5 -6 -7 \
+  -8 -10 -12 -14 -16 -20 -24 -28 \
+  -32 -40 -48 -56 -64 -80 -96 -1.1e\\+02 \
+  -1.3e\\+02 -1.6e\\+02 -1.9e\\+02 -2.2e\\+02 -2.6e\\+02 -3.2e\\+02 -3.8e\\+02 -4.5e\\+02 \
+  -5.1e\\+02 -6.4e\\+02 -7.7e\\+02 -9e\\+02 -1e\\+03 -1.3e\\+03 -1.5e\\+03 -1.8e\\+03 \
+  -2e\\+03 -2.6e\\+03 -3.1e\\+03 -3.6e\\+03 -4.1e\\+03 -5.1e\\+03 -6.1e\\+03 -7.2e\\+03 \
+  -8.2e\\+03 -1e\\+04 -1.2e\\+04 -1.4e\\+04 -1.6e\\+04 -2e\\+04 -2.5e\\+04 -2.9e\\+04 \
+  -3.3e\\+04 -4.1e\\+04 -4.9e\\+04 -5.7e\\+04 -inf -nan\\(1\\) -nan\\(2\\) -nan\\(3\\) \
+}
+
+set e4m3_expected_vals {
+  0 0.00195 0.00391 0.00586 0.00781 0.00977 0.0117 0.0137 \
+  0.0156 0.0176 0.0195 0.0215 0.0234 0.0254 0.0273 0.0293 \
+  0.0312 0.0352 0.0391 0.043 0.0469 0.0508 0.0547 0.0586 \
+  0.0625 0.0703 0.0781 0.0859 0.0938 0.102 0.109 0.117 \
+  0.125 0.141 0.156 0.172 0.188 0.203 0.219 0.234 \
+  0.25 0.281 0.312 0.344 0.375 0.406 0.438 0.469 \
+  0.5 0.562 0.625 0.688 0.75 0.812 0.875 0.938 \
+  1 1.12 1.25 1.38 1.5 1.62 1.75 1.88 \
+  2 2.25 2.5 2.75 3 3.25 3.5 3.75 \
+  4 4.5 5 5.5 6 6.5 7 7.5 \
+  8 9 10 11 12 13 14 15 \
+  16 18 20 22 24 26 28 30 \
+  32 36 40 44 48 52 56 60 \
+  64 72 80 88 96 104 112 120 \
+  128 144 160 176 192 208 224 240 \
+  256 288 320 352 384 416 448 nan \
+  -0 -0.00195 -0.00391 -0.00586 -0.00781 -0.00977 -0.0117 -0.0137 \
+  -0.0156 -0.0176 -0.0195 -0.0215 -0.0234 -0.0254 -0.0273 -0.0293 \
+  -0.0312 -0.0352 -0.0391 -0.043 -0.0469 -0.0508 -0.0547 -0.0586 \
+  -0.0625 -0.0703 -0.0781 -0.0859 -0.0938 -0.102 -0.109 -0.117 \
+  -0.125 -0.141 -0.156 -0.172 -0.188 -0.203 -0.219 -0.234 \
+  -0.25 -0.281 -0.312 -0.344 -0.375 -0.406 -0.438 -0.469 \
+  -0.5 -0.562 -0.625 -0.688 -0.75 -0.812 -0.875 -0.938 \
+  -1 -1.12 -1.25 -1.38 -1.5 -1.62 -1.75 -1.88 \
+  -2 -2.25 -2.5 -2.75 -3 -3.25 -3.5 -3.75 \
+  -4 -4.5 -5 -5.5 -6 -6.5 -7 -7.5 \
+  -8 -9 -10 -11 -12 -13 -14 -15 \
+  -16 -18 -20 -22 -24 -26 -28 -30 \
+  -32 -36 -40 -44 -48 -52 -56 -60 \
+  -64 -72 -80 -88 -96 -104 -112 -120 \
+  -128 -144 -160 -176 -192 -208 -224 -240 \
+  -256 -288 -320 -352 -384 -416 -448 -nan \
+}
+
+set remote_python_file [gdb_remote_download host \
+    ${srcdir}/${subdir}/${testfile}.py]
+
+gdb_test_no_output "source ${remote_python_file}" "load python file"
+
+set breakpoint2 "break1"
+gdb_breakpoint [gdb_get_line_number $breakpoint2]
+for { set i 0 } { $i < 256 } { incr i } {
+    gdb_continue_to_breakpoint "Continue until breakpoint $i"
+    set e4m3_expected_val [lindex $e4m3_expected_vals $i]
+    set e5m2_expected_val [lindex $e5m2_expected_vals $i]
+    gdb_test "print foo" " = { e4m3: $e4m3_expected_val, e5m2: $e5m2_expected_val }" "fp8 check for $i"
+}
+
+set breakpoint "break2"
+gdb_breakpoint [gdb_get_line_number $breakpoint]
+gdb_continue_to_breakpoint "Continue until end"
+
+gdb_test "print bar" " = {x = { e4m3: 0.00195, e5m2: 1.5e-05 }, y = { e4m3: 0.00391, e5m2: 3.1e-05 }, a = { e4m3: 0.00586, e5m2: 4.6e-05 }, b = { e4m3: 0.00781, e5m2: 6.1e-05 }}"
+
+gdb_test "print baz" " = {{ e4m3: 0, e5m2: 0 },\
+                           { e4m3: 0.00195, e5m2: 1.5e-05 },\
+                           { e4m3: 0.00391, e5m2: 3.1e-05 },\
+                           { e4m3: 0.00586, e5m2: 4.6e-05 },\
+                           { e4m3: 0.00781, e5m2: 6.1e-05 },\
+                           { e4m3: 0.00977, e5m2: 7.6e-05 },\
+                           { e4m3: 0.0117, e5m2: 9.2e-05 },\
+                           { e4m3: 0.0137, e5m2: 0.00011 },\
+                           { e4m3: 0.0156, e5m2: 0.00012 },\
+                           { e4m3: 0.0176, e5m2: 0.00015 },\
+                           { e4m3: 0.0195, e5m2: 0.00018 },\
+                           { e4m3: 0.0215, e5m2: 0.00021 },\
+                           { e4m3: 0.0234, e5m2: 0.00024 },\
+                           { e4m3: 0.0254, e5m2: 0.00031 },\
+                           { e4m3: 0.0273, e5m2: 0.00037 },\
+                           { e4m3: 0.0293, e5m2: 0.00043 }}"
diff --git a/gdb/testsuite/gdb.python/aarch64-fp8.py b/gdb/testsuite/gdb.python/aarch64-fp8.py
new file mode 100644
index 00000000000..3ba2916de5b
--- /dev/null
+++ b/gdb/testsuite/gdb.python/aarch64-fp8.py
@@ -0,0 +1,18 @@
+# Copyright (C) 2008-2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import gdb.printer
+
+gdb.printer.register_aarch64_fp8_printers(gdb.current_objfile())
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 930462f63fa..6996926236a 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -4897,6 +4897,54 @@ gdb_caching_proc allow_btrace_pt_event_trace_tests {} {
     return $allow_event_trace_tests
 }
 
+# Run a test on the target to see if it supports AArch64 FP8 hardware.
+# Return 1 if so, 0 if it does not.  Note this causes a restart of GDB.
+
+gdb_caching_proc allow_aarch64_fp8_tests {} {
+    global srcdir subdir gdb_prompt inferior_exited_re
+
+    set me "allow_aarch64_fp8_tests"
+
+    if { ![is_aarch64_target]} {
+	return 0
+    }
+
+    set compile_flags "{additional_flags=-march=armv9.2-a+fp8}"
+
+    # Compile a test program containing FP8 instructions.
+    set src {
+	int main() {
+	    asm volatile ("fscale v0.4h, v1.4h, v2.4h");
+	    return 0;
+	}
+    }
+    if {![gdb_simple_compile $me $src executable $compile_flags]} {
+        return 0
+    }
+
+    # Compilation succeeded so now run it via gdb.
+    clean_restart
+    gdb_load $obj
+    gdb_run_cmd
+    gdb_expect {
+        -re ".*Illegal instruction.*${gdb_prompt} $" {
+            verbose -log "\n$me fp8 hardware not detected"
+            set allow_fp8_tests 0
+        }
+        -re ".*$inferior_exited_re normally.*${gdb_prompt} $" {
+            verbose -log "\n$me: fp8 hardware detected"
+            set allow_fp8_tests 1
+        }
+        default {
+          warning "\n$me: default case taken"
+            set allow_fp8_tests 0
+        }
+    }
+    gdb_exit
+    remote_file build delete $obj
+
+    return $allow_fp8_tests
+}
 
 # Run a test on the target to see if it supports Aarch64 SVE hardware.
 # Return 1 if so, 0 if it does not.  Note this causes a restart of GDB.
-- 
2.45.2


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2025-12-16 16:40 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-11-18 14:14 [RFC PATCH] gdb/py: Add pretty printer for __mfp8 for aarch64 Ezra.Sitorus
2025-11-18 17:12 ` Andrew Burgess
2025-11-18 18:37   ` Ezra Sitorus
2025-11-26 16:08   ` Ezra Sitorus
2025-11-18 18:42 ` Tom Tromey
2025-11-19 13:12   ` Ezra Sitorus
2025-11-19 15:58     ` Tom Tromey
2025-11-19 21:28       ` Ezra Sitorus
2025-12-16 16:39       ` Ezra Sitorus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox