--- /dev/null
+#include <cstdint>
+#include <mutex>
+#include <thread>
+
+std::mutex t1_mutex, t2_mutex;
+
+struct test_data {
+ uint32_t eax;
+ uint32_t ebx;
+
+ struct alignas(16) {
+ uint64_t mantissa;
+ uint16_t sign_exp;
+ } st0;
+};
+
+void t_func(std::mutex &t_mutex, const test_data &t_data) {
+ std::lock_guard<std::mutex> t_lock(t_mutex);
+
+ asm volatile(
+ "finit\t\n"
+ "fldt %2\t\n"
+ "int3\n\t"
+ :
+ : "a"(t_data.eax), "b"(t_data.ebx), "m"(t_data.st0)
+ : "st"
+ );
+}
+
+int main() {
+ test_data t1_data = {
+ .eax = 0x05060708,
+ .ebx = 0x15161718,
+ .st0 = {0x8070605040302010, 0x4000},
+ };
+ test_data t2_data = {
+ .eax = 0x25262728,
+ .ebx = 0x35363738,
+ .st0 = {0x8171615141312111, 0xc000},
+ };
+
+ // block both threads from proceeding
+ std::unique_lock<std::mutex> m1_lock(t1_mutex);
+ std::unique_lock<std::mutex> m2_lock(t2_mutex);
+
+ // start both threads
+ std::thread t1(t_func, std::ref(t1_mutex), std::ref(t1_data));
+ std::thread t2(t_func, std::ref(t2_mutex), std::ref(t2_data));
+
+ // release lock on thread 1 to make it interrupt the program
+ m1_lock.unlock();
+ // wait for thread 1 to finish
+ t1.join();
+
+ // release lock on thread 2
+ m2_lock.unlock();
+ // wait for thread 2 to finish
+ t2.join();
+
+ return 0;
+}
--- /dev/null
+#include <cinttypes>
+#include <cstdint>
+#include <cstdio>
+#include <mutex>
+#include <thread>
+
+std::mutex t1_mutex, t2_mutex;
+
+struct test_data {
+ uint32_t eax;
+ uint32_t ebx;
+
+ struct alignas(16) {
+ uint8_t data[10];
+ } st0;
+};
+
+constexpr test_data filler = {
+ .eax = 0xffffffff,
+ .ebx = 0xffffffff,
+ .st0 = {{0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f, 0x8f, 0x80, 0x40}},
+};
+
+void t_func(std::mutex &t_mutex) {
+ std::lock_guard<std::mutex> t_lock(t_mutex);
+ test_data out = filler;
+
+ asm volatile(
+ "finit\t\n"
+ "fldt %2\t\n"
+ "int3\n\t"
+ "fstpt %2\t\n"
+ : "+a"(out.eax), "+b"(out.ebx)
+ : "m"(out.st0)
+ : "memory", "st"
+ );
+
+ printf("eax = 0x%08" PRIx32 "\n", out.eax);
+ printf("ebx = 0x%08" PRIx32 "\n", out.ebx);
+ printf("st0 = { ");
+ for (int i = 0; i < sizeof(out.st0.data); ++i)
+ printf("0x%02" PRIx8 " ", out.st0.data[i]);
+ printf("}\n");
+}
+
+int main() {
+ // block both threads from proceeding
+ std::unique_lock<std::mutex> m1_lock(t1_mutex);
+ std::unique_lock<std::mutex> m2_lock(t2_mutex);
+
+ // start both threads
+ std::thread t1(t_func, std::ref(t1_mutex));
+ std::thread t2(t_func, std::ref(t2_mutex));
+
+ // release lock on thread 1 to make it interrupt the program
+ m1_lock.unlock();
+ // wait for thread 1 to finish
+ t1.join();
+
+ // release lock on thread 2
+ m2_lock.unlock();
+ // wait for thread 2 to finish
+ t2.join();
+
+ return 0;
+}
--- /dev/null
+# XFAIL: system-windows
+# REQUIRES: native && (target-x86 || target-x86_64)
+# RUN: %clangxx_host %p/Inputs/x86-multithread-read.cpp -o %t -pthread
+# RUN: %lldb -b -s %s %t | FileCheck %s
+
+process launch
+# CHECK: Process {{[0-9]+}} stopped
+
+register read --all
+# CHECK-DAG: eax = 0x05060708
+# CHECK-DAG: ebx = 0x15161718
+# CHECK-DAG: st{{(mm)?}}0 = {0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x00 0x40}
+
+process continue
+# CHECK: Process {{[0-9]+}} stopped
+
+register read --all
+# CHECK-DAG: eax = 0x25262728
+# CHECK-DAG: ebx = 0x35363738
+# CHECK-DAG: st{{(mm)?}}0 = {0x11 0x21 0x31 0x41 0x51 0x61 0x71 0x81 0x00 0xc0}
+
+process continue
+# CHECK: Process {{[0-9]+}} exited with status = 0
--- /dev/null
+# XFAIL: system-windows
+# XFAIL: system-darwin
+# REQUIRES: native && (target-x86 || target-x86_64)
+# RUN: %clangxx_host %p/Inputs/x86-multithread-write.cpp -o %t -pthread
+# RUN: %lldb -b -s %s %t | FileCheck %s
+
+process launch
+# CHECK: Process {{[0-9]+}} stopped
+
+register write eax 0x05060708
+register write ebx 0x15161718
+# TODO: the need to call 'read' is probably a bug in the Linux plugin
+register read st0
+register write st0 "{0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x00 0x40}"
+
+process continue
+# CHECK-DAG: eax = 0x05060708
+# CHECK-DAG: ebx = 0x15161718
+# CHECK-DAG: st0 = { 0x10 0x20 0x30 0x40 0x50 0x60 0x70 0x80 0x00 0x40 }
+# CHECK: Process {{[0-9]+}} stopped
+
+register write eax 0x25262728
+register write ebx 0x35363738
+register read st0
+register write st0 "{0x11 0x21 0x31 0x41 0x51 0x61 0x71 0x81 0x00 0xc0}"
+
+process continue
+# CHECK-DAG: eax = 0x25262728
+# CHECK-DAG: ebx = 0x35363738
+# CHECK-DAG: st0 = { 0x11 0x21 0x31 0x41 0x51 0x61 0x71 0x81 0x00 0xc0 }
+# CHECK: Process {{[0-9]+}} exited with status = 0