[Lldb-commits] [lldb] 381bdc7 - [lldb] [test/Register] Add read/write tests for x87 regs

Michał Górny via lldb-commits lldb-commits at lists.llvm.org
Sat Oct 3 10:54:54 PDT 2020


Author: Michał Górny
Date: 2020-10-03T19:54:38+02:00
New Revision: 381bdc75ee2ca2fb9784ffb2f6b90accd8eab3b6

URL: https://github.com/llvm/llvm-project/commit/381bdc75ee2ca2fb9784ffb2f6b90accd8eab3b6
DIFF: https://github.com/llvm/llvm-project/commit/381bdc75ee2ca2fb9784ffb2f6b90accd8eab3b6.diff

LOG: [lldb] [test/Register] Add read/write tests for x87 regs

Add a partial read/write tests for x87 FPU registers.  This includes
reading and writing ST registers, control registers and floating-point
exception data registers (fop, fip, fdp).

The tests assume the current (roughly incorrect) behavior of reporting
the 'abridged' 8-bit ftag state as 16-bit ftag.  They also assume Linux
plugin behavior of reporting fip/fdp split into halves as (fiseg, fioff)
and (foseg, fooff).

Differential Revision: https://reviews.llvm.org/D88583

Added: 
    lldb/test/Shell/Register/Inputs/x86-fp-read.cpp
    lldb/test/Shell/Register/Inputs/x86-fp-write.cpp
    lldb/test/Shell/Register/x86-64-fp-write.test
    lldb/test/Shell/Register/x86-fp-read.test
    lldb/test/Shell/Register/x86-fp-write.test

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/lldb/test/Shell/Register/Inputs/x86-fp-read.cpp b/lldb/test/Shell/Register/Inputs/x86-fp-read.cpp
new file mode 100644
index 000000000000..1bd2d60affa2
--- /dev/null
+++ b/lldb/test/Shell/Register/Inputs/x86-fp-read.cpp
@@ -0,0 +1,45 @@
+#include <cstdint>
+
+struct alignas(16) float80_raw {
+  uint64_t mantissa;
+  uint16_t sign_exp;
+};
+
+int main() {
+  float80_raw st[] = {
+    {0x8000000000000000, 0x4000},  // +2.0
+    {0x3f00000000000000, 0x0000},  // 1.654785e-4932 (denormal)
+    {0x0000000000000000, 0x0000},  // +0
+    {0x0000000000000000, 0x8000},  // -0
+    {0x8000000000000000, 0x7fff},  // +inf
+    {0x8000000000000000, 0xffff},  // -inf
+    {0xc000000000000000, 0xffff},  // nan
+    // leave st7 empty to test tag word better
+  };
+
+  // unmask divide-by-zero exception
+  uint16_t cw = 0x037b;
+  // used as single-precision float
+  uint32_t zero = 0;
+
+  asm volatile(
+    "finit\n\t"
+    "fldcw %1\n\t"
+    // load on stack in reverse order to make the result easier to read
+    "fldt 0x60(%0)\n\t"
+    "fldt 0x50(%0)\n\t"
+    "fldt 0x40(%0)\n\t"
+    "fldt 0x30(%0)\n\t"
+    "fldt 0x20(%0)\n\t"
+    "fldt 0x10(%0)\n\t"
+    "fldt 0x00(%0)\n\t"
+    // this should trigger a divide-by-zero
+    "fdivs (%2)\n\t"
+    "int3\n\t"
+    :
+    : "a"(st), "m"(cw), "b"(&zero)
+    : "st"
+  );
+
+  return 0;
+}

