From d83364eb1d8cb443dd94dbf5cb2aa4f32ceedcf9 Mon Sep 17 00:00:00 2001 From: Guinevere Larsen Date: Mon, 9 Jun 2025 17:25:00 -0300 Subject: [PATCH] gdb/record: add support for AVX/AVX2 shuffle instructions This commit adds support for the following instructions: * VPSHUF[B|D|HW|LW] * VSHUFP[S|D] and the associated test. --- gdb/i386-tdep.c | 3 ++ gdb/testsuite/gdb.reverse/i386-avx-reverse.c | 30 +++++++++++ .../gdb.reverse/i386-avx-reverse.exp | 54 +++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 4e442d28813..e8e2d6e734b 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -5030,6 +5030,7 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r, break; } + case 0x00: /* VSHUFB. */ case 0x40: /* VPMULLD */ case 0x57: /* VXORP[S|D] */ case 0x58: /* VPBROADCASTD and VADD[P|S][S|D] */ @@ -5038,8 +5039,10 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r, case 0x5d: /* VMIN[P|S][S|D] */ case 0x5e: /* VDIV[P|S][S|D] */ case 0x5f: /* VMAX[P|S][S|D] */ + case 0x70: /* VPSHUF[B|D|HW|LW]. */ case 0x78: /* VPBROADCASTB */ case 0x79: /* VPBROADCASTW */ + case 0xc6: /* VSHUFP[S|D]. */ case 0xd1: /* VPSRLW, dynamic shift. */ case 0xd2: /* VPSRLD, dynamic shift. */ case 0xd3: /* VPSRLQ, dynamic shift. */ diff --git a/gdb/testsuite/gdb.reverse/i386-avx-reverse.c b/gdb/testsuite/gdb.reverse/i386-avx-reverse.c index 6ce8ff861bf..d438a335e91 100644 --- a/gdb/testsuite/gdb.reverse/i386-avx-reverse.c +++ b/gdb/testsuite/gdb.reverse/i386-avx-reverse.c @@ -514,6 +514,35 @@ shift_test () return 0; /* end shift_test */ } +int +shuffle_test () +{ + /* start shuffle_test. */ + /* Using GDB, load these values onto registers for testing. + ymm0.v2_int128 = {0, 0} + ymm1.v16_int16 = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16} + ymm2.v16_int15 = {17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32} + ymm15.v2_int128 = {0x0, 0x0} + this way it's easy to confirm we're undoing things correctly. */ + + asm volatile ("vpshufb %xmm1, %xmm2, %xmm0"); + asm volatile ("vpshufb %ymm1, %ymm2, %ymm15"); + asm volatile ("vpshufd $1, %ymm2, %ymm0"); + asm volatile ("vpshufd $2, %xmm2, %xmm15"); + + asm volatile ("vpshufhw $3, %xmm2, %xmm0"); + asm volatile ("vpshufhw $4, %ymm2, %ymm15"); + asm volatile ("vpshuflw $5, %ymm2, %ymm0"); + asm volatile ("vpshuflw $6, %xmm2, %xmm15"); + + asm volatile ("vshufps $1, %xmm1, %xmm2, %xmm0"); + asm volatile ("vshufps $2, %ymm1, %ymm2, %ymm15"); + asm volatile ("vshufpd $4, %ymm1, %ymm2, %ymm0"); + asm volatile ("vshufpd $8, %xmm1, %xmm2, %xmm15"); + + return 0; /* end shuffle_test */ +} + /* This include is used to allocate the dynamic buffer and have the pointers aligned to a 32-bit boundary, so we can test instructions that require aligned memory. */ @@ -547,5 +576,6 @@ main () vaddsubpd_test (); vaddsubps_test (); shift_test (); + shuffle_test (); return 0; /* end of main */ } diff --git a/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp b/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp index ecd9fa6f4db..4bcafe7c331 100644 --- a/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp +++ b/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp @@ -817,3 +817,57 @@ if {[record_full_function "shift"] == true} { } gdb_test "finish" "Run till exit from.*shift_test.*" \ "leaving shift" + +# Preparation and testing shuffling instructions. +gdb_test_no_output \ + "set \$ymm0.v2_int128 = {0, 0}" "set ymm0 for shuffle" +gdb_test_no_output \ + "set \$ymm1.v16_int16 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}" \ + "set ymm1 for shuffle" +gdb_test_no_output "set \$ymm2.v16_int16 = {17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}" \ + "set ymm2 for shuffle" +gdb_test_no_output "set \$ymm15.v2_int128 = {0,0}" "set ymm15 for shuffle" + +if {[record_full_function "shuffle"] == true} { + test_one_register "vshufpd" "ymm15" \ + "0x20001000200010012001100160015, 0xa0009000a0009001a0019001e001d" \ + "high register: " + test_one_register "vshufpd" "ymm0" \ + "0x20001000200010012001100140013, 0x0" \ + "low register: " + test_one_register "vshufps" "ymm15" \ + "0x180017001600150011001100120013, 0x0" \ + "high register: " + test_one_register "vshufps" "ymm0" \ + "0x180017001600150011001100120012, 0x20001f001e001d00190019001a001a" \ + "low register: " + + test_one_register "vpshuflw" "ymm15" \ + "0x150015001600150014001300120011, 0x1d001d001e001d001c001b001a0019" \ + "high register: " + test_one_register "vpshuflw" "ymm0" \ + "0x150015001500180014001300120011, 0x0" \ + "low register: " + test_one_register "vpshufhw" "ymm15" \ + "0x120011001200110012001100160015, 0x0" \ + "high register: " + test_one_register "vpshufhw" "ymm0" \ + "0x120011001200110012001100140013, 0x1a0019001a0019001a0019001c001b" \ + "low register: " + + test_one_register "vpshufd" "ymm15" \ + "0x11151100111411001113110011121100, 0x1919190019201900191f1900191e1900" \ + "high register: " + test_one_register "vpshufd" "ymm0" \ + "0x11151100111411001113110011121100, 0x0" \ + "low register: " + test_one_register "vpshufb" "ymm15" "0x0, 0x0" "high register: " + test_one_register "vpshufb" "ymm0" "0x0, 0x0" "low register: " + + gdb_test "record stop" "Process record is stopped.*" \ + "delete history for shuffle_test" +} else { + untested "couldn't run shuffle tests" +} +gdb_test "finish" "Run till exit from.*shuffle_test.*" \ + "leaving shuffle" -- 2.47.2