]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb/record: add support for AVX floating point arithmetic instructions
authorGuinevere Larsen <guinevere@redhat.com>
Thu, 9 Jan 2025 12:47:22 +0000 (09:47 -0300)
committerGuinevere Larsen <guinevere@redhat.com>
Tue, 14 Jan 2025 17:47:56 +0000 (14:47 -0300)
This commit adds support for the following types of instructions
relating to floating poitn values: add, mul, sub, min, div, max.
These are supported with packed or single values, and single or double
precision.

Some of the instructions had opcode clashes, however, considering the
mechanics of recording the registers is the same on both instructions,
this is just marked with a comment.

Approved-By: Guinevere Larsen <guinevere@redhat.com>
gdb/i386-tdep.c
gdb/testsuite/gdb.reverse/i386-avx-reverse.c
gdb/testsuite/gdb.reverse/i386-avx-reverse.exp

index 44123979186a49d9a9654e2aea5af4a933759544..5f585b2ca7ec357e0332cfc48c91892898fd700d 100644 (file)
@@ -5003,9 +5003,15 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
 
     case 0x78: /* VPBROADCASTB  */
     case 0x79: /* VPBROADCASTW  */
-    case 0x58: /* VPBROADCASTD  */
-    case 0x59: /* VPBROADCASTQ  */
+    case 0x58: /* VPBROADCASTD and VADD[P|S][S|D]  */
+    case 0x59: /* VPBROADCASTQ and VMUL[P|S][S|D]  */
+    case 0x5c: /* VSUB[P|S][S|D]  */
+    case 0x5d: /* VMIN[P|S][S|D]  */
+    case 0x5e: /* VDIV[P|S][S|D]  */
+    case 0x5f: /* VMAX[P|S][S|D]  */
       {
+       /* vpbroadcast and arithmethic operations are differentiated
+          by map_select, but it doesn't change the recording mechanics.  */
        i386_record_modrm (ir);
        int reg_offset = ir->reg + vex_r * 8;
        gdb_assert (tdep->num_ymm_regs > reg_offset);
index f41c7ff2933e0959cfca0fa01503902835e30dd9..0c26bcd8e85962b92cdb39da0a7224cab08ddf47 100644 (file)
@@ -364,6 +364,61 @@ vpmovmskb_test ()
   return 0; /* end vpmovmskb_test  */
 }
 
+/* Test record arithmetic instructions.  */
+int
+arith_test ()
+{
+  /* start arith_test.  */
+  /* Using GDB, load these values onto registers for testing.
+     ymm0.v8_float = {0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5}
+     ymm1.v8_float = {0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5}
+     ymm15.v2_int128 = {0x0, 0x0}
+     this way it's easy to confirm we're undoing things correctly.  */
+  asm volatile ("vaddps %xmm0, %xmm1, %xmm15");
+  asm volatile ("vaddps %ymm0, %ymm1, %ymm15");
+  asm volatile ("vaddpd %xmm0, %xmm1, %xmm15");
+  asm volatile ("vaddpd %ymm0, %ymm1, %ymm15");
+  asm volatile ("vaddss %xmm0, %xmm1, %xmm15");
+  asm volatile ("vaddsd %xmm0, %xmm1, %xmm15");
+
+  asm volatile ("vmulps %xmm0, %xmm1, %xmm15");
+  asm volatile ("vmulps %ymm0, %ymm1, %ymm15");
+  asm volatile ("vmulpd %xmm0, %xmm1, %xmm15");
+  asm volatile ("vmulpd %ymm0, %ymm1, %ymm15");
+  asm volatile ("vmulss %xmm0, %xmm1, %xmm15");
+  asm volatile ("vmulsd %xmm0, %xmm1, %xmm15");
+
+  asm volatile ("vsubps %xmm0, %xmm1, %xmm15");
+  asm volatile ("vsubps %ymm0, %ymm1, %ymm15");
+  asm volatile ("vsubpd %xmm0, %xmm1, %xmm15");
+  asm volatile ("vsubpd %ymm0, %ymm1, %ymm15");
+  asm volatile ("vsubss %xmm0, %xmm1, %xmm15");
+  asm volatile ("vsubsd %xmm0, %xmm1, %xmm15");
+
+  asm volatile ("vdivps %xmm0, %xmm1, %xmm15");
+  asm volatile ("vdivps %ymm0, %ymm1, %ymm15");
+  asm volatile ("vdivpd %xmm0, %xmm1, %xmm15");
+  asm volatile ("vdivpd %ymm0, %ymm1, %ymm15");
+  asm volatile ("vdivss %xmm0, %xmm1, %xmm15");
+  asm volatile ("vdivsd %xmm0, %xmm1, %xmm15");
+
+  asm volatile ("vminps %xmm0, %xmm1, %xmm15");
+  asm volatile ("vminps %ymm0, %ymm1, %ymm15");
+  asm volatile ("vminpd %xmm0, %xmm1, %xmm15");
+  asm volatile ("vminpd %ymm0, %ymm1, %ymm15");
+  asm volatile ("vminss %xmm0, %xmm1, %xmm15");
+  asm volatile ("vminsd %xmm0, %xmm1, %xmm15");
+
+  asm volatile ("vmaxps %xmm0, %xmm1, %xmm15");
+  asm volatile ("vmaxps %ymm0, %ymm1, %ymm15");
+  asm volatile ("vmaxpd %xmm0, %xmm1, %xmm15");
+  asm volatile ("vmaxpd %ymm0, %ymm1, %ymm15");
+  asm volatile ("vmaxss %xmm0, %xmm1, %xmm15");
+  asm volatile ("vmaxsd %xmm0, %xmm1, %xmm15");
+
+  return 0; /* end arith_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.  */
@@ -392,5 +447,6 @@ main ()
   vpor_xor_test ();
   vpcmpeq_test ();
   vpmovmskb_test ();
+  arith_test ();
   return 0;    /* end of main */
 }
index e3d1bbb3faa737105a3d78a799fe1a466bb4b8f1..11532afe344b8eee05f9373e135aa0bd2f4a0a34 100644 (file)
@@ -517,3 +517,108 @@ if {[record_full_function "vpmovmskb"] == true} {
 }
 gdb_test "finish" "Run till exit from.*vpmovmskb_test.*" \
     "leaving vpmovmskb"
+
+# Preparation and testing arithmetic instructions.
+gdb_test_no_output \
+    "set \$ymm0.v8_float = {0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5}"
+gdb_test_no_output \
+    "set \$ymm1.v8_float = {0, 1, 2, 3, 4, 5, 6, 7}"
+gdb_test_no_output "set \$ymm15.v2_int128 = {0,0}"
+
+if {[record_full_function "arith"] == true} {
+    test_one_register "vmaxsd" "ymm15" \
+       "0x40400000400000003f8000003f000000, 0x0" "ymm operation: "
+    test_one_register "vmaxss" "ymm15" \
+       "0x40600000402000003fc000003f000000, 0x40f0000040d0000040b0000040900000" \
+       "xmm operation: "
+    test_one_register "vmaxpd" "ymm15" \
+       "0x40600000402000003fc000003f000000, 0x0" "ymm operation: "
+    test_one_register "vmaxpd" "ymm15" \
+       "0x40600000402000003fc000003f000000, 0x40f0000040d0000040b0000040900000" \
+       "xmm operation: "
+    test_one_register "vmaxps" "ymm15" \
+       "0x40600000402000003fc000003f000000, 0x0" "ymm operation: "
+    test_one_register "vmaxps" "ymm15" \
+       "0x40400000400000003f80000000000000, 0x0" "xmm operation: "
+
+    test_one_register "vminsd" "ymm15" \
+       "0x40400000400000003f80000000000000, 0x0" "ymm operation: "
+    test_one_register "vminss" "ymm15" \
+       "0x40400000400000003f80000000000000, 0x40e0000040c0000040a0000040800000" \
+       "xmm operation: "
+    test_one_register "vminpd" "ymm15" \
+       "0x40400000400000003f80000000000000, 0x0" "ymm operation: "
+    test_one_register "vminpd" "ymm15" \
+       "0x40400000400000003f80000000000000, 0x40e0000040c0000040a0000040800000" \
+       "xmm operation: "
+    test_one_register "vminps" "ymm15" \
+       "0x40400000400000003f80000000000000, 0x0" "ymm operation: "
+    test_one_register "vminps" "ymm15" \
+       "0x40400000400000003fafffff820001f0, 0x0" "xmm operation: "
+
+    test_one_register "vdivsd" "ymm15" \
+       "0x40400000400000003f80000000000000, 0x0" "ymm operation: "
+    test_one_register "vdivss" "ymm15" \
+       "0x3fcfffffffc000013fafffff820001f0, 0x3fdfffffffe000013fdfffffffe00001" \
+       "xmm operation: "
+    test_one_register "vdivpd" "ymm15" \
+       "0x3fcfffffffc000013fafffff820001f0, 0x0" "ymm operation: "
+    test_one_register "vdivpd" "ymm15" \
+       "0x3f5b6db73f4ccccd3f2aaaab00000000, 0x3f6eeeef3f6c4ec53f68ba2f3f638e39" \
+       "xmm operation: "
+    test_one_register "vdivps" "ymm15" \
+       "0x3f5b6db73f4ccccd3f2aaaab00000000, 0x0" "ymm operation: "
+    test_one_register "vdivps" "ymm15" \
+       "0x4040000040000000bfbe00007e000000, 0x0" "xmm operation: "
+
+    test_one_register "vsubsd" "ymm15" \
+       "0x40400000400000003f800000bf000000, 0x0" "ymm operation: "
+    test_one_register "vsubss" "ymm15" \
+       "0xc058000060400000bfbe00007e000000, 0xc0e0000040e00000c0a0000040a00000" \
+       "xmm operation: "
+    test_one_register "vsubpd" "ymm15" \
+       "0xc058000060400000bfbe00007e000000, 0x0" "ymm operation: "
+    test_one_register "vsubpd" "ymm15" \
+       "0xbf000000bf000000bf000000bf000000, 0xbf000000bf000000bf000000bf000000" \
+       "xmm operation: "
+    test_one_register "vsubps" "ymm15" \
+       "0xbf000000bf000000bf000000bf000000, 0x0" "ymm operation: "
+    test_one_register "vsubps" "ymm15" \
+       "0x40400000400000003f5000003f000000, 0x0" "xmm operation: "
+
+    test_one_register "vmulsd" "ymm15" \
+       "0x40400000400000003f80000000000000, 0x0" "ymm operation: "
+    test_one_register "vmulss" "ymm15" \
+       "0x40b00000802001003f5000003f000000, 0x41e00000819001064160000081100104" \
+       "xmm operation: "
+    test_one_register "vmulpd" "ymm15" \
+       "0x40b00000802001003f5000003f000000, 0x0" "ymm operation: "
+    test_one_register "vmulpd" "ymm15" \
+       "0x4128000040a000003fc0000000000000, 0x42520000421c000041dc000041900000" \
+       "xmm operation: "
+    test_one_register "vmulps" "ymm15" \
+       "0x4128000040a000003fc0000000000000, 0x0" "ymm operation: "
+    test_one_register "vmulps" "ymm15" \
+       "0x40400000400000003fc100003f000000, 0x0" "xmm operation: "
+
+    test_one_register "vaddsd" "ymm15" \
+       "0x40400000400000003f8000003f000000, 0x0" "ymm operation: "
+    test_one_register "vaddss" "ymm15" \
+       "0x40640000502000003fc100003f000000, 0x40f800006130000040b8000060d00000" \
+       "xmm operation: "
+    test_one_register "vaddpd" "ymm15" \
+       "0x40640000502000003fc100003f000000, 0x0" "ymm operation: "
+    test_one_register "vaddpd" "ymm15" \
+       "0x40d0000040900000402000003f000000, 0x41680000414800004128000041080000" \
+       "xmm operation: "
+    test_one_register "vaddps" "ymm15" \
+       "0x40d0000040900000402000003f000000, 0x0" "ymm operation: "
+    test_one_register "vaddps" "ymm15" "0x0, 0x0" "xmm operation: "
+
+    gdb_test "record stop" "Process record is stopped.*" \
+       "delete history for arith_test"
+} else {
+    untested "couldn't run arith tests"
+}
+gdb_test "finish" "Run till exit from.*arith_test.*" \
+    "leaving arith"