diff  --git a/lldb/test/Shell/Register/Inputs/x86-fp-write.cpp b/lldb/test/Shell/Register/Inputs/x86-fp-write.cpp
new file mode 100644
index 000000000000..63791a8eff2e
--- /dev/null
+++ b/lldb/test/Shell/Register/Inputs/x86-fp-write.cpp
@@ -0,0 +1,69 @@
+#include <cassert>
+#include <cinttypes>
+#include <cstdint>
+#include <cstdio>
+
+struct alignas(16) float80_raw {
+  uint8_t data[10];
+};
+
+int main() {
+  float80_raw st[8];
+  uint16_t env[14];
+  union alignas(16) {
+    uint16_t i16[256];
+    uint32_t i32[128];
+    uint64_t i64[64];
+  } fxsave;
+
+  asm volatile(
+    "finit\n\t"
+    "int3\n\t"
+#if defined(__x86_64__)
+    "fxsave64 %2\n\t"
+#else
+    "fxsave %2\n\t"
+#endif
+    "fnstenv %1\n\t"
+    "fnclex\n\t"
+    "fstpt 0x00(%0)\n\t"
+    "fstpt 0x10(%0)\n\t"
+    "fstpt 0x20(%0)\n\t"
+    "fstpt 0x30(%0)\n\t"
+    "fstpt 0x40(%0)\n\t"
+    "fstpt 0x50(%0)\n\t"
+    "fstpt 0x60(%0)\n\t"
+    "fstpt 0x70(%0)\n\t"
+    :
+    : "a"(st), "m"(env), "m"(fxsave)
+    : "st"
+  );
+
+  assert(env[0] == fxsave.i16[0]);
+  assert(env[2] == fxsave.i16[1]);
+
+  printf("fctrl = 0x%04" PRIx16 "\n", env[0]);
+  printf("fstat = 0x%04" PRIx16 "\n", env[2]);
+  printf("ftag = 0x%04" PRIx16 "\n", env[4]);
+  printf("fop = 0x%04" PRIx16 "\n", fxsave.i16[3]);
+#if defined(__x86_64__)
+  printf("fip = 0x%016" PRIx64 "\n", fxsave.i64[1]);
+  printf("fdp = 0x%016" PRIx64 "\n", fxsave.i64[2]);
+#else
+  printf("fip = 0x%08" PRIx32 "\n", fxsave.i32[2]);
+  printf("fcs = 0x%04" PRIx16 "\n", fxsave.i16[6]);
+  printf("fdp = 0x%08" PRIx32 "\n", fxsave.i32[4]);
+  printf("fds = 0x%04" PRIx16 "\n", fxsave.i16[10]);
+#endif
+  printf("mxcsr = 0x%08" PRIx32 "\n", fxsave.i32[6]);
+  printf("mxcsr_mask = 0x%08" PRIx32 "\n", fxsave.i32[7]);
+
+  for (int i = 0; i < 8; ++i) {
+    printf("st%d = { ", i);
+    for (int j = 0; j < sizeof(st->data); ++j)
+      printf("0x%02" PRIx8 " ", st[i].data[j]);
+    printf("}\n");
+  }
+
+  return 0;
+}

diff  --git a/lldb/test/Shell/Register/x86-64-fp-write.test b/lldb/test/Shell/Register/x86-64-fp-write.test
new file mode 100644
index 000000000000..b2e8c271b51b
--- /dev/null
+++ b/lldb/test/Shell/Register/x86-64-fp-write.test
@@ -0,0 +1,48 @@
+# REQUIRES: native && target-x86_64
+# RUN: %clangxx_host %p/Inputs/x86-fp-write.cpp -o %t
+# RUN: %lldb -b -s %s %t | FileCheck %s
+process launch
+
+register write fctrl 0x037b
+register write fstat 0x8884
+# note: this needs to enable all registers for writes to be effective
+# TODO: fix it to use proper ftag values instead of 'abridged'
+register write ftag 0x00ff
+register write fop 0x0033
+# the exact addresses do not matter, we want just to verify FXSAVE
+# note: fxrstor64 apparently truncates this to 48 bits, and sign extends
+#       the highest bits, so let's keep the value safely below
+register write fiseg 0x00000567
+register write fioff 0x89abcdef
+register write foseg 0x00000a98
+register write fooff 0x76543210
+
+register write st0 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x00 0x40}"
+register write st1 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x3f 0x00 0x00}"
+register write st2 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
+register write st3 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80}"
+register write st4 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0x7f}"
+register write st5 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0xff}"
+register write st6 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xc0 0xff 0xff}"
+register write st7 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
+
+process continue
+
+# CHECK: process continue
+# CHECK-DAG: fctrl = 0x037b
+# CHECK-DAG: fstat = 0x8884
+# CHECK-DAG: ftag = 0xa961
+# CHECK-DAG: fop = 0x0033
+# CHECK-DAG: fip = 0x0000056789abcdef
+# CHECK-DAG: fdp = 0x00000a9876543210
+
+# CHECK-DAG: st0 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x00 0x40 }
+# CHECK-DAG: st1 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x3f 0x00 0x00 }
+# CHECK-DAG: st2 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 }
+# CHECK-DAG: st3 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 }
+# CHECK-DAG: st4 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0x7f }
+# CHECK-DAG: st5 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0xff }
+# CHECK-DAG: st6 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xc0 0xff 0xff }
+# CHECK-DAG: st7 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 }
+
+# CHECK: Process {{[0-9]+}} exited with status = 0

diff  --git a/lldb/test/Shell/Register/x86-fp-read.test b/lldb/test/Shell/Register/x86-fp-read.test
new file mode 100644
index 000000000000..9ecc5634e729
--- /dev/null
+++ b/lldb/test/Shell/Register/x86-fp-read.test
@@ -0,0 +1,36 @@
+# REQUIRES: native && (target-x86 || target-x86_64)
+# RUN: %clangxx_host -g %p/Inputs/x86-fp-read.cpp -o %t
+# RUN: %lldb -b -s %s %t | FileCheck %s
+process launch
+# CHECK: Process {{.*}} stopped
+
+register read --all
+# CHECK-DAG: fctrl = 0x037b
+# CHECK-DAG: fstat = 0x8884
+# TODO: the following value is incorrect, it's a bug in the way
+# FXSAVE/XSAVE is interpreted; it should be 0xa963 once fixed
+# CHECK-DAG: ftag = 0x00fe
+# CHECK-DAG: fop = 0x0033
+
+# CHECK-DAG: st0 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x00 0x40}
+# CHECK-DAG: st1 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x3f 0x00 0x00}
+# CHECK-DAG: st2 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
+# CHECK-DAG: st3 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80}
+# CHECK-DAG: st4 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0x7f}
+# CHECK-DAG: st5 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0xff}
+# CHECK-DAG: st6 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xc0 0xff 0xff}
+# CHECK-DAG: st7 = {0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}
+
+# fdiv (%rbx) gets encoded into 2 bytes, int3 into 1 byte
+print (void*)($pc-3)
+# CHECK: (void *) $0 = [[FDIV:0x[0-9a-f]*]]
+# TODO: we probably should not split it like this
+print (void*)($fiseg*0x100000000 + $fioff)
+# CHECK: (void *) $1 = [[FDIV]]
+print &zero
+# CHECK: (uint32_t *) $2 = [[ZERO:0x[0-9a-f]*]]
+print (uint32_t*)($foseg * 0x100000000 + $fooff)
+# CHECK: (uint32_t *) $3 = [[ZERO]]
+
+process continue
+# CHECK: Process {{[0-9]+}} exited with status = 0

diff  --git a/lldb/test/Shell/Register/x86-fp-write.test b/lldb/test/Shell/Register/x86-fp-write.test
new file mode 100644
index 000000000000..81f542c419af
--- /dev/null
+++ b/lldb/test/Shell/Register/x86-fp-write.test
@@ -0,0 +1,45 @@
+# REQUIRES: native && target-x86
+# RUN: %clangxx_host %p/Inputs/x86-fp-write.cpp -o %t
+# RUN: %lldb -b -s %s %t | FileCheck %s
+process launch
+
+register write fctrl 0x037b
+register write fstat 0x8884
+# note: this needs to enable all registers for writes to be effective
+# TODO: fix it to use proper ftag values instead of 'abridged'
+register write ftag 0x00ff
+register write fop 0x0033
+# the exact addresses do not matter, we want just to verify FXSAVE
+# note: segment registers are not supported on all CPUs
+register write fioff 0x89abcdef
+register write fooff 0x76543210
+
+register write st0 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x00 0x40}"
+register write st1 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x3f 0x00 0x00}"
+register write st2 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
+register write st3 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80}"
+register write st4 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0x7f}"
+register write st5 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0xff}"
+register write st6 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xc0 0xff 0xff}"
+register write st7 "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}"
+
+process continue
+
+# CHECK: process continue
+# CHECK-DAG: fctrl = 0x037b
+# CHECK-DAG: fstat = 0x8884
+# CHECK-DAG: ftag = 0xa961
+# CHECK-DAG: fop = 0x0033
+# CHECK-DAG: fip = 0x89abcdef
+# CHECK-DAG: fdp = 0x76543210
+
+# CHECK-DAG: st0 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x00 0x40 }
+# CHECK-DAG: st1 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x3f 0x00 0x00 }
+# CHECK-DAG: st2 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 }
+# CHECK-DAG: st3 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 }
+# CHECK-DAG: st4 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0x7f }
+# CHECK-DAG: st5 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0xff 0xff }
+# CHECK-DAG: st6 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xc0 0xff 0xff }
+# CHECK-DAG: st7 = { 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 }
+
+# CHECK: Process {{[0-9]+}} exited with status = 0


        


More information about the lldb-commits mailing list