1 | #include <cstdint> |
2 | #include <mutex> |
3 | #include <thread> |
4 | |
5 | std::mutex t1_mutex, t2_mutex; |
6 | |
7 | struct test_data { |
8 | uint32_t eax; |
9 | uint32_t ebx; |
10 | |
11 | struct alignas(16) { |
12 | uint64_t mantissa; |
13 | uint16_t sign_exp; |
14 | } st0; |
15 | }; |
16 | |
17 | void t_func(std::mutex &t_mutex, const test_data &t_data) { |
18 | std::lock_guard<std::mutex> t_lock(t_mutex); |
19 | |
20 | asm volatile( |
21 | "finit\t\n" |
22 | "fldt %2\t\n" |
23 | "int3\n\t" |
24 | : |
25 | : "a" (t_data.eax), "b" (t_data.ebx), "m" (t_data.st0) |
26 | : "st" |
27 | ); |
28 | } |
29 | |
30 | int main() { |
31 | test_data t1_data = { |
32 | .eax = 0x05060708, |
33 | .ebx = 0x15161718, |
34 | .st0 = {.mantissa: 0x8070605040302010, .sign_exp: 0x4000}, |
35 | }; |
36 | test_data t2_data = { |
37 | .eax = 0x25262728, |
38 | .ebx = 0x35363738, |
39 | .st0 = {.mantissa: 0x8171615141312111, .sign_exp: 0xc000}, |
40 | }; |
41 | |
42 | // block both threads from proceeding |
43 | std::unique_lock<std::mutex> m1_lock(t1_mutex); |
44 | std::unique_lock<std::mutex> m2_lock(t2_mutex); |
45 | |
46 | // start both threads |
47 | std::thread t1(t_func, std::ref(t&: t1_mutex), std::ref(t&: t1_data)); |
48 | std::thread t2(t_func, std::ref(t&: t2_mutex), std::ref(t&: t2_data)); |
49 | |
50 | // release lock on thread 1 to make it interrupt the program |
51 | m1_lock.unlock(); |
52 | // wait for thread 1 to finish |
53 | t1.join(); |
54 | |
55 | // release lock on thread 2 |
56 | m2_lock.unlock(); |
57 | // wait for thread 2 to finish |
58 | t2.join(); |
59 | |
60 | return 0; |
61 | } |
62 | |