PR #25755 opened by Martin Storsjö (mstorsjo)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25755
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25755.patch
These currently allow printing GPRs, SIMD vectors and memory.
GPRs are printed as signed decimal and unsigned hexadecimal.
SIMD vectors are printed as signed or unsigned decimal, as either
8, 16 or 32 bit elements.
Memory can be dumped, interpreted as a stored SIMD vector, by
specifying a base register and how many vectors to read from that
address.
Usage example:
DUMP_SIMD_U8("input", 4, 5) /* Printing v4-v5 as 8 bit unsigned elments */
DUMP_SIMD_S16("sum", 6, 6) /* Printing v6 as 16 bit signed elments */
DUMP_GPR("w,h", 4, 5) /* Printing x4-x5 */
Which prints:
3450: input:
v04.16b = { 201, 1, 245, 0, 139, 0, 225, 1, 33, 1, 254, 0, 41, 2, 212, 1 }
3451: sum:
v06.8h = { 20394, -23720, -30625, 32619, -28321, 11312, 30270, 32051 }
3468: w,h:
x04 = 16 (0x10)
x05 = 64 (0x40)
(or)
3468: w,h:
x04 = -2401053092612145136 (0xdeadbeef00000010)
x05 = -2401053092612145148 (0xdeadbeef00000004)
For inspecting memory:
DUMP_MEM_S16("out", x0, 2) /* Print 2 vectors worth of data from x0, as s16
*/
Which can print:
3523: out:
v00.8h = { 12340, 18058, 21605, -10848, -32395, -26577, -15192, 26296 }
v01.8h = { 1998, 1722, 24014, -17100, 2150, -26619, -23289, -4052 }
Using these macros requires linking in the debug printing helper
functions, which can be enabled by passing `--enable-asm-debug` to
the configure command.
From ddc7f14b09d44ed60704c5ad6eee12eca9d35cea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <[email protected]>
Date: Fri, 22 Mar 2024 10:58:36 +0200
Subject: [PATCH] arm/aarch64: Add helpers for debug printing from assembly
These currently allow printing GPRs, SIMD vectors and memory.
GPRs are printed as signed decimal and unsigned hexadecimal.
SIMD vectors are printed as signed or unsigned decimal, as either
8, 16 or 32 bit elements.
Memory can be dumped, interpreted as a stored SIMD vector, by
specifying a base register and how many vectors to read from that
address.
Usage example:
DUMP_SIMD_U8("input", 4, 5) /* Printing v4-v5 as 8 bit unsigned elments */
DUMP_SIMD_S16("sum", 6, 6) /* Printing v6 as 16 bit signed elments */
DUMP_GPR("w,h", 4, 5) /* Printing x4-x5 */
Which prints:
3450: input:
v04.16b = { 201, 1, 245, 0, 139, 0, 225, 1, 33, 1, 254, 0, 41, 2, 212, 1 }
3451: sum:
v06.8h = { 20394, -23720, -30625, 32619, -28321, 11312, 30270, 32051 }
3468: w,h:
x04 = 16 (0x10)
x05 = 64 (0x40)
(or)
3468: w,h:
x04 = -2401053092612145136 (0xdeadbeef00000010)
x05 = -2401053092612145148 (0xdeadbeef00000004)
For inspecting memory:
DUMP_MEM_S16("out", x0, 2) /* Print 2 vectors worth of data from x0, as s16
*/
Which can print:
3523: out:
v00.8h = { 12340, 18058, 21605, -10848, -32395, -26577, -15192, 26296 }
v01.8h = { 1998, 1722, 24014, -17100, 2150, -26619, -23289, -4052 }
Using these macros requires linking in the debug printing helper
functions, which can be enabled by passing --enable-asm-debug to
the configure command.
---
configure | 2 +
libavutil/Makefile | 1 +
libavutil/aarch64/asm.S | 106 +++++++++++++++++++++++++
libavutil/arm/asm.S | 47 +++++++++++
libavutil/arm_asm_debug.c | 161 ++++++++++++++++++++++++++++++++++++++
5 files changed, 317 insertions(+)
create mode 100644 libavutil/arm_asm_debug.c
diff --git a/configure b/configure
index 2bbc7812eb3..e8c11f88be9 100755
--- a/configure
+++ b/configure
@@ -541,6 +541,7 @@ Developer options (useful when working on FFmpeg itself):
--disable-shader-compression don't compress shader code even when possible
--disable-resource-compression don't compress resources even when possible
--disable-version-tracking don't include the git/release version in the build
+ --enable-asm-debug include functions for assembly debugging
NOTE: Object files are built at the place where configure is launched.
EOF
@@ -2249,6 +2250,7 @@ CONFIG_LIST="
$PROGRAM_LIST
$SUBSYSTEM_LIST
autodetect
+ asm_debug
fontconfig
large_tests
linux_perf
diff --git a/libavutil/Makefile b/libavutil/Makefile
index 1f91fd5d170..76f1391a809 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -207,6 +207,7 @@ OBJS = adler32.o
\
video_hint.o \
+OBJS-$(CONFIG_ASM_DEBUG) += arm_asm_debug.o
OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o
OBJS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.o
OBJS-$(CONFIG_D3D12VA) += hwcontext_d3d12va.o
diff --git a/libavutil/aarch64/asm.S b/libavutil/aarch64/asm.S
index 665202a8082..0ef45efade0 100644
--- a/libavutil/aarch64/asm.S
+++ b/libavutil/aarch64/asm.S
@@ -370,3 +370,109 @@ ELF .size \name, . - \name
AARCH64_VALIDATE_LINK_REGISTER
.endm
#endif
+
+
+#if CONFIG_ASM_DEBUG
+#undef x18
+.macro call_c func, line, msg, first, last, ptr, offset
+ stp x29, x30, [sp, #-16]!
+ stp x27, x28, [sp, #-16]!
+ stp x25, x26, [sp, #-16]!
+ stp x23, x24, [sp, #-16]!
+ stp x21, x22, [sp, #-16]!
+ stp x19, x20, [sp, #-16]!
+ stp x17, x18, [sp, #-16]!
+ stp x15, x16, [sp, #-16]!
+ stp x13, x14, [sp, #-16]!
+ stp x11, x12, [sp, #-16]!
+ stp x9, x10, [sp, #-16]!
+ stp x7, x8, [sp, #-16]!
+ stp x5, x6, [sp, #-16]!
+ stp x3, x4, [sp, #-16]!
+ stp x1, x2, [sp, #-16]!
+ mrs x30, nzcv
+ stp x30, x0, [sp, #-16]!
+
+ stp q30, q31, [sp, #-32]!
+ stp q28, q29, [sp, #-32]!
+ stp q26, q27, [sp, #-32]!
+ stp q24, q25, [sp, #-32]!
+ stp q22, q23, [sp, #-32]!
+ stp q20, q21, [sp, #-32]!
+ stp q18, q19, [sp, #-32]!
+ stp q16, q17, [sp, #-32]!
+ stp q14, q15, [sp, #-32]!
+ stp q12, q13, [sp, #-32]!
+ stp q10, q11, [sp, #-32]!
+ stp q8, q9, [sp, #-32]!
+ stp q6, q7, [sp, #-32]!
+ stp q4, q5, [sp, #-32]!
+ stp q2, q3, [sp, #-32]!
+ stp q0, q1, [sp, #-32]!
+
+ add x4, \ptr, #\offset
+ ldr x0, =\line
+ adr x1, 777f
+ mov x2, \first
+ mov x3, \last
+ bl X(ff_\func)
+
+ ldp q0, q1, [sp], #32
+ ldp q2, q3, [sp], #32
+ ldp q4, q5, [sp], #32
+ ldp q6, q7, [sp], #32
+ ldp q8, q9, [sp], #32
+ ldp q10, q11, [sp], #32
+ ldp q12, q13, [sp], #32
+ ldp q14, q15, [sp], #32
+ ldp q16, q17, [sp], #32
+ ldp q18, q19, [sp], #32
+ ldp q20, q21, [sp], #32
+ ldp q22, q23, [sp], #32
+ ldp q24, q25, [sp], #32
+ ldp q26, q27, [sp], #32
+ ldp q28, q29, [sp], #32
+ ldp q30, q31, [sp], #32
+
+ ldp x30, x0, [sp], #16
+ msr nzcv, x30
+ ldp x1, x2, [sp], #16
+ ldp x3, x4, [sp], #16
+ ldp x5, x6, [sp], #16
+ ldp x7, x8, [sp], #16
+ ldp x9, x10, [sp], #16
+ ldp x11, x12, [sp], #16
+ ldp x13, x14, [sp], #16
+ ldp x15, x16, [sp], #16
+ ldp x17, x18, [sp], #16
+ ldp x19, x20, [sp], #16
+ ldp x21, x22, [sp], #16
+ ldp x23, x24, [sp], #16
+ ldp x25, x26, [sp], #16
+ ldp x27, x28, [sp], #16
+ ldp x29, x30, [sp], #16
+.endm
+
+#ifdef __APPLE__
+#define SEP %%
+#else
+#define SEP ;
+#endif
+
+#define CALL_C(func, msg, first, last, ptr, offset) \
+ call_c func, __LINE__, msg, first, last, ptr, offset SEP \
+ b 778f SEP \
+ 777: \
+ .asciz msg SEP \
+ .align 2 SEP \
+ 778:
+
+#define DUMP_SIMD_S8(msg, first, last) CALL_C(dump_simd_s8, msg, first,
last, sp, 0)
+#define DUMP_SIMD_U8(msg, first, last) CALL_C(dump_simd_u8, msg, first,
last, sp, 0)
+#define DUMP_SIMD_S16(msg, first, last) CALL_C(dump_simd_s16, msg, first,
last, sp, 0)
+#define DUMP_SIMD_U16(msg, first, last) CALL_C(dump_simd_u16, msg, first,
last, sp, 0)
+#define DUMP_SIMD_S32(msg, first, last) CALL_C(dump_simd_s32, msg, first,
last, sp, 0)
+#define DUMP_MEM_S16(msg, reg, n) CALL_C(dump_simd_s16, msg, 0, n-1,
reg, 0)
+#define DUMP_GPR(msg, first, last) CALL_C(dump_gpr, msg, first,
last, sp, 520)
+
+#endif /* CONFIG_ASM_DEBUG */
diff --git a/libavutil/arm/asm.S b/libavutil/arm/asm.S
index e8a9dabbca5..86c9fe395ba 100644
--- a/libavutil/arm/asm.S
+++ b/libavutil/arm/asm.S
@@ -365,3 +365,50 @@ ELF .eabi_attribute 28, 1
#define GLUE(a, b) a ## b
#define JOIN(a, b) GLUE(a, b)
#define X(s) JOIN(EXTERN_ASM, s)
+
+
+#if CONFIG_ASM_DEBUG
+.macro call_c func, line, msg, first, last, ptr, offset
+ push {lr}
+ mov lr, sp
+ push {lr}
+ push {r0-r12}
+ mrs lr, cpsr
+ push {lr}
+ vpush {d16-d31}
+ vpush {d0-d15}
+ add r0, \ptr, #\offset
+ push {r0}
+ ldr r0, =\line
+ adr r1, 777f
+ mov r2, \first
+ mov r3, \last
+ bl X(ff_\func)
+ pop {r0}
+ vpop {d0-d15}
+ vpop {d16-d31}
+ pop {lr}
+ msr cpsr, lr
+ pop {r0-r12}
+ add sp, sp, #4
+ pop {lr}
+.endm
+
+#define CALL_C(func, msg, first, last, ptr, offset) \
+ call_c func, __LINE__, msg, first, last, ptr, offset; \
+ b 778f; \
+ 777: \
+ .asciz msg; \
+ .align 2; \
+ .ltorg; \
+ 778:
+
+#define DUMP_SIMD_S8(msg, first, last) CALL_C(dump_simd_s8, msg, first,
last, sp, 0)
+#define DUMP_SIMD_U8(msg, first, last) CALL_C(dump_simd_u8, msg, first,
last, sp, 0)
+#define DUMP_SIMD_S16(msg, first, last) CALL_C(dump_simd_s16, msg, first,
last, sp, 0)
+#define DUMP_SIMD_U16(msg, first, last) CALL_C(dump_simd_u16, msg, first,
last, sp, 0)
+#define DUMP_SIMD_S32(msg, first, last) CALL_C(dump_simd_s32, msg, first,
last, sp, 0)
+#define DUMP_MEM_S16(msg, reg, n) CALL_C(dump_simd_s16, msg, 0, n-1,
reg, 0)
+#define DUMP_GPR(msg, first, last) CALL_C(dump_gpr, msg, first,
last, sp, 260)
+
+#endif /* CONFIG_ASM_DEBUG */
diff --git a/libavutil/arm_asm_debug.c b/libavutil/arm_asm_debug.c
new file mode 100644
index 00000000000..5c1c90fc2c5
--- /dev/null
+++ b/libavutil/arm_asm_debug.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright © 2019-2026, Martin Storsjo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <inttypes.h>
+
+void ff_dump_simd_s8(int line, const char *msg, int first, int last, const
int8_t *ptr);
+void ff_dump_simd_s8(int line, const char *msg, int first, int last, const
int8_t *ptr) {
+ fprintf(stderr, "%d: %s:\n", line, msg);
+#if ARCH_AARCH64
+ for (int v = first; v <= last; v++) {
+ const int8_t *vec = &ptr[16*v];
+ fprintf(stderr, "v%02d.16b = {", v);
+ for (int i = 0; i < 16; i++)
+ fprintf(stderr, "%s %d", i > 0 ? "," : "", vec[i]);
+ fprintf(stderr, " }\n");
+ }
+#elif ARCH_ARM
+ for (int v = first; v <= last; v++) {
+ const int8_t *vec = &ptr[8*v];
+ fprintf(stderr, "d%02d = {", v);
+ for (int i = 0; i < 8; i++)
+ fprintf(stderr, "%s %d", i > 0 ? "," : "", vec[i]);
+ fprintf(stderr, " }\n");
+ }
+#endif
+ fflush(stderr);
+}
+
+void ff_dump_simd_u8(int line, const char *msg, int first, int last, const
uint8_t *ptr);
+void ff_dump_simd_u8(int line, const char *msg, int first, int last, const
uint8_t *ptr) {
+ fprintf(stderr, "%d: %s:\n", line, msg);
+#if ARCH_AARCH64
+ for (int v = first; v <= last; v++) {
+ const uint8_t *vec = &ptr[16*v];
+ fprintf(stderr, "v%02d.16b = {", v);
+ for (int i = 0; i < 16; i++)
+ fprintf(stderr, "%s %d", i > 0 ? "," : "", vec[i]);
+ fprintf(stderr, " }\n");
+ }
+#elif ARCH_ARM
+ for (int v = first; v <= last; v++) {
+ const uint8_t *vec = &ptr[8*v];
+ fprintf(stderr, "d%02d = {", v);
+ for (int i = 0; i < 8; i++)
+ fprintf(stderr, "%s %d", i > 0 ? "," : "", vec[i]);
+ fprintf(stderr, " }\n");
+ }
+#endif
+ fflush(stderr);
+}
+
+void ff_dump_simd_s16(int line, const char *msg, int first, int last, const
int16_t *ptr);
+void ff_dump_simd_s16(int line, const char *msg, int first, int last, const
int16_t *ptr) {
+ fprintf(stderr, "%d: %s:\n", line, msg);
+#if ARCH_AARCH64
+ for (int v = first; v <= last; v++) {
+ const int16_t *vec = &ptr[8*v];
+ fprintf(stderr, "v%02d.8h = {", v);
+ for (int i = 0; i < 8; i++)
+ fprintf(stderr, "%s %d", i > 0 ? "," : "", vec[i]);
+ fprintf(stderr, " }\n");
+ }
+#elif ARCH_ARM
+ for (int v = first; v <= last; v++) {
+ const int16_t *vec = &ptr[4*v];
+ fprintf(stderr, "d%02d = {", v);
+ for (int i = 0; i < 4; i++)
+ fprintf(stderr, "%s %d", i > 0 ? "," : "", vec[i]);
+ fprintf(stderr, " }\n");
+ }
+#endif
+ fflush(stderr);
+}
+
+void ff_dump_simd_u16(int line, const char *msg, int first, int last, const
uint16_t *ptr);
+void ff_dump_simd_u16(int line, const char *msg, int first, int last, const
uint16_t *ptr) {
+ fprintf(stderr, "%d: %s:\n", line, msg);
+#if ARCH_AARCH64
+ for (int v = first; v <= last; v++) {
+ const uint16_t *vec = &ptr[8*v];
+ fprintf(stderr, "v%02d.8h = {", v);
+ for (int i = 0; i < 8; i++)
+ fprintf(stderr, "%s %d", i > 0 ? "," : "", vec[i]);
+ fprintf(stderr, " }\n");
+ }
+#elif ARCH_ARM
+ for (int v = first; v <= last; v++) {
+ const uint16_t *vec = &ptr[4*v];
+ fprintf(stderr, "d%02d = {", v);
+ for (int i = 0; i < 4; i++)
+ fprintf(stderr, "%s %d", i > 0 ? "," : "", vec[i]);
+ fprintf(stderr, " }\n");
+ }
+#endif
+ fflush(stderr);
+}
+
+void ff_dump_simd_s32(int line, const char *msg, int first, int last, const
int32_t *ptr);
+void ff_dump_simd_s32(int line, const char *msg, int first, int last, const
int32_t *ptr) {
+ fprintf(stderr, "%d: %s:\n", line, msg);
+#if ARCH_AARCH64
+ for (int v = first; v <= last; v++) {
+ const int32_t *vec = &ptr[4*v];
+ fprintf(stderr, "v%02d.4s = {", v);
+ for (int i = 0; i < 4; i++)
+ fprintf(stderr, "%s %d", i > 0 ? "," : "", vec[i]);
+ fprintf(stderr, " }\n");
+ }
+#elif ARCH_ARM
+ for (int v = first; v <= last; v++) {
+ const int32_t *vec = &ptr[2*v];
+ fprintf(stderr, "d%02d = {", v);
+ for (int i = 0; i < 2; i++)
+ fprintf(stderr, "%s %d", i > 0 ? "," : "", vec[i]);
+ fprintf(stderr, " }\n");
+ }
+#endif
+ fflush(stderr);
+}
+
+void ff_dump_gpr(int line, const char *msg, int first, int last, const size_t
*ptr);
+void ff_dump_gpr(int line, const char *msg, int first, int last, const size_t
*ptr) {
+ fprintf(stderr, "%d: %s:\n", line, msg);
+#if ARCH_AARCH64
+ for (int r = first; r <= last; r++)
+ fprintf(stderr, "x%02d = %"PRId64" (0x%"PRIx64")\n", r, (int64_t)
ptr[r], (uint64_t) ptr[r]);
+#elif ARCH_ARM
+ for (int r = first; r <= last; r++)
+ if (r < 13)
+ fprintf(stderr, "r%02d = %"PRId32" (0x%"PRIx32")\n", r, (int32_t)
ptr[r], (uint32_t) ptr[r]);
+ else
+ fprintf(stderr, "%s = %"PRId32" (0x%"PRIx32")\n", r == 13 ? "sp"
: "lr", (int32_t) ptr[r], (uint32_t) ptr[r]);
+#endif
+ fflush(stderr);
+}
--
2.54.0
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]