tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[PATCH v4 3/4] Combine x86 register tests into unified test function



Reduce the code duplication and improve maintainability of x86 register
tests by combining all of them to a single base function.
---
 tests/lib/libc/sys/t_ptrace_amd64_wait.h |  406 +---
 tests/lib/libc/sys/t_ptrace_i386_wait.h  |  335 +--
 tests/lib/libc/sys/t_ptrace_x86_wait.h   | 2417 ++++++++++------------
 3 files changed, 1103 insertions(+), 2055 deletions(-)

diff --git a/tests/lib/libc/sys/t_ptrace_amd64_wait.h b/tests/lib/libc/sys/t_ptrace_amd64_wait.h
index 1ea17ea1ec1a..0f410f3600d0 100644
--- a/tests/lib/libc/sys/t_ptrace_amd64_wait.h
+++ b/tests/lib/libc/sys/t_ptrace_amd64_wait.h
@@ -111,415 +111,11 @@ ATF_TC_BODY(x86_64_regs1, tc)
 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
 }
 
-ATF_TC(x86_64_regs_gp_read);
-ATF_TC_HEAD(x86_64_regs_gp_read, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set general-purpose reg values from debugged program and read "
-		"them via PT_GETREGS, comparing values against expected.");
-}
-
-ATF_TC_BODY(x86_64_regs_gp_read, tc)
-{
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct reg gpr;
-
-	const uint64_t rax = 0x0001020304050607;
-	const uint64_t rbx = 0x1011121314151617;
-	const uint64_t rcx = 0x2021222324252627;
-	const uint64_t rdx = 0x3031323334353637;
-	const uint64_t rsi = 0x4041424344454647;
-	const uint64_t rdi = 0x5051525354555657;
-	const uint64_t rsp = 0x6061626364656667;
-	const uint64_t rbp = 0x7071727374757677;
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-
-		__asm__ __volatile__(
-			/* rbp & rbp are a bit tricky, we must not clobber them */
-			"movq    %%rsp, %%r8\n\t"
-			"movq    %%rbp, %%r9\n\t"
-			"movq    %6, %%rsp\n\t"
-			"movq    %7, %%rbp\n\t"
-			"\n\t"
-			"int3\n\t"
-			"\n\t"
-			"movq    %%r8, %%rsp\n\t"
-			"movq    %%r9, %%rbp\n\t"
-			:
-			: "a"(rax), "b"(rbx), "c"(rcx), "d"(rdx), "S"(rsi), "D"(rdi),
-			  "i"(rsp), "i"(rbp)
-			: "%r8", "%r9"
-		);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	DPRINTF("Call GETREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RAX], rax);
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RBX], rbx);
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RCX], rcx);
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RDX], rdx);
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RSI], rsi);
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RDI], rdi);
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RSP], rsp);
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RBP], rbp);
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(x86_64_regs_gp_write);
-ATF_TC_HEAD(x86_64_regs_gp_write, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set general-purpose reg values into a debugged program via "
-		"PT_SETREGS and compare the result against expected.");
-}
-
-ATF_TC_BODY(x86_64_regs_gp_write, tc)
-{
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct reg gpr;
-
-	const uint64_t rax = 0x0001020304050607;
-	const uint64_t rbx = 0x1011121314151617;
-	const uint64_t rcx = 0x2021222324252627;
-	const uint64_t rdx = 0x3031323334353637;
-	const uint64_t rsi = 0x4041424344454647;
-	const uint64_t rdi = 0x5051525354555657;
-	const uint64_t rsp = 0x6061626364656667;
-	const uint64_t rbp = 0x7071727374757677;
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
-		uint64_t v_rax, v_rbx, v_rcx, v_rdx, v_rsi, v_rdi, v_rsp, v_rbp;
-
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-
-		__asm__ __volatile__(
-			/* save rsp & rbp */
-			"movq    %%rsp, %4\n\t"
-			"movq    %%rbp, %5\n\t"
-			"\n\t"
-			/* fill registers with clobber pattern */
-			"movq    %8, %%rax\n\t"
-			"movq    %8, %%rbx\n\t"
-			"movq    %8, %%rcx\n\t"
-			"movq    %8, %%rdx\n\t"
-			"movq    %8, %%rsp\n\t"
-			"movq    %8, %%rbp\n\t"
-			"movq    %8, %%rsi\n\t"
-			"movq    %8, %%rdi\n\t"
-			"\n\t"
-			"int3\n\t"
-			"\n\t"
-			/* swap saved & current rsp & rbp */
-			"xchgq    %%rsp, %4\n\t"
-			"xchgq    %%rbp, %5\n\t"
-			: "=a"(v_rax), "=b"(v_rbx), "=c"(v_rcx), "=d"(v_rdx), "=r"(v_rsp),
-			"=r"(v_rbp), "=S"(v_rsi), "=D"(v_rdi)
-			: "g"(fill)
-			:
-		);
-
-		DPRINTF("Before comparing results\n");
-		FORKEE_ASSERT_EQ(v_rax, rax);
-		FORKEE_ASSERT_EQ(v_rbx, rbx);
-		FORKEE_ASSERT_EQ(v_rcx, rcx);
-		FORKEE_ASSERT_EQ(v_rdx, rdx);
-		FORKEE_ASSERT_EQ(v_rsi, rsi);
-		FORKEE_ASSERT_EQ(v_rdi, rdi);
-		FORKEE_ASSERT_EQ(v_rsp, rsp);
-		FORKEE_ASSERT_EQ(v_rbp, rbp);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	DPRINTF("Call GETREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
-	gpr.regs[_REG_RAX] = rax;
-	gpr.regs[_REG_RBX] = rbx;
-	gpr.regs[_REG_RCX] = rcx;
-	gpr.regs[_REG_RDX] = rdx;
-	gpr.regs[_REG_RSI] = rsi;
-	gpr.regs[_REG_RDI] = rdi;
-	gpr.regs[_REG_RSP] = rsp;
-	gpr.regs[_REG_RBP] = rbp;
-
-	DPRINTF("Call SETREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(x86_64_regs_r8_read);
-ATF_TC_HEAD(x86_64_regs_r8_read, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set r8..r15 reg values from debugged program and read "
-		"them via PT_GETREGS, comparing values against expected.");
-}
-
-ATF_TC_BODY(x86_64_regs_r8_read, tc)
-{
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct reg gpr;
-
-	const uint64_t r8[] = {
-		0x0001020304050607,
-		0x1011121314151617,
-		0x2021222324252627,
-		0x3031323334353637,
-		0x4041424344454647,
-		0x5051525354555657,
-		0x6061626364656667,
-		0x7071727374757677,
-	};
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-
-		__asm__ __volatile__(
-			"movq    0x00(%%rbx), %%r8\n\t"
-			"movq    0x08(%%rbx), %%r9\n\t"
-			"movq    0x10(%%rbx), %%r10\n\t"
-			"movq    0x18(%%rbx), %%r11\n\t"
-			"movq    0x20(%%rbx), %%r12\n\t"
-			"movq    0x28(%%rbx), %%r13\n\t"
-			"movq    0x30(%%rbx), %%r14\n\t"
-			"movq    0x38(%%rbx), %%r15\n\t"
-			"int3\n\t"
-			:
-			: "b"(r8)
-			: "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
-		);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	DPRINTF("Call GETREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R8], r8[0]);
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R9], r8[1]);
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R10], r8[2]);
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R11], r8[3]);
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R12], r8[4]);
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R13], r8[5]);
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R14], r8[6]);
-	ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R15], r8[7]);
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(x86_64_regs_r8_write);
-ATF_TC_HEAD(x86_64_regs_r8_write, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set r8..r15 reg values into a debugged program via "
-		"PT_SETREGS and compare the result against expected.");
-}
-
-ATF_TC_BODY(x86_64_regs_r8_write, tc)
-{
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct reg gpr;
-
-	const uint64_t r8[] = {
-		0x0001020304050607,
-		0x1011121314151617,
-		0x2021222324252627,
-		0x3031323334353637,
-		0x4041424344454647,
-		0x5051525354555657,
-		0x6061626364656667,
-		0x7071727374757677,
-	};
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
-		uint64_t v_r8[8];
-
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-
-		__asm__ __volatile__(
-			/* fill registers with clobber pattern */
-			"movq    %1, %%r8\n\t"
-			"movq    %1, %%r9\n\t"
-			"movq    %1, %%r10\n\t"
-			"movq    %1, %%r11\n\t"
-			"movq    %1, %%r12\n\t"
-			"movq    %1, %%r13\n\t"
-			"movq    %1, %%r14\n\t"
-			"movq    %1, %%r15\n\t"
-			"\n\t"
-			"int3\n\t"
-			"\n\t"
-			"movq    %%r8, 0x00(%0)\n\t"
-			"movq    %%r9, 0x08(%0)\n\t"
-			"movq    %%r10, 0x10(%0)\n\t"
-			"movq    %%r11, 0x18(%0)\n\t"
-			"movq    %%r12, 0x20(%0)\n\t"
-			"movq    %%r13, 0x28(%0)\n\t"
-			"movq    %%r14, 0x30(%0)\n\t"
-			"movq    %%r15, 0x38(%0)\n\t"
-			:
-			: "a"(v_r8), "m"(fill)
-			: "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
-		);
-
-		DPRINTF("Before comparing results\n");
-		FORKEE_ASSERT_EQ(v_r8[0], r8[0]);
-		FORKEE_ASSERT_EQ(v_r8[1], r8[1]);
-		FORKEE_ASSERT_EQ(v_r8[2], r8[2]);
-		FORKEE_ASSERT_EQ(v_r8[3], r8[3]);
-		FORKEE_ASSERT_EQ(v_r8[4], r8[4]);
-		FORKEE_ASSERT_EQ(v_r8[5], r8[5]);
-		FORKEE_ASSERT_EQ(v_r8[6], r8[6]);
-		FORKEE_ASSERT_EQ(v_r8[7], r8[7]);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	DPRINTF("Call GETREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
-	gpr.regs[_REG_R8] = r8[0];
-	gpr.regs[_REG_R9] = r8[1];
-	gpr.regs[_REG_R10] = r8[2];
-	gpr.regs[_REG_R11] = r8[3];
-	gpr.regs[_REG_R12] = r8[4];
-	gpr.regs[_REG_R13] = r8[5];
-	gpr.regs[_REG_R14] = r8[6];
-	gpr.regs[_REG_R15] = r8[7];
-
-	DPRINTF("Call SETREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
 /// ----------------------------------------------------------------------------
 
 
 #define ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64() \
-	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs1); \
-	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_gp_read); \
-	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_gp_write); \
-	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_r8_read); \
-	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs_r8_write);
+	ATF_TP_ADD_TC_HAVE_GPREGS(tp, x86_64_regs1);
 #else
 #define ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64()
 #endif
diff --git a/tests/lib/libc/sys/t_ptrace_i386_wait.h b/tests/lib/libc/sys/t_ptrace_i386_wait.h
index 7250f4eb66db..8db74261bb35 100644
--- a/tests/lib/libc/sys/t_ptrace_i386_wait.h
+++ b/tests/lib/libc/sys/t_ptrace_i386_wait.h
@@ -101,341 +101,8 @@ ATF_TC_BODY(i386_regs1, tc)
 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
 }
 
-ATF_TC(i386_regs_gp_read);
-ATF_TC_HEAD(i386_regs_gp_read, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set general-purpose reg values from debugged program and read "
-		"them via PT_GETREGS, comparing values against expected.");
-}
-
-ATF_TC_BODY(i386_regs_gp_read, tc)
-{
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct reg gpr;
-
-	const uint32_t eax = 0x00010203;
-	const uint32_t ebx = 0x10111213;
-	const uint32_t ecx = 0x20212223;
-	const uint32_t edx = 0x30313233;
-	const uint32_t esi = 0x40414243;
-	const uint32_t edi = 0x50515253;
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-
-		__asm__ __volatile__(
-			"int3\n\t"
-			:
-			: "a"(eax), "b"(ebx), "c"(ecx), "d"(edx), "S"(esi), "D"(edi)
-			:
-		);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	DPRINTF("Call GETREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
-	ATF_CHECK_EQ((uint32_t)gpr.r_eax, eax);
-	ATF_CHECK_EQ((uint32_t)gpr.r_ebx, ebx);
-	ATF_CHECK_EQ((uint32_t)gpr.r_ecx, ecx);
-	ATF_CHECK_EQ((uint32_t)gpr.r_edx, edx);
-	ATF_CHECK_EQ((uint32_t)gpr.r_esi, esi);
-	ATF_CHECK_EQ((uint32_t)gpr.r_edi, edi);
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(i386_regs_gp_write);
-ATF_TC_HEAD(i386_regs_gp_write, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set general-purpose reg values into a debugged program via "
-		"PT_SETREGS and compare the result against expected.");
-}
-
-ATF_TC_BODY(i386_regs_gp_write, tc)
-{
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct reg gpr;
-
-	const uint32_t eax = 0x00010203;
-	const uint32_t ebx = 0x10111213;
-	const uint32_t ecx = 0x20212223;
-	const uint32_t edx = 0x30313233;
-	const uint32_t esi = 0x40414243;
-	const uint32_t edi = 0x50515253;
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		const uint64_t fill = 0x0F0F0F0F;
-		uint32_t v_eax, v_ebx, v_ecx, v_edx, v_esi, v_edi;
-
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-
-		__asm__ __volatile__(
-			/* fill registers with clobber pattern */
-			"movl    %6, %%eax\n\t"
-			"movl    %6, %%ebx\n\t"
-			"movl    %6, %%ecx\n\t"
-			"movl    %6, %%edx\n\t"
-			"movl    %6, %%esi\n\t"
-			"movl    %6, %%edi\n\t"
-			"\n\t"
-			"int3\n\t"
-			: "=a"(v_eax), "=b"(v_ebx), "=c"(v_ecx), "=d"(v_edx), "=S"(v_esi),
-			"=D"(v_edi)
-			: "g"(fill)
-			:
-		);
-
-		DPRINTF("Before comparing results\n");
-		FORKEE_ASSERT_EQ(v_eax, eax);
-		FORKEE_ASSERT_EQ(v_ebx, ebx);
-		FORKEE_ASSERT_EQ(v_ecx, ecx);
-		FORKEE_ASSERT_EQ(v_edx, edx);
-		FORKEE_ASSERT_EQ(v_esi, esi);
-		FORKEE_ASSERT_EQ(v_edi, edi);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	DPRINTF("Call GETREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
-	gpr.r_eax = eax;
-	gpr.r_ebx = ebx;
-	gpr.r_ecx = ecx;
-	gpr.r_edx = edx;
-	gpr.r_esi = esi;
-	gpr.r_edi = edi;
-
-	DPRINTF("Call SETREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(i386_regs_ebp_esp_read);
-ATF_TC_HEAD(i386_regs_ebp_esp_read, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set EBP & ESP reg values from debugged program and read "
-		"them via PT_GETREGS, comparing values against expected.");
-}
-
-ATF_TC_BODY(i386_regs_ebp_esp_read, tc)
-{
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct reg gpr;
-
-	const uint32_t esp = 0x60616263;
-	const uint32_t ebp = 0x70717273;
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-
-		__asm__ __volatile__(
-			/* ebp & ebp are a bit tricky, we must not clobber them */
-			"movl    %%esp, %%eax\n\t"
-			"movl    %%ebp, %%ebx\n\t"
-			"movl    %0, %%esp\n\t"
-			"movl    %1, %%ebp\n\t"
-			"\n\t"
-			"int3\n\t"
-			"\n\t"
-			"movl    %%eax, %%esp\n\t"
-			"movl    %%ebx, %%ebp\n\t"
-			:
-			: "ri"(esp), "ri"(ebp)
-			: "%eax", "%ebx"
-		);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	DPRINTF("Call GETREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
-	ATF_CHECK_EQ((uint32_t)gpr.r_esp, esp);
-	ATF_CHECK_EQ((uint32_t)gpr.r_ebp, ebp);
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(i386_regs_ebp_esp_write);
-ATF_TC_HEAD(i386_regs_ebp_esp_write, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set EBP & ESP reg values into a debugged program via "
-		"PT_SETREGS and compare the result against expected.");
-}
-
-ATF_TC_BODY(i386_regs_ebp_esp_write, tc)
-{
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct reg gpr;
-
-	const uint32_t esp = 0x60616263;
-	const uint32_t ebp = 0x70717273;
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		const uint64_t fill = 0x0F0F0F0F;
-		uint32_t v_esp, v_ebp;
-
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-
-		__asm__ __volatile__(
-			/* save original ebp & esp using our output registers */
-			"movl    %%esp, %0\n\t"
-			"movl    %%ebp, %1\n\t"
-			/* fill them with clobber pattern */
-			"movl    %2, %%esp\n\t"
-			"movl    %2, %%ebp\n\t"
-			"\n\t"
-			"int3\n\t"
-			"\n\t"
-			/* restore ebp & esp, and save the result */
-			"xchgl   %%esp, %0\n\t"
-			"xchgl   %%ebp, %1\n\t"
-			: "=r"(v_esp), "=r"(v_ebp)
-			: "g"(fill)
-			:
-		);
-
-		DPRINTF("Before comparing results\n");
-		FORKEE_ASSERT_EQ(v_esp, esp);
-		FORKEE_ASSERT_EQ(v_ebp, ebp);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	DPRINTF("Call GETREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
-
-	gpr.r_esp = esp;
-	gpr.r_ebp = ebp;
-
-	DPRINTF("Call SETREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
 #define ATF_TP_ADD_TCS_PTRACE_WAIT_I386() \
-	ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs1); \
-	ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_gp_read); \
-	ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_gp_write); \
-	ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_ebp_esp_read); \
-	ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_ebp_esp_write);
+	ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs1);
 #else
 #define ATF_TP_ADD_TCS_PTRACE_WAIT_I386()
 #endif
diff --git a/tests/lib/libc/sys/t_ptrace_x86_wait.h b/tests/lib/libc/sys/t_ptrace_x86_wait.h
index 6d177d4624e9..4572e3eb8b23 100644
--- a/tests/lib/libc/sys/t_ptrace_x86_wait.h
+++ b/tests/lib/libc/sys/t_ptrace_x86_wait.h
@@ -2189,1273 +2189,400 @@ ATF_TC_BODY(x86_cve_2018_8897, tc)
 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
 }
 
-ATF_TC(x86_regs_mm_read);
-ATF_TC_HEAD(x86_regs_mm_read, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set MMX (mm0..mm7) reg values from debugged program and read "
-		"them via PT_GETFPREGS, comparing values against expected.");
-}
+/// ----------------------------------------------------------------------------
 
-__attribute__((target("mmx")))
-static __inline void set_mm_regs(const uint64_t mm[])
+union x86_test_register {
+	struct {
+		uint64_t a, b, c, d;
+	} ymm;
+	struct {
+		uint64_t a, b;
+	} xmm;
+	uint64_t u64;
+	uint32_t u32;
+};
+
+enum x86_test_regset {
+	TEST_GPREGS,
+	TEST_FPREGS,
+	TEST_XMMREGS,
+	TEST_XSTATE
+};
+
+/* Please keep them grouped by acceptable x86_test_regset. */
+enum x86_test_registers {
+	/* TEST_GPREGS */
+	GPREGS_32,
+	GPREGS_32_EBP_ESP,
+	GPREGS_64,
+	GPREGS_64_R8,
+	/* TEST_FPREGS/TEST_XMMREGS */
+	FPREGS_MM,
+	FPREGS_XMM,
+	/* TEST_XSTATE */
+	FPREGS_YMM
+};
+
+enum x86_test_regmode {
+	TEST_GETREGS,
+	TEST_SETREGS
+};
+
+static __inline void get_gp32_regs(union x86_test_register out[])
 {
+#if defined(__i386__)
+	const uint32_t fill = 0x0F0F0F0F;
+
 	__asm__ __volatile__(
-		"movq    0x00(%0), %%mm0\n\t"
-		"movq    0x08(%0), %%mm1\n\t"
-		"movq    0x10(%0), %%mm2\n\t"
-		"movq    0x18(%0), %%mm3\n\t"
-		"movq    0x20(%0), %%mm4\n\t"
-		"movq    0x28(%0), %%mm5\n\t"
-		"movq    0x30(%0), %%mm6\n\t"
-		"movq    0x38(%0), %%mm7\n\t"
+		/* fill registers with clobber pattern */
+		"movl    %6, %%eax\n\t"
+		"movl    %6, %%ebx\n\t"
+		"movl    %6, %%ecx\n\t"
+		"movl    %6, %%edx\n\t"
+		"movl    %6, %%esi\n\t"
+		"movl    %6, %%edi\n\t"
+		"\n\t"
 		"int3\n\t"
-		:
-		: "b"(mm)
-		: "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
+		: "=a"(out[0].u32), "=b"(out[1].u32), "=c"(out[2].u32),
+		  "=d"(out[3].u32), "=S"(out[4].u32), "=D"(out[5].u32)
+		: "g"(fill)
 	);
+#else
+	__unreachable();
+#endif
 }
 
-ATF_TC_BODY(x86_regs_mm_read, tc)
+static __inline void set_gp32_regs(const union x86_test_register data[])
 {
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct fpreg fpr;
-
-	const uint64_t mm[] = {
-		0x0001020304050607,
-		0x1011121314151617,
-		0x2021222324252627,
-		0x3031323334353637,
-		0x4041424344454647,
-		0x5051525354555657,
-		0x6061626364656667,
-		0x7071727374757677,
-	};
-
-	/* verify whether MMX is supported here */
-	DPRINTF("Before invoking cpuid\n");
-	{
-		unsigned int eax, ebx, ecx, edx;
-		if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
-			atf_tc_skip("CPUID is not supported by the CPU");
-
-		DPRINTF("cpuid: EDX = %08x\n", edx);
-
-		if (!(edx & bit_MMX))
-			atf_tc_skip("MMX is not supported by the CPU");
-	}
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-		set_mm_regs(mm);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	DPRINTF("Call GETFPREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
-
-#if defined(__x86_64__)
-#define MM_REG(n) fpr.fxstate.fx_87_ac[n].r.f87_mantissa
+#if defined(__i386__)
+	__asm__ __volatile__(
+		"int3\n\t"
+		:
+		: "a"(data[0].u32), "b"(data[1].u32), "c"(data[2].u32),
+		  "d"(data[3].u32), "S"(data[4].u32), "D"(data[5].u32)
+		:
+	);
 #else
-#define MM_REG(n) fpr.fstate.s87_ac[n].f87_mantissa
+	__unreachable();
 #endif
-
-	ATF_CHECK_EQ(MM_REG(0), mm[0]);
-	ATF_CHECK_EQ(MM_REG(1), mm[1]);
-	ATF_CHECK_EQ(MM_REG(2), mm[2]);
-	ATF_CHECK_EQ(MM_REG(3), mm[3]);
-	ATF_CHECK_EQ(MM_REG(4), mm[4]);
-	ATF_CHECK_EQ(MM_REG(5), mm[5]);
-	ATF_CHECK_EQ(MM_REG(6), mm[6]);
-	ATF_CHECK_EQ(MM_REG(7), mm[7]);
-
-#undef MM_REG
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
 }
 
-__attribute__((target("mmx")))
-static __inline void get_mm_regs(uint64_t v_mm[])
+static __inline void get_gp32_ebp_esp_regs(union x86_test_register out[])
 {
-	const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
+#if defined(__i386__)
+	const uint32_t fill = 0x0F0F0F0F;
 
 	__asm__ __volatile__(
-		/* fill registers with clobber pattern */
-		"movq    %1, %%mm0\n\t"
-		"movq    %1, %%mm1\n\t"
-		"movq    %1, %%mm2\n\t"
-		"movq    %1, %%mm3\n\t"
-		"movq    %1, %%mm4\n\t"
-		"movq    %1, %%mm5\n\t"
-		"movq    %1, %%mm6\n\t"
-		"movq    %1, %%mm7\n\t"
+		/* save original ebp & esp using our output registers */
+		"movl    %%esp, %0\n\t"
+		"movl    %%ebp, %1\n\t"
+		/* fill them with clobber pattern */
+		"movl    %2, %%esp\n\t"
+		"movl    %2, %%ebp\n\t"
 		"\n\t"
 		"int3\n\t"
 		"\n\t"
-		"movq    %%mm0, 0x00(%0)\n\t"
-		"movq    %%mm1, 0x08(%0)\n\t"
-		"movq    %%mm2, 0x10(%0)\n\t"
-		"movq    %%mm3, 0x18(%0)\n\t"
-		"movq    %%mm4, 0x20(%0)\n\t"
-		"movq    %%mm5, 0x28(%0)\n\t"
-		"movq    %%mm6, 0x30(%0)\n\t"
-		"movq    %%mm7, 0x38(%0)\n\t"
+		/* restore ebp & esp, and save the result */
+		"xchgl   %%esp, %0\n\t"
+		"xchgl   %%ebp, %1\n\t"
+		: "=r"(out[0].u32), "=r"(out[1].u32)
+		: "g"(fill)
 		:
-		: "a"(v_mm), "m"(fill)
-		: "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
 	);
-}
-
-ATF_TC(x86_regs_mm_write);
-ATF_TC_HEAD(x86_regs_mm_write, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set mm0..mm7 reg values into a debugged program via "
-		"PT_SETFPREGS and compare the result against expected.");
-}
-
-ATF_TC_BODY(x86_regs_mm_write, tc)
-{
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct fpreg fpr;
-
-	const uint64_t mm[] = {
-		0x0001020304050607,
-		0x1011121314151617,
-		0x2021222324252627,
-		0x3031323334353637,
-		0x4041424344454647,
-		0x5051525354555657,
-		0x6061626364656667,
-		0x7071727374757677,
-	};
-
-	/* verify whether MMX is supported here */
-	DPRINTF("Before invoking cpuid\n");
-	{
-		unsigned int eax, ebx, ecx, edx;
-		if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
-			atf_tc_skip("CPUID is not supported by the CPU");
-
-		DPRINTF("cpuid: EDX = %08x\n", edx);
-
-		if (!(edx & bit_MMX))
-			atf_tc_skip("MMX is not supported by the CPU");
-	}
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		uint64_t v_mm[8];
-
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-		get_mm_regs(v_mm);
-
-		DPRINTF("Before comparing results\n");
-		FORKEE_ASSERT_EQ(v_mm[0], mm[0]);
-		FORKEE_ASSERT_EQ(v_mm[1], mm[1]);
-		FORKEE_ASSERT_EQ(v_mm[2], mm[2]);
-		FORKEE_ASSERT_EQ(v_mm[3], mm[3]);
-		FORKEE_ASSERT_EQ(v_mm[4], mm[4]);
-		FORKEE_ASSERT_EQ(v_mm[5], mm[5]);
-		FORKEE_ASSERT_EQ(v_mm[6], mm[6]);
-		FORKEE_ASSERT_EQ(v_mm[7], mm[7]);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	DPRINTF("Call GETFPREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
-
-#if defined(__x86_64__)
-#define MM_REG(n) fpr.fxstate.fx_87_ac[n].r.f87_mantissa
 #else
-#define MM_REG(n) fpr.fstate.s87_ac[n].f87_mantissa
+	__unreachable();
 #endif
-
-	MM_REG(0) = mm[0];
-	MM_REG(1) = mm[1];
-	MM_REG(2) = mm[2];
-	MM_REG(3) = mm[3];
-	MM_REG(4) = mm[4];
-	MM_REG(5) = mm[5];
-	MM_REG(6) = mm[6];
-	MM_REG(7) = mm[7];
-
-#undef MM_REG
-
-	DPRINTF("Call SETFPREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
 }
 
-__attribute__((target("sse")))
-static __inline void set_xmm_regs(const void* xmm)
+static __inline void set_gp32_ebp_esp_regs(const union x86_test_register data[])
 {
+#if defined(__i386__)
 	__asm__ __volatile__(
-		"movaps   0x00(%0), %%xmm0\n\t"
-		"movaps   0x10(%0), %%xmm1\n\t"
-		"movaps   0x20(%0), %%xmm2\n\t"
-		"movaps   0x30(%0), %%xmm3\n\t"
-		"movaps   0x40(%0), %%xmm4\n\t"
-		"movaps   0x50(%0), %%xmm5\n\t"
-		"movaps   0x60(%0), %%xmm6\n\t"
-		"movaps   0x70(%0), %%xmm7\n\t"
-#if defined(__x86_64__)
-		"movaps   0x80(%0), %%xmm8\n\t"
-		"movaps   0x90(%0), %%xmm9\n\t"
-		"movaps   0xA0(%0), %%xmm10\n\t"
-		"movaps   0xB0(%0), %%xmm11\n\t"
-		"movaps   0xC0(%0), %%xmm12\n\t"
-		"movaps   0xD0(%0), %%xmm13\n\t"
-		"movaps   0xE0(%0), %%xmm14\n\t"
-		"movaps   0xF0(%0), %%xmm15\n\t"
-#endif
+		/* ebp & ebp are a bit tricky, we must not clobber them */
+		"movl    %%esp, %%eax\n\t"
+		"movl    %%ebp, %%ebx\n\t"
+		"movl    %0, %%esp\n\t"
+		"movl    %1, %%ebp\n\t"
+		"\n\t"
 		"int3\n\t"
+		"\n\t"
+		"movl    %%eax, %%esp\n\t"
+		"movl    %%ebx, %%ebp\n\t"
 		:
-		: "b"(xmm)
-		: "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
-		"%xmm7"
-#if defined(__x86_64__)
-		, "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13",
-		"%xmm14", "%xmm15"
-#endif
+		: "ri"(data[0].u32), "ri"(data[1].u32)
+		: "%eax", "%ebx"
 	);
+#else
+	__unreachable();
+#endif
 }
 
-ATF_TC(x86_regs_xmm_read);
-ATF_TC_HEAD(x86_regs_xmm_read, tc)
+static __inline void get_gp64_regs(union x86_test_register out[])
 {
-	atf_tc_set_md_var(tc, "descr",
-		"Set xmm0..xmm15 (..xmm7 on i386) reg values from debugged program "
-		"and read them via PT_GETFPREGS (PT_GETXMMREGS on i386), comparing "
-		"values against expected.");
+#if defined(__x86_64__)
+	const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
+
+	__asm__ __volatile__(
+		/* save rsp & rbp */
+		"movq    %%rsp, %6\n\t"
+		"movq    %%rbp, %7\n\t"
+		"\n\t"
+		/* fill registers with clobber pattern */
+		"movq    %8, %%rax\n\t"
+		"movq    %8, %%rbx\n\t"
+		"movq    %8, %%rcx\n\t"
+		"movq    %8, %%rdx\n\t"
+		"movq    %8, %%rsp\n\t"
+		"movq    %8, %%rbp\n\t"
+		"movq    %8, %%rsi\n\t"
+		"movq    %8, %%rdi\n\t"
+		"\n\t"
+		"int3\n\t"
+		"\n\t"
+		/* swap saved & current rsp & rbp */
+		"xchgq    %%rsp, %6\n\t"
+		"xchgq    %%rbp, %7\n\t"
+		: "=a"(out[0].u64), "=b"(out[1].u64), "=c"(out[2].u64),
+		  "=d"(out[3].u64), "=S"(out[4].u64), "=D"(out[5].u64),
+		  "=r"(out[6].u64), "=r"(out[7].u64)
+		: "g"(fill)
+	);
+#else
+	__unreachable();
+#endif
 }
 
-ATF_TC_BODY(x86_regs_xmm_read, tc)
+static __inline void set_gp64_regs(const union x86_test_register data[])
 {
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
 #if defined(__x86_64__)
-	struct fpreg fpr;
+	__asm__ __volatile__(
+		/* rbp & rbp are a bit tricky, we must not clobber them */
+		"movq    %%rsp, %%r8\n\t"
+		"movq    %%rbp, %%r9\n\t"
+		"movq    %6, %%rsp\n\t"
+		"movq    %7, %%rbp\n\t"
+		"\n\t"
+		"int3\n\t"
+		"\n\t"
+		"movq    %%r8, %%rsp\n\t"
+		"movq    %%r9, %%rbp\n\t"
+		:
+		: "a"(data[0].u64), "b"(data[1].u64), "c"(data[2].u64),
+		  "d"(data[3].u64), "S"(data[4].u64), "D"(data[5].u64),
+		  "r"(data[6].u64), "r"(data[7].u64)
+		: "%r8", "%r9"
+	);
 #else
-	struct xmmregs fpr;
+	__unreachable();
 #endif
+}
 
-	const struct {
-		uint64_t a, b;
-	} xmm[] __aligned(16) = {
-		{ 0x0706050403020100, 0x0F0E0D0C0B0A0908, },
-		{ 0x0807060504030201, 0x100F0E0D0C0B0A09, },
-		{ 0x0908070605040302, 0x11100F0E0D0C0B0A, },
-		{ 0x0A09080706050403, 0x1211100F0E0D0C0B, },
-		{ 0x0B0A090807060504, 0x131211100F0E0D0C, },
-		{ 0x0C0B0A0908070605, 0x14131211100F0E0D, },
-		{ 0x0D0C0B0A09080706, 0x1514131211100F0E, },
-		{ 0x0E0D0C0B0A090807, 0x161514131211100F, },
+static __inline void get_gp64_r8_regs(union x86_test_register out[])
+{
 #if defined(__x86_64__)
-		{ 0x0F0E0D0C0B0A0908, 0x1716151413121110, },
-		{ 0x100F0E0D0C0B0A09, 0x1817161514131211, },
-		{ 0x11100F0E0D0C0B0A, 0x1918171615141312, },
-		{ 0x1211100F0E0D0C0B, 0x1A19181716151413, },
-		{ 0x131211100F0E0D0C, 0x1B1A191817161514, },
-		{ 0x14131211100F0E0D, 0x1C1B1A1918171615, },
-		{ 0x1514131211100F0E, 0x1D1C1B1A19181716, },
-		{ 0x161514131211100F, 0x1E1D1C1B1A191817, },
-#endif
-	};
-
-	/* verify whether SSE is supported here */
-	DPRINTF("Before invoking cpuid\n");
-	{
-		unsigned int eax, ebx, ecx, edx;
-		if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
-			atf_tc_skip("CPUID is not supported by the CPU");
-
-		DPRINTF("cpuid: EDX = %08x\n", edx);
-
-		if (!(edx & bit_SSE))
-			atf_tc_skip("SSE is not supported by the CPU");
-	}
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-		set_xmm_regs(xmm);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
+	const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
 
-#if defined(__x86_64__)
-	DPRINTF("Call GETFPREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
+	__asm__ __volatile__(
+		/* fill registers with clobber pattern */
+		"movq    %1, %%r8\n\t"
+		"movq    %1, %%r9\n\t"
+		"movq    %1, %%r10\n\t"
+		"movq    %1, %%r11\n\t"
+		"movq    %1, %%r12\n\t"
+		"movq    %1, %%r13\n\t"
+		"movq    %1, %%r14\n\t"
+		"movq    %1, %%r15\n\t"
+		"\n\t"
+		"int3\n\t"
+		"\n\t"
+		"movq    %%r8, 0x00(%0)\n\t"
+		"movq    %%r9, 0x20(%0)\n\t"
+		"movq    %%r10, 0x40(%0)\n\t"
+		"movq    %%r11, 0x60(%0)\n\t"
+		"movq    %%r12, 0x80(%0)\n\t"
+		"movq    %%r13, 0xA0(%0)\n\t"
+		"movq    %%r14, 0xC0(%0)\n\t"
+		"movq    %%r15, 0xE0(%0)\n\t"
+		:
+		: "a"(out), "m"(fill)
+		: "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
+	);
 #else
-	DPRINTF("Call GETXMMREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETXMMREGS, child, &fpr, 0) != -1);
-#endif
-
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[0], &xmm[0], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[1], &xmm[1], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[2], &xmm[2], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[3], &xmm[3], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[4], &xmm[4], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[5], &xmm[5], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[6], &xmm[6], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[7], &xmm[7], sizeof(*xmm)));
-#if defined(__x86_64__)
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[8], &xmm[8], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[9], &xmm[9], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[10], &xmm[10], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[11], &xmm[11], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[12], &xmm[12], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[13], &xmm[13], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[14], &xmm[14], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[15], &xmm[15], sizeof(*xmm)));
+	__unreachable();
 #endif
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
 }
 
-__attribute__((target("sse")))
-static __inline void get_xmm_regs(void* v_xmm)
+static __inline void set_gp64_r8_regs(const union x86_test_register data[])
 {
-	const struct {
-		uint64_t a, b;
-	} fill __aligned(16) = {0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F};
-
-	__asm__ __volatile__(
-		/* fill registers with clobber pattern */
-		"movaps  %1, %%xmm0\n\t"
-		"movaps  %1, %%xmm1\n\t"
-		"movaps  %1, %%xmm2\n\t"
-		"movaps  %1, %%xmm3\n\t"
-		"movaps  %1, %%xmm4\n\t"
-		"movaps  %1, %%xmm5\n\t"
-		"movaps  %1, %%xmm6\n\t"
-		"movaps  %1, %%xmm7\n\t"
-#if defined(__x86_64__)
-		"movaps  %1, %%xmm8\n\t"
-		"movaps  %1, %%xmm9\n\t"
-		"movaps  %1, %%xmm10\n\t"
-		"movaps  %1, %%xmm11\n\t"
-		"movaps  %1, %%xmm12\n\t"
-		"movaps  %1, %%xmm13\n\t"
-		"movaps  %1, %%xmm14\n\t"
-		"movaps  %1, %%xmm15\n\t"
-#endif
-		"\n\t"
-		"int3\n\t"
-		"\n\t"
-		"movaps  %%xmm0, 0x00(%0)\n\t"
-		"movaps  %%xmm1, 0x10(%0)\n\t"
-		"movaps  %%xmm2, 0x20(%0)\n\t"
-		"movaps  %%xmm3, 0x30(%0)\n\t"
-		"movaps  %%xmm4, 0x40(%0)\n\t"
-		"movaps  %%xmm5, 0x50(%0)\n\t"
-		"movaps  %%xmm6, 0x60(%0)\n\t"
-		"movaps  %%xmm7, 0x70(%0)\n\t"
-#if defined(__x86_64__)
-		"movaps  %%xmm8, 0x80(%0)\n\t"
-		"movaps  %%xmm9, 0x90(%0)\n\t"
-		"movaps  %%xmm10, 0xA0(%0)\n\t"
-		"movaps  %%xmm11, 0xB0(%0)\n\t"
-		"movaps  %%xmm12, 0xC0(%0)\n\t"
-		"movaps  %%xmm13, 0xD0(%0)\n\t"
-		"movaps  %%xmm14, 0xE0(%0)\n\t"
-		"movaps  %%xmm15, 0xF0(%0)\n\t"
-#endif
-		:
-		: "a"(v_xmm), "m"(fill)
-		: "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7"
-#if defined(__x86_64__)
-		, "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14",
-		"%xmm15"
-#endif
-	);
-}
-
-ATF_TC(x86_regs_xmm_write);
-ATF_TC_HEAD(x86_regs_xmm_write, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set xmm0..xmm15 (..xmm7 on i386) reg values into a debugged "
-		"program via PT_SETFPREGS (PT_SETXMMREGS on i386) and compare "
-		"the result against expected.");
-}
-
-ATF_TC_BODY(x86_regs_xmm_write, tc)
-{
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
 #if defined(__x86_64__)
-	struct fpreg fpr;
-#else
-	struct xmmregs fpr;
-#endif
-
-	const struct {
-		uint64_t a, b;
-	} xmm[] __aligned(16) = {
-		{ 0x0706050403020100, 0x0F0E0D0C0B0A0908, },
-		{ 0x0807060504030201, 0x100F0E0D0C0B0A09, },
-		{ 0x0908070605040302, 0x11100F0E0D0C0B0A, },
-		{ 0x0A09080706050403, 0x1211100F0E0D0C0B, },
-		{ 0x0B0A090807060504, 0x131211100F0E0D0C, },
-		{ 0x0C0B0A0908070605, 0x14131211100F0E0D, },
-		{ 0x0D0C0B0A09080706, 0x1514131211100F0E, },
-		{ 0x0E0D0C0B0A090807, 0x161514131211100F, },
-#if defined(__x86_64__)
-		{ 0x0F0E0D0C0B0A0908, 0x1716151413121110, },
-		{ 0x100F0E0D0C0B0A09, 0x1817161514131211, },
-		{ 0x11100F0E0D0C0B0A, 0x1918171615141312, },
-		{ 0x1211100F0E0D0C0B, 0x1A19181716151413, },
-		{ 0x131211100F0E0D0C, 0x1B1A191817161514, },
-		{ 0x14131211100F0E0D, 0x1C1B1A1918171615, },
-		{ 0x1514131211100F0E, 0x1D1C1B1A19181716, },
-		{ 0x161514131211100F, 0x1E1D1C1B1A191817, },
-#endif
-	};
-
-	/* verify whether SSE is supported here */
-	DPRINTF("Before invoking cpuid\n");
-	{
-		unsigned int eax, ebx, ecx, edx;
-		if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
-			atf_tc_skip("CPUID is not supported by the CPU");
-
-		DPRINTF("cpuid: EDX = %08x\n", edx);
-
-		if (!(edx & bit_SSE))
-			atf_tc_skip("SSE is not supported by the CPU");
-	}
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		struct {
-			uint64_t a, b;
-		} v_xmm[16] __aligned(16);
-
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-		get_xmm_regs(v_xmm);
-
-		DPRINTF("Before comparing results\n");
-		FORKEE_ASSERT(!memcmp(&v_xmm[0], &xmm[0], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[1], &xmm[1], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[2], &xmm[2], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[3], &xmm[3], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[4], &xmm[4], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[5], &xmm[5], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[6], &xmm[6], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[7], &xmm[7], sizeof(*xmm)));
-#if defined(__x86_64__)
-		FORKEE_ASSERT(!memcmp(&v_xmm[8], &xmm[8], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[9], &xmm[9], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[10], &xmm[10], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[11], &xmm[11], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[12], &xmm[12], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[13], &xmm[13], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[14], &xmm[14], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[15], &xmm[15], sizeof(*xmm)));
-#endif
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-#if defined(__x86_64__)
-	DPRINTF("Call GETFPREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
-#else
-	DPRINTF("Call GETXMMREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETXMMREGS, child, &fpr, 0) != -1);
-#endif
-
-	memcpy(&fpr.fxstate.fx_xmm[0], &xmm[0], sizeof(*xmm));
-	memcpy(&fpr.fxstate.fx_xmm[1], &xmm[1], sizeof(*xmm));
-	memcpy(&fpr.fxstate.fx_xmm[2], &xmm[2], sizeof(*xmm));
-	memcpy(&fpr.fxstate.fx_xmm[3], &xmm[3], sizeof(*xmm));
-	memcpy(&fpr.fxstate.fx_xmm[4], &xmm[4], sizeof(*xmm));
-	memcpy(&fpr.fxstate.fx_xmm[5], &xmm[5], sizeof(*xmm));
-	memcpy(&fpr.fxstate.fx_xmm[6], &xmm[6], sizeof(*xmm));
-	memcpy(&fpr.fxstate.fx_xmm[7], &xmm[7], sizeof(*xmm));
-#if defined(__x86_64__)
-	memcpy(&fpr.fxstate.fx_xmm[8], &xmm[8], sizeof(*xmm));
-	memcpy(&fpr.fxstate.fx_xmm[9], &xmm[9], sizeof(*xmm));
-	memcpy(&fpr.fxstate.fx_xmm[10], &xmm[10], sizeof(*xmm));
-	memcpy(&fpr.fxstate.fx_xmm[11], &xmm[11], sizeof(*xmm));
-	memcpy(&fpr.fxstate.fx_xmm[12], &xmm[12], sizeof(*xmm));
-	memcpy(&fpr.fxstate.fx_xmm[13], &xmm[13], sizeof(*xmm));
-	memcpy(&fpr.fxstate.fx_xmm[14], &xmm[14], sizeof(*xmm));
-	memcpy(&fpr.fxstate.fx_xmm[15], &xmm[15], sizeof(*xmm));
-#endif
-
-#if defined(__x86_64__)
-	DPRINTF("Call SETFPREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &fpr, 0) != -1);
-#else
-	DPRINTF("Call SETXMMREGS for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_SETXMMREGS, child, &fpr, 0) != -1);
-#endif
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(x86_xstate_mm_read);
-ATF_TC_HEAD(x86_xstate_mm_read, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set MMX (mm0..mm7) reg values from debugged program and read "
-		"them via PT_GETXSTATE, comparing values against expected.");
-}
-
-ATF_TC_BODY(x86_xstate_mm_read, tc)
-{
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct iovec iov;
-	struct xstate xst;
-
-	const uint64_t mm[] = {
-		0x0001020304050607,
-		0x1011121314151617,
-		0x2021222324252627,
-		0x3031323334353637,
-		0x4041424344454647,
-		0x5051525354555657,
-		0x6061626364656667,
-		0x7071727374757677,
-	};
-
-	/* verify whether MMX is supported here */
-	DPRINTF("Before invoking cpuid\n");
-	{
-		unsigned int eax, ebx, ecx, edx;
-		if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
-			atf_tc_skip("CPUID is not supported by the CPU");
-
-		DPRINTF("cpuid: EDX = %08x\n", edx);
-
-		if (!(edx & bit_MMX))
-			atf_tc_skip("MMX is not supported by the CPU");
-	}
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-		set_mm_regs(mm);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	iov.iov_base = &xst;
-	iov.iov_len = sizeof(xst);
-
-	DPRINTF("Call GETXSTATE for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETXSTATE, child, &iov, 0) != -1);
-
-	ATF_REQUIRE(xst.xs_rfbm & XCR0_X87);
-	ATF_REQUIRE(xst.xs_xstate_bv & XCR0_X87);
-
-	ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[0].r.f87_mantissa, mm[0]);
-	ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[1].r.f87_mantissa, mm[1]);
-	ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[2].r.f87_mantissa, mm[2]);
-	ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[3].r.f87_mantissa, mm[3]);
-	ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[4].r.f87_mantissa, mm[4]);
-	ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[5].r.f87_mantissa, mm[5]);
-	ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[6].r.f87_mantissa, mm[6]);
-	ATF_CHECK_EQ(xst.xs_fxsave.fx_87_ac[7].r.f87_mantissa, mm[7]);
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(x86_xstate_mm_write);
-ATF_TC_HEAD(x86_xstate_mm_write, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set mm0..mm7 reg values into a debugged program via "
-		"PT_SETXSTATE and compare the result against expected.");
-}
-
-ATF_TC_BODY(x86_xstate_mm_write, tc)
-{
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct iovec iov;
-	struct xstate xst;
-
-	const uint64_t mm[] = {
-		0x0001020304050607,
-		0x1011121314151617,
-		0x2021222324252627,
-		0x3031323334353637,
-		0x4041424344454647,
-		0x5051525354555657,
-		0x6061626364656667,
-		0x7071727374757677,
-	};
-
-	/* verify whether MMX is supported here */
-	DPRINTF("Before invoking cpuid\n");
-	{
-		unsigned int eax, ebx, ecx, edx;
-		if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
-			atf_tc_skip("CPUID is not supported by the CPU");
-
-		DPRINTF("cpuid: EDX = %08x\n", edx);
-
-		if (!(edx & bit_MMX))
-			atf_tc_skip("MMX is not supported by the CPU");
-	}
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		uint64_t v_mm[8];
-
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-		get_mm_regs(v_mm);
-
-		DPRINTF("Before comparing results\n");
-		FORKEE_ASSERT_EQ(v_mm[0], mm[0]);
-		FORKEE_ASSERT_EQ(v_mm[1], mm[1]);
-		FORKEE_ASSERT_EQ(v_mm[2], mm[2]);
-		FORKEE_ASSERT_EQ(v_mm[3], mm[3]);
-		FORKEE_ASSERT_EQ(v_mm[4], mm[4]);
-		FORKEE_ASSERT_EQ(v_mm[5], mm[5]);
-		FORKEE_ASSERT_EQ(v_mm[6], mm[6]);
-		FORKEE_ASSERT_EQ(v_mm[7], mm[7]);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	iov.iov_base = &xst;
-	iov.iov_len = sizeof(xst);
-
-	DPRINTF("Call GETXSTATE for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETXSTATE, child, &iov, 0) != -1);
-
-	ATF_REQUIRE(xst.xs_rfbm & XCR0_X87);
-
-	xst.xs_rfbm = XCR0_X87;
-	xst.xs_xstate_bv = XCR0_X87;
-
-	xst.xs_fxsave.fx_87_ac[0].r.f87_mantissa = mm[0];
-	xst.xs_fxsave.fx_87_ac[1].r.f87_mantissa = mm[1];
-	xst.xs_fxsave.fx_87_ac[2].r.f87_mantissa = mm[2];
-	xst.xs_fxsave.fx_87_ac[3].r.f87_mantissa = mm[3];
-	xst.xs_fxsave.fx_87_ac[4].r.f87_mantissa = mm[4];
-	xst.xs_fxsave.fx_87_ac[5].r.f87_mantissa = mm[5];
-	xst.xs_fxsave.fx_87_ac[6].r.f87_mantissa = mm[6];
-	xst.xs_fxsave.fx_87_ac[7].r.f87_mantissa = mm[7];
-
-	DPRINTF("Call SETXSTATE for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_SETXSTATE, child, &iov, 0) != -1);
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(x86_xstate_xmm_read);
-ATF_TC_HEAD(x86_xstate_xmm_read, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set xmm0..xmm15 (..xmm7 on i386) reg values from debugged program "
-		"and read them via PT_GETXSTATE, comparing values against expected.");
-}
-
-ATF_TC_BODY(x86_xstate_xmm_read, tc)
-{
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct xstate xst;
-	struct iovec iov;
-
-	const struct {
-		uint64_t a, b;
-	} xmm[] __aligned(16) = {
-		{ 0x0706050403020100, 0x0F0E0D0C0B0A0908, },
-		{ 0x0807060504030201, 0x100F0E0D0C0B0A09, },
-		{ 0x0908070605040302, 0x11100F0E0D0C0B0A, },
-		{ 0x0A09080706050403, 0x1211100F0E0D0C0B, },
-		{ 0x0B0A090807060504, 0x131211100F0E0D0C, },
-		{ 0x0C0B0A0908070605, 0x14131211100F0E0D, },
-		{ 0x0D0C0B0A09080706, 0x1514131211100F0E, },
-		{ 0x0E0D0C0B0A090807, 0x161514131211100F, },
-#if defined(__x86_64__)
-		{ 0x0F0E0D0C0B0A0908, 0x1716151413121110, },
-		{ 0x100F0E0D0C0B0A09, 0x1817161514131211, },
-		{ 0x11100F0E0D0C0B0A, 0x1918171615141312, },
-		{ 0x1211100F0E0D0C0B, 0x1A19181716151413, },
-		{ 0x131211100F0E0D0C, 0x1B1A191817161514, },
-		{ 0x14131211100F0E0D, 0x1C1B1A1918171615, },
-		{ 0x1514131211100F0E, 0x1D1C1B1A19181716, },
-		{ 0x161514131211100F, 0x1E1D1C1B1A191817, },
-#endif
-	};
-
-	/* verify whether SSE is supported here */
-	DPRINTF("Before invoking cpuid\n");
-	{
-		unsigned int eax, ebx, ecx, edx;
-		if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
-			atf_tc_skip("CPUID is not supported by the CPU");
-
-		DPRINTF("cpuid: EDX = %08x\n", edx);
-
-		if (!(edx & bit_SSE))
-			atf_tc_skip("SSE is not supported by the CPU");
-	}
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-		set_xmm_regs(xmm);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	iov.iov_base = &xst;
-	iov.iov_len = sizeof(xst);
-
-	DPRINTF("Call GETXSTATE for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETXSTATE, child, &iov, 0) != -1);
-
-	ATF_REQUIRE(xst.xs_rfbm & XCR0_SSE);
-	ATF_REQUIRE(xst.xs_xstate_bv & XCR0_SSE);
-
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[0], &xmm[0], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[1], &xmm[1], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[2], &xmm[2], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[3], &xmm[3], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[4], &xmm[4], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[5], &xmm[5], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[6], &xmm[6], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[7], &xmm[7], sizeof(*xmm)));
-#if defined(__x86_64__)
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[8], &xmm[8], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[9], &xmm[9], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[10], &xmm[10], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[11], &xmm[11], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[12], &xmm[12], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[13], &xmm[13], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[14], &xmm[14], sizeof(*xmm)));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[15], &xmm[15], sizeof(*xmm)));
-#endif
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
-}
-
-ATF_TC(x86_xstate_xmm_write);
-ATF_TC_HEAD(x86_xstate_xmm_write, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set xmm0..xmm15 (..xmm7 on i386) reg values into a debugged "
-		"program via PT_SETXSTATE and compare the result against expected.");
-}
-
-ATF_TC_BODY(x86_xstate_xmm_write, tc)
-{
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct xstate xst;
-	struct iovec iov;
-
-	const struct {
-		uint64_t a, b;
-	} xmm[] __aligned(16) = {
-		{ 0x0706050403020100, 0x0F0E0D0C0B0A0908, },
-		{ 0x0807060504030201, 0x100F0E0D0C0B0A09, },
-		{ 0x0908070605040302, 0x11100F0E0D0C0B0A, },
-		{ 0x0A09080706050403, 0x1211100F0E0D0C0B, },
-		{ 0x0B0A090807060504, 0x131211100F0E0D0C, },
-		{ 0x0C0B0A0908070605, 0x14131211100F0E0D, },
-		{ 0x0D0C0B0A09080706, 0x1514131211100F0E, },
-		{ 0x0E0D0C0B0A090807, 0x161514131211100F, },
-#if defined(__x86_64__)
-		{ 0x0F0E0D0C0B0A0908, 0x1716151413121110, },
-		{ 0x100F0E0D0C0B0A09, 0x1817161514131211, },
-		{ 0x11100F0E0D0C0B0A, 0x1918171615141312, },
-		{ 0x1211100F0E0D0C0B, 0x1A19181716151413, },
-		{ 0x131211100F0E0D0C, 0x1B1A191817161514, },
-		{ 0x14131211100F0E0D, 0x1C1B1A1918171615, },
-		{ 0x1514131211100F0E, 0x1D1C1B1A19181716, },
-		{ 0x161514131211100F, 0x1E1D1C1B1A191817, },
-#endif
-	};
-
-	/* verify whether SSE is supported here */
-	DPRINTF("Before invoking cpuid\n");
-	{
-		unsigned int eax, ebx, ecx, edx;
-		if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
-			atf_tc_skip("CPUID is not supported by the CPU");
-
-		DPRINTF("cpuid: EDX = %08x\n", edx);
-
-		if (!(edx & bit_SSE))
-			atf_tc_skip("SSE is not supported by the CPU");
-	}
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		struct {
-			uint64_t a, b;
-		} v_xmm[16] __aligned(16);
-
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-		get_xmm_regs(v_xmm);
-
-		DPRINTF("Before comparing results\n");
-		FORKEE_ASSERT(!memcmp(&v_xmm[0], &xmm[0], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[1], &xmm[1], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[2], &xmm[2], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[3], &xmm[3], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[4], &xmm[4], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[5], &xmm[5], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[6], &xmm[6], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[7], &xmm[7], sizeof(*xmm)));
-#if defined(__x86_64__)
-		FORKEE_ASSERT(!memcmp(&v_xmm[8], &xmm[8], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[9], &xmm[9], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[10], &xmm[10], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[11], &xmm[11], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[12], &xmm[12], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[13], &xmm[13], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[14], &xmm[14], sizeof(*xmm)));
-		FORKEE_ASSERT(!memcmp(&v_xmm[15], &xmm[15], sizeof(*xmm)));
-#endif
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	iov.iov_base = &xst;
-	iov.iov_len = sizeof(xst);
-
-	DPRINTF("Call GETXSTATE for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETXSTATE, child, &iov, 0) != -1);
-
-	ATF_REQUIRE(xst.xs_rfbm & XCR0_SSE);
-
-	xst.xs_rfbm = XCR0_SSE;
-	xst.xs_xstate_bv = XCR0_SSE;
-
-	memcpy(&xst.xs_fxsave.fx_xmm[0], &xmm[0], sizeof(*xmm));
-	memcpy(&xst.xs_fxsave.fx_xmm[1], &xmm[1], sizeof(*xmm));
-	memcpy(&xst.xs_fxsave.fx_xmm[2], &xmm[2], sizeof(*xmm));
-	memcpy(&xst.xs_fxsave.fx_xmm[3], &xmm[3], sizeof(*xmm));
-	memcpy(&xst.xs_fxsave.fx_xmm[4], &xmm[4], sizeof(*xmm));
-	memcpy(&xst.xs_fxsave.fx_xmm[5], &xmm[5], sizeof(*xmm));
-	memcpy(&xst.xs_fxsave.fx_xmm[6], &xmm[6], sizeof(*xmm));
-	memcpy(&xst.xs_fxsave.fx_xmm[7], &xmm[7], sizeof(*xmm));
-#if defined(__x86_64__)
-	memcpy(&xst.xs_fxsave.fx_xmm[8], &xmm[8], sizeof(*xmm));
-	memcpy(&xst.xs_fxsave.fx_xmm[9], &xmm[9], sizeof(*xmm));
-	memcpy(&xst.xs_fxsave.fx_xmm[10], &xmm[10], sizeof(*xmm));
-	memcpy(&xst.xs_fxsave.fx_xmm[11], &xmm[11], sizeof(*xmm));
-	memcpy(&xst.xs_fxsave.fx_xmm[12], &xmm[12], sizeof(*xmm));
-	memcpy(&xst.xs_fxsave.fx_xmm[13], &xmm[13], sizeof(*xmm));
-	memcpy(&xst.xs_fxsave.fx_xmm[14], &xmm[14], sizeof(*xmm));
-	memcpy(&xst.xs_fxsave.fx_xmm[15], &xmm[15], sizeof(*xmm));
+	__asm__ __volatile__(
+		"movq    0x00(%0), %%r8\n\t"
+		"movq    0x20(%0), %%r9\n\t"
+		"movq    0x40(%0), %%r10\n\t"
+		"movq    0x60(%0), %%r11\n\t"
+		"movq    0x80(%0), %%r12\n\t"
+		"movq    0xA0(%0), %%r13\n\t"
+		"movq    0xC0(%0), %%r14\n\t"
+		"movq    0xE0(%0), %%r15\n\t"
+		"int3\n\t"
+		:
+		: "b"(data)
+		: "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
+	);
+#else
+	__unreachable();
 #endif
+}
 
-	DPRINTF("Call SETXSTATE for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_SETXSTATE, child, &iov, 0) != -1);
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
+__attribute__((target("mmx")))
+static __inline void get_mm_regs(union x86_test_register out[])
+{
+	const uint64_t fill = 0x0F0F0F0F0F0F0F0F;
 
-	validate_status_exited(status, exitval);
+	__asm__ __volatile__(
+		/* fill registers with clobber pattern */
+		"movq    %1, %%mm0\n\t"
+		"movq    %1, %%mm1\n\t"
+		"movq    %1, %%mm2\n\t"
+		"movq    %1, %%mm3\n\t"
+		"movq    %1, %%mm4\n\t"
+		"movq    %1, %%mm5\n\t"
+		"movq    %1, %%mm6\n\t"
+		"movq    %1, %%mm7\n\t"
+		"\n\t"
+		"int3\n\t"
+		"\n\t"
+		"movq    %%mm0, 0x00(%0)\n\t"
+		"movq    %%mm1, 0x20(%0)\n\t"
+		"movq    %%mm2, 0x40(%0)\n\t"
+		"movq    %%mm3, 0x60(%0)\n\t"
+		"movq    %%mm4, 0x80(%0)\n\t"
+		"movq    %%mm5, 0xA0(%0)\n\t"
+		"movq    %%mm6, 0xC0(%0)\n\t"
+		"movq    %%mm7, 0xE0(%0)\n\t"
+		:
+		: "a"(out), "m"(fill)
+		: "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
+	);
+}
 
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
+__attribute__((target("mmx")))
+static __inline void set_mm_regs(const union x86_test_register data[])
+{
+	__asm__ __volatile__(
+		"movq    0x00(%0), %%mm0\n\t"
+		"movq    0x20(%0), %%mm1\n\t"
+		"movq    0x40(%0), %%mm2\n\t"
+		"movq    0x60(%0), %%mm3\n\t"
+		"movq    0x80(%0), %%mm4\n\t"
+		"movq    0xA0(%0), %%mm5\n\t"
+		"movq    0xC0(%0), %%mm6\n\t"
+		"movq    0xE0(%0), %%mm7\n\t"
+		"int3\n\t"
+		:
+		: "b"(data)
+		: "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"
+	);
 }
 
-__attribute__((target("avx")))
-static __inline void set_ymm_regs(const void* ymm)
+__attribute__((target("sse")))
+static __inline void get_xmm_regs(union x86_test_register out[])
 {
+	union x86_test_register fill __aligned(32) = {
+		.xmm={ 0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F }
+	};
+
 	__asm__ __volatile__(
-		"vmovaps  0x000(%0), %%ymm0\n\t"
-		"vmovaps  0x020(%0), %%ymm1\n\t"
-		"vmovaps  0x040(%0), %%ymm2\n\t"
-		"vmovaps  0x060(%0), %%ymm3\n\t"
-		"vmovaps  0x080(%0), %%ymm4\n\t"
-		"vmovaps  0x0A0(%0), %%ymm5\n\t"
-		"vmovaps  0x0C0(%0), %%ymm6\n\t"
-		"vmovaps  0x0E0(%0), %%ymm7\n\t"
+		/* fill registers with clobber pattern */
+		"movaps  %1, %%xmm0\n\t"
+		"movaps  %1, %%xmm1\n\t"
+		"movaps  %1, %%xmm2\n\t"
+		"movaps  %1, %%xmm3\n\t"
+		"movaps  %1, %%xmm4\n\t"
+		"movaps  %1, %%xmm5\n\t"
+		"movaps  %1, %%xmm6\n\t"
+		"movaps  %1, %%xmm7\n\t"
 #if defined(__x86_64__)
-		"vmovaps  0x100(%0), %%ymm8\n\t"
-		"vmovaps  0x120(%0), %%ymm9\n\t"
-		"vmovaps  0x140(%0), %%ymm10\n\t"
-		"vmovaps  0x160(%0), %%ymm11\n\t"
-		"vmovaps  0x180(%0), %%ymm12\n\t"
-		"vmovaps  0x1A0(%0), %%ymm13\n\t"
-		"vmovaps  0x1C0(%0), %%ymm14\n\t"
-		"vmovaps  0x1E0(%0), %%ymm15\n\t"
+		"movaps  %1, %%xmm8\n\t"
+		"movaps  %1, %%xmm9\n\t"
+		"movaps  %1, %%xmm10\n\t"
+		"movaps  %1, %%xmm11\n\t"
+		"movaps  %1, %%xmm12\n\t"
+		"movaps  %1, %%xmm13\n\t"
+		"movaps  %1, %%xmm14\n\t"
+		"movaps  %1, %%xmm15\n\t"
 #endif
+		"\n\t"
 		"int3\n\t"
+		"\n\t"
+		"movaps  %%xmm0, 0x000(%0)\n\t"
+		"movaps  %%xmm1, 0x020(%0)\n\t"
+		"movaps  %%xmm2, 0x040(%0)\n\t"
+		"movaps  %%xmm3, 0x060(%0)\n\t"
+		"movaps  %%xmm4, 0x080(%0)\n\t"
+		"movaps  %%xmm5, 0x0A0(%0)\n\t"
+		"movaps  %%xmm6, 0x0C0(%0)\n\t"
+		"movaps  %%xmm7, 0x0E0(%0)\n\t"
+#if defined(__x86_64__)
+		"movaps  %%xmm8, 0x100(%0)\n\t"
+		"movaps  %%xmm9, 0x120(%0)\n\t"
+		"movaps  %%xmm10, 0x140(%0)\n\t"
+		"movaps  %%xmm11, 0x160(%0)\n\t"
+		"movaps  %%xmm12, 0x180(%0)\n\t"
+		"movaps  %%xmm13, 0x1A0(%0)\n\t"
+		"movaps  %%xmm14, 0x1C0(%0)\n\t"
+		"movaps  %%xmm15, 0x1E0(%0)\n\t"
+#endif
 		:
-		: "b"(ymm)
-		: "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6",
-		"%ymm7"
+		: "a"(out), "m"(fill)
+		: "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7"
 #if defined(__x86_64__)
-		, "%ymm8", "%ymm9", "%ymm10", "%ymm11", "%ymm12", "%ymm13",
-		"%ymm14", "%ymm15"
+		, "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14",
+		"%xmm15"
 #endif
 	);
 }
 
-ATF_TC(x86_xstate_ymm_read);
-ATF_TC_HEAD(x86_xstate_ymm_read, tc)
-{
-	atf_tc_set_md_var(tc, "descr",
-		"Set ymm0..ymm15 (..ymm7 on i386) reg values from debugged program "
-		"and read them via PT_GETXSTATE, comparing values against expected.");
-}
-
-ATF_TC_BODY(x86_xstate_ymm_read, tc)
+__attribute__((target("sse")))
+static __inline void set_xmm_regs(const union x86_test_register data[])
 {
-	const int exitval = 5;
-	pid_t child, wpid;
-#if defined(TWAIT_HAVE_STATUS)
-	const int sigval = SIGTRAP;
-	int status;
-#endif
-	struct xstate xst;
-	struct iovec iov;
-
-	const struct {
-		uint64_t a, b, c, d;
-	} ymm[] __aligned(32) = {
-		{ 0x0706050403020100, 0x0F0E0D0C0B0A0908,
-		  0x1716151413121110, 0x1F1E1D1C1B1A1918, },
-		{ 0x0807060504030201, 0x100F0E0D0C0B0A09,
-		  0x1817161514131211, 0x201F1E1D1C1B1A19, },
-		{ 0x0908070605040302, 0x11100F0E0D0C0B0A,
-		  0x1918171615141312, 0x21201F1E1D1C1B1A, },
-		{ 0x0A09080706050403, 0x1211100F0E0D0C0B,
-		  0x1A19181716151413, 0x2221201F1E1D1C1B, },
-		{ 0x0B0A090807060504, 0x131211100F0E0D0C,
-		  0x1B1A191817161514, 0x232221201F1E1D1C, },
-		{ 0x0C0B0A0908070605, 0x14131211100F0E0D,
-		  0x1C1B1A1918171615, 0x24232221201F1E1D, },
-		{ 0x0D0C0B0A09080706, 0x1514131211100F0E,
-		  0x1D1C1B1A19181716, 0x2524232221201F1E, },
-		{ 0x0E0D0C0B0A090807, 0x161514131211100F,
-		  0x1E1D1C1B1A191817, 0x262524232221201F, },
+	__asm__ __volatile__(
+		"movaps   0x000(%0), %%xmm0\n\t"
+		"movaps   0x020(%0), %%xmm1\n\t"
+		"movaps   0x040(%0), %%xmm2\n\t"
+		"movaps   0x060(%0), %%xmm3\n\t"
+		"movaps   0x080(%0), %%xmm4\n\t"
+		"movaps   0x0A0(%0), %%xmm5\n\t"
+		"movaps   0x0C0(%0), %%xmm6\n\t"
+		"movaps   0x0E0(%0), %%xmm7\n\t"
 #if defined(__x86_64__)
-		{ 0x0F0E0D0C0B0A0908, 0x1716151413121110,
-		  0x1F1E1D1C1B1A1918, 0x2726252423222120, },
-		{ 0x100F0E0D0C0B0A09, 0x1817161514131211,
-		  0x201F1E1D1C1B1A19, 0x2827262524232221, },
-		{ 0x11100F0E0D0C0B0A, 0x1918171615141312,
-		  0x21201F1E1D1C1B1A, 0x2928272625242322, },
-		{ 0x1211100F0E0D0C0B, 0x1A19181716151413,
-		  0x2221201F1E1D1C1B, 0x2A29282726252423, },
-		{ 0x131211100F0E0D0C, 0x1B1A191817161514,
-		  0x232221201F1E1D1C, 0x2B2A292827262524, },
-		{ 0x14131211100F0E0D, 0x1C1B1A1918171615,
-		  0x24232221201F1E1D, 0x2C2B2A2928272625, },
-		{ 0x1514131211100F0E, 0x1D1C1B1A19181716,
-		  0x2524232221201F1E, 0x2D2C2B2A29282726, },
-		{ 0x161514131211100F, 0x1E1D1C1B1A191817,
-		  0x262524232221201F, 0x2E2D2C2B2A292827, },
+		"movaps   0x100(%0), %%xmm8\n\t"
+		"movaps   0x120(%0), %%xmm9\n\t"
+		"movaps   0x140(%0), %%xmm10\n\t"
+		"movaps   0x160(%0), %%xmm11\n\t"
+		"movaps   0x180(%0), %%xmm12\n\t"
+		"movaps   0x1A0(%0), %%xmm13\n\t"
+		"movaps   0x1C0(%0), %%xmm14\n\t"
+		"movaps   0x1E0(%0), %%xmm15\n\t"
 #endif
-	};
-
-	/* verify whether AVX is supported here */
-	DPRINTF("Before invoking cpuid\n");
-	{
-		unsigned int eax, ebx, ecx, edx;
-		if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
-			atf_tc_skip("CPUID is not supported by the CPU");
-
-		DPRINTF("cpuid: ECX = %08x\n", ecx);
-
-		if (!(ecx & bit_AVX))
-			atf_tc_skip("AVX is not supported by the CPU");
-	}
-
-	DPRINTF("Before forking process PID=%d\n", getpid());
-	SYSCALL_REQUIRE((child = fork()) != -1);
-	if (child == 0) {
-		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
-		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
-		DPRINTF("Before running assembly from child\n");
-		set_ymm_regs(ymm);
-
-		DPRINTF("Before exiting of the child process\n");
-		_exit(exitval);
-	}
-	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_stopped(status, sigval);
-
-	iov.iov_base = &xst;
-	iov.iov_len = sizeof(xst);
-
-	DPRINTF("Call GETXSTATE for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETXSTATE, child, &iov, 0) != -1);
-
-	ATF_REQUIRE(xst.xs_rfbm & XCR0_SSE);
-	ATF_REQUIRE(xst.xs_rfbm & XCR0_YMM_Hi128);
-	ATF_REQUIRE(xst.xs_xstate_bv & XCR0_SSE);
-	ATF_REQUIRE(xst.xs_xstate_bv & XCR0_YMM_Hi128);
-
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[0], &ymm[0].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[0], &ymm[0].c, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[1], &ymm[1].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[1], &ymm[1].c, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[2], &ymm[2].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[2], &ymm[2].c, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[3], &ymm[3].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[3], &ymm[3].c, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[4], &ymm[4].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[4], &ymm[4].c, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[5], &ymm[5].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[5], &ymm[5].c, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[6], &ymm[6].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[6], &ymm[6].c, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[7], &ymm[7].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[7], &ymm[7].c, sizeof(*ymm)/2));
+		"int3\n\t"
+		:
+		: "b"(data)
+		: "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6",
+		"%xmm7"
 #if defined(__x86_64__)
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[8], &ymm[8].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[8], &ymm[8].c, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[9], &ymm[9].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[9], &ymm[9].c, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[10], &ymm[10].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[10], &ymm[10].c, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[11], &ymm[11].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[11], &ymm[11].c, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[12], &ymm[12].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[12], &ymm[12].c, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[13], &ymm[13].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[13], &ymm[13].c, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[14], &ymm[14].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[14], &ymm[14].c, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_fxsave.fx_xmm[15], &ymm[15].a, sizeof(*ymm)/2));
-	ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[15], &ymm[15].c, sizeof(*ymm)/2));
+		, "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13",
+		"%xmm14", "%xmm15"
 #endif
-
-	DPRINTF("Before resuming the child process where it left off and "
-	    "without signal to be sent\n");
-	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
-
-	validate_status_exited(status, exitval);
-
-	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
-	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
+	);
 }
 
 __attribute__((target("avx")))
-static __inline void get_ymm_regs(void* v_ymm)
+static __inline void get_ymm_regs(union x86_test_register out[])
 {
-	const struct {
-		uint64_t a, b, c, d;
-	} fill __aligned(32) = {
-		0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F,
-		0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F
+	union x86_test_register fill __aligned(32) = {
+		{ 0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F,
+		  0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F }
 	};
 
 	__asm__ __volatile__(
@@ -3500,7 +2627,7 @@ static __inline void get_ymm_regs(void* v_ymm)
 		"vmovaps %%ymm15, 0x1E0(%0)\n\t"
 #endif
 		:
-		: "a"(v_ymm), "m"(fill)
+		: "a"(out), "m"(fill)
 		: "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6", "%ymm7"
 #if defined(__x86_64__)
 		, "%ymm8", "%ymm9", "%ymm10", "%ymm11", "%ymm12", "%ymm13", "%ymm14",
@@ -3509,109 +2636,328 @@ static __inline void get_ymm_regs(void* v_ymm)
 	);
 }
 
-ATF_TC(x86_xstate_ymm_write);
-ATF_TC_HEAD(x86_xstate_ymm_write, tc)
+__attribute__((target("avx")))
+static __inline void set_ymm_regs(const union x86_test_register data[])
 {
-	atf_tc_set_md_var(tc, "descr",
-		"Set ymm0..ymm15 (..ymm7 on i386) reg values into a debugged "
-		"program via PT_SETXSTATE and compare the result against expected.");
+	__asm__ __volatile__(
+		"vmovaps  0x000(%0), %%ymm0\n\t"
+		"vmovaps  0x020(%0), %%ymm1\n\t"
+		"vmovaps  0x040(%0), %%ymm2\n\t"
+		"vmovaps  0x060(%0), %%ymm3\n\t"
+		"vmovaps  0x080(%0), %%ymm4\n\t"
+		"vmovaps  0x0A0(%0), %%ymm5\n\t"
+		"vmovaps  0x0C0(%0), %%ymm6\n\t"
+		"vmovaps  0x0E0(%0), %%ymm7\n\t"
+#if defined(__x86_64__)
+		"vmovaps  0x100(%0), %%ymm8\n\t"
+		"vmovaps  0x120(%0), %%ymm9\n\t"
+		"vmovaps  0x140(%0), %%ymm10\n\t"
+		"vmovaps  0x160(%0), %%ymm11\n\t"
+		"vmovaps  0x180(%0), %%ymm12\n\t"
+		"vmovaps  0x1A0(%0), %%ymm13\n\t"
+		"vmovaps  0x1C0(%0), %%ymm14\n\t"
+		"vmovaps  0x1E0(%0), %%ymm15\n\t"
+#endif
+		"int3\n\t"
+		:
+		: "b"(data)
+		: "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6",
+		"%ymm7"
+#if defined(__x86_64__)
+		, "%ymm8", "%ymm9", "%ymm10", "%ymm11", "%ymm12", "%ymm13",
+		"%ymm14", "%ymm15"
+#endif
+	);
 }
 
-ATF_TC_BODY(x86_xstate_ymm_write, tc)
+static void
+x86_register_test(enum x86_test_regset regset, enum x86_test_registers regs,
+    enum x86_test_regmode regmode)
 {
 	const int exitval = 5;
 	pid_t child, wpid;
 #if defined(TWAIT_HAVE_STATUS)
 	const int sigval = SIGTRAP;
 	int status;
+#endif
+	struct reg gpr;
+	struct fpreg fpr;
+#if defined(__i386__)
+	struct xmmregs xmm;
 #endif
 	struct xstate xst;
 	struct iovec iov;
+	struct fxsave* fxs;
+	uint64_t xst_flags = 0;
+
+	const union x86_test_register expected[] __aligned(32) = {
+		{{ 0x0706050403020100, 0x0F0E0D0C0B0A0908,
+		   0x1716151413121110, 0x1F1E1D1C1B1A1918, }},
+		{{ 0x0807060504030201, 0x100F0E0D0C0B0A09,
+		   0x1817161514131211, 0x201F1E1D1C1B1A19, }},
+		{{ 0x0908070605040302, 0x11100F0E0D0C0B0A,
+		   0x1918171615141312, 0x21201F1E1D1C1B1A, }},
+		{{ 0x0A09080706050403, 0x1211100F0E0D0C0B,
+		   0x1A19181716151413, 0x2221201F1E1D1C1B, }},
+		{{ 0x0B0A090807060504, 0x131211100F0E0D0C,
+		   0x1B1A191817161514, 0x232221201F1E1D1C, }},
+		{{ 0x0C0B0A0908070605, 0x14131211100F0E0D,
+		   0x1C1B1A1918171615, 0x24232221201F1E1D, }},
+		{{ 0x0D0C0B0A09080706, 0x1514131211100F0E,
+		   0x1D1C1B1A19181716, 0x2524232221201F1E, }},
+		{{ 0x0E0D0C0B0A090807, 0x161514131211100F,
+		   0x1E1D1C1B1A191817, 0x262524232221201F, }},
+		{{ 0x0F0E0D0C0B0A0908, 0x1716151413121110,
+		   0x1F1E1D1C1B1A1918, 0x2726252423222120, }},
+		{{ 0x100F0E0D0C0B0A09, 0x1817161514131211,
+		   0x201F1E1D1C1B1A19, 0x2827262524232221, }},
+		{{ 0x11100F0E0D0C0B0A, 0x1918171615141312,
+		   0x21201F1E1D1C1B1A, 0x2928272625242322, }},
+		{{ 0x1211100F0E0D0C0B, 0x1A19181716151413,
+		   0x2221201F1E1D1C1B, 0x2A29282726252423, }},
+		{{ 0x131211100F0E0D0C, 0x1B1A191817161514,
+		   0x232221201F1E1D1C, 0x2B2A292827262524, }},
+		{{ 0x14131211100F0E0D, 0x1C1B1A1918171615,
+		   0x24232221201F1E1D, 0x2C2B2A2928272625, }},
+		{{ 0x1514131211100F0E, 0x1D1C1B1A19181716,
+		   0x2524232221201F1E, 0x2D2C2B2A29282726, }},
+		{{ 0x161514131211100F, 0x1E1D1C1B1A191817,
+		   0x262524232221201F, 0x2E2D2C2B2A292827, }},
+	};
 
-	const struct {
-		uint64_t a, b, c, d;
-	} ymm[] __aligned(32) = {
-		{ 0x0706050403020100, 0x0F0E0D0C0B0A0908,
-		  0x1716151413121110, 0x1F1E1D1C1B1A1918, },
-		{ 0x0807060504030201, 0x100F0E0D0C0B0A09,
-		  0x1817161514131211, 0x201F1E1D1C1B1A19, },
-		{ 0x0908070605040302, 0x11100F0E0D0C0B0A,
-		  0x1918171615141312, 0x21201F1E1D1C1B1A, },
-		{ 0x0A09080706050403, 0x1211100F0E0D0C0B,
-		  0x1A19181716151413, 0x2221201F1E1D1C1B, },
-		{ 0x0B0A090807060504, 0x131211100F0E0D0C,
-		  0x1B1A191817161514, 0x232221201F1E1D1C, },
-		{ 0x0C0B0A0908070605, 0x14131211100F0E0D,
-		  0x1C1B1A1918171615, 0x24232221201F1E1D, },
-		{ 0x0D0C0B0A09080706, 0x1514131211100F0E,
-		  0x1D1C1B1A19181716, 0x2524232221201F1E, },
-		{ 0x0E0D0C0B0A090807, 0x161514131211100F,
-		  0x1E1D1C1B1A191817, 0x262524232221201F, },
+	bool need_32 = false, need_64 = false, need_cpuid = false;
+
+	switch (regs) {
+	case GPREGS_32:
+	case GPREGS_32_EBP_ESP:
+		need_32 = true;
+		break;
+	case GPREGS_64:
+	case GPREGS_64_R8:
+		need_64 = true;
+		break;
+	case FPREGS_MM:
+	case FPREGS_XMM:
+	case FPREGS_YMM:
+		need_cpuid = true;
+		break;
+	}
+
+	if (need_32) {
 #if defined(__x86_64__)
-		{ 0x0F0E0D0C0B0A0908, 0x1716151413121110,
-		  0x1F1E1D1C1B1A1918, 0x2726252423222120, },
-		{ 0x100F0E0D0C0B0A09, 0x1817161514131211,
-		  0x201F1E1D1C1B1A19, 0x2827262524232221, },
-		{ 0x11100F0E0D0C0B0A, 0x1918171615141312,
-		  0x21201F1E1D1C1B1A, 0x2928272625242322, },
-		{ 0x1211100F0E0D0C0B, 0x1A19181716151413,
-		  0x2221201F1E1D1C1B, 0x2A29282726252423, },
-		{ 0x131211100F0E0D0C, 0x1B1A191817161514,
-		  0x232221201F1E1D1C, 0x2B2A292827262524, },
-		{ 0x14131211100F0E0D, 0x1C1B1A1918171615,
-		  0x24232221201F1E1D, 0x2C2B2A2928272625, },
-		{ 0x1514131211100F0E, 0x1D1C1B1A19181716,
-		  0x2524232221201F1E, 0x2D2C2B2A29282726, },
-		{ 0x161514131211100F, 0x1E1D1C1B1A191817,
-		  0x262524232221201F, 0x2E2D2C2B2A292827, },
+		atf_tc_skip("Test requires 32-bit mode");
 #endif
-	};
+	}
+	if (need_64) {
+#if defined(__i386__)
+		atf_tc_skip("Test requires 64-bit mode");
+#endif
+	}
 
-	/* verify whether AVX is supported here */
-	DPRINTF("Before invoking cpuid\n");
-	{
+	if (need_cpuid) {
+		/* verify whether needed instruction sets are supported here */
 		unsigned int eax, ebx, ecx, edx;
+
+		DPRINTF("Before invoking cpuid\n");
 		if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx))
 			atf_tc_skip("CPUID is not supported by the CPU");
 
-		DPRINTF("cpuid: ECX = %08x\n", ecx);
-
-		if (!(ecx & bit_AVX))
-			atf_tc_skip("AVX is not supported by the CPU");
+		DPRINTF("cpuid: ECX = %08x, EDX = %08xd\n", ecx, edx);
+
+		switch (regs) {
+		case FPREGS_YMM:
+			if (!(ecx & bit_AVX))
+				atf_tc_skip("AVX is not supported by the CPU");
+			/*FALLTHROUGH*/
+		case FPREGS_XMM:
+			if (!(edx & bit_SSE))
+				atf_tc_skip("SSE is not supported by the CPU");
+			break;
+		case FPREGS_MM:
+			if (!(edx & bit_MMX))
+				atf_tc_skip("MMX is not supported by the CPU");
+			break;
+		case GPREGS_32:
+		case GPREGS_32_EBP_ESP:
+		case GPREGS_64:
+		case GPREGS_64_R8:
+			__unreachable();
+		}
 	}
 
 	DPRINTF("Before forking process PID=%d\n", getpid());
 	SYSCALL_REQUIRE((child = fork()) != -1);
 	if (child == 0) {
-		struct {
-			uint64_t a, b, c, d;
-		} v_ymm[16] __aligned(32);
+		union x86_test_register vals[16] __aligned(32);
 
 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
 
 		DPRINTF("Before running assembly from child\n");
-		get_ymm_regs(v_ymm);
-
-		DPRINTF("Before comparing results\n");
-		FORKEE_ASSERT(!memcmp(&v_ymm[0], &ymm[0], sizeof(*ymm)));
-		FORKEE_ASSERT(!memcmp(&v_ymm[1], &ymm[1], sizeof(*ymm)));
-		FORKEE_ASSERT(!memcmp(&v_ymm[2], &ymm[2], sizeof(*ymm)));
-		FORKEE_ASSERT(!memcmp(&v_ymm[3], &ymm[3], sizeof(*ymm)));
-		FORKEE_ASSERT(!memcmp(&v_ymm[4], &ymm[4], sizeof(*ymm)));
-		FORKEE_ASSERT(!memcmp(&v_ymm[5], &ymm[5], sizeof(*ymm)));
-		FORKEE_ASSERT(!memcmp(&v_ymm[6], &ymm[6], sizeof(*ymm)));
-		FORKEE_ASSERT(!memcmp(&v_ymm[7], &ymm[7], sizeof(*ymm)));
+		switch (regmode) {
+		case TEST_GETREGS:
+			switch (regs) {
+			case GPREGS_32:
+				set_gp32_regs(expected);
+				break;
+			case GPREGS_32_EBP_ESP:
+				set_gp32_ebp_esp_regs(expected);
+				break;
+			case GPREGS_64:
+				set_gp64_regs(expected);
+				break;
+			case GPREGS_64_R8:
+				set_gp64_r8_regs(expected);
+				break;
+			case FPREGS_MM:
+				set_mm_regs(expected);
+				break;
+			case FPREGS_XMM:
+				set_xmm_regs(expected);
+				break;
+			case FPREGS_YMM:
+				set_ymm_regs(expected);
+				break;
+			}
+			break;
+		case TEST_SETREGS:
+			switch (regs) {
+			case GPREGS_32:
+				get_gp32_regs(vals);
+				break;
+			case GPREGS_32_EBP_ESP:
+				get_gp32_ebp_esp_regs(vals);
+				break;
+			case GPREGS_64:
+				get_gp64_regs(vals);
+				break;
+			case GPREGS_64_R8:
+				get_gp64_r8_regs(vals);
+				break;
+			case FPREGS_MM:
+				get_mm_regs(vals);
+				break;
+			case FPREGS_XMM:
+				get_xmm_regs(vals);
+				break;
+			case FPREGS_YMM:
+				get_ymm_regs(vals);
+				break;
+			}
+
+			DPRINTF("Before comparing results\n");
+			switch (regs) {
+			case GPREGS_32:
+				FORKEE_ASSERT(!memcmp(&vals[5].u32,
+				    &expected[5].u32, sizeof(vals->u32)));
+				FORKEE_ASSERT(!memcmp(&vals[4].u32,
+				    &expected[4].u32, sizeof(vals->u32)));
+				FORKEE_ASSERT(!memcmp(&vals[3].u32,
+				    &expected[3].u32, sizeof(vals->u32)));
+				FORKEE_ASSERT(!memcmp(&vals[2].u32,
+				    &expected[2].u32, sizeof(vals->u32)));
+				/*FALLTHROUGH*/
+			case GPREGS_32_EBP_ESP:
+				FORKEE_ASSERT(!memcmp(&vals[1].u32,
+				    &expected[1].u32, sizeof(vals->u32)));
+				FORKEE_ASSERT(!memcmp(&vals[0].u32,
+				    &expected[0].u32, sizeof(vals->u32)));
+				break;
+			case GPREGS_64:
+			case GPREGS_64_R8:
+			case FPREGS_MM:
+				FORKEE_ASSERT(!memcmp(&vals[0].u64,
+				    &expected[0].u64, sizeof(vals->u64)));
+				FORKEE_ASSERT(!memcmp(&vals[1].u64,
+				    &expected[1].u64, sizeof(vals->u64)));
+				FORKEE_ASSERT(!memcmp(&vals[2].u64,
+				    &expected[2].u64, sizeof(vals->u64)));
+				FORKEE_ASSERT(!memcmp(&vals[3].u64,
+				    &expected[3].u64, sizeof(vals->u64)));
+				FORKEE_ASSERT(!memcmp(&vals[4].u64,
+				    &expected[4].u64, sizeof(vals->u64)));
+				FORKEE_ASSERT(!memcmp(&vals[5].u64,
+				    &expected[5].u64, sizeof(vals->u64)));
+				FORKEE_ASSERT(!memcmp(&vals[6].u64,
+				    &expected[6].u64, sizeof(vals->u64)));
+				FORKEE_ASSERT(!memcmp(&vals[7].u64,
+				    &expected[7].u64, sizeof(vals->u64)));
+				break;
+			case FPREGS_XMM:
+				FORKEE_ASSERT(!memcmp(&vals[0].xmm,
+				    &expected[0].xmm, sizeof(vals->xmm)));
+				FORKEE_ASSERT(!memcmp(&vals[1].xmm,
+				    &expected[1].xmm, sizeof(vals->xmm)));
+				FORKEE_ASSERT(!memcmp(&vals[2].xmm,
+				    &expected[2].xmm, sizeof(vals->xmm)));
+				FORKEE_ASSERT(!memcmp(&vals[3].xmm,
+				    &expected[3].xmm, sizeof(vals->xmm)));
+				FORKEE_ASSERT(!memcmp(&vals[4].xmm,
+				    &expected[4].xmm, sizeof(vals->xmm)));
+				FORKEE_ASSERT(!memcmp(&vals[5].xmm,
+				    &expected[5].xmm, sizeof(vals->xmm)));
+				FORKEE_ASSERT(!memcmp(&vals[6].xmm,
+				    &expected[6].xmm, sizeof(vals->xmm)));
+				FORKEE_ASSERT(!memcmp(&vals[7].xmm,
+				    &expected[7].xmm, sizeof(vals->xmm)));
+#if defined(__x86_64__)
+				FORKEE_ASSERT(!memcmp(&vals[8].xmm,
+				    &expected[8].xmm, sizeof(vals->xmm)));
+				FORKEE_ASSERT(!memcmp(&vals[9].xmm,
+				    &expected[9].xmm, sizeof(vals->xmm)));
+				FORKEE_ASSERT(!memcmp(&vals[10].xmm,
+				    &expected[10].xmm, sizeof(vals->xmm)));
+				FORKEE_ASSERT(!memcmp(&vals[11].xmm,
+				    &expected[11].xmm, sizeof(vals->xmm)));
+				FORKEE_ASSERT(!memcmp(&vals[12].xmm,
+				    &expected[12].xmm, sizeof(vals->xmm)));
+				FORKEE_ASSERT(!memcmp(&vals[13].xmm,
+				    &expected[13].xmm, sizeof(vals->xmm)));
+				FORKEE_ASSERT(!memcmp(&vals[14].xmm,
+				    &expected[14].xmm, sizeof(vals->xmm)));
+				FORKEE_ASSERT(!memcmp(&vals[15].xmm,
+				    &expected[15].xmm, sizeof(vals->xmm)));
+#endif
+				break;
+			case FPREGS_YMM:
+				FORKEE_ASSERT(!memcmp(&vals[0].ymm,
+				    &expected[0].ymm, sizeof(vals->ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[1].ymm,
+				    &expected[1].ymm, sizeof(vals->ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[2].ymm,
+				    &expected[2].ymm, sizeof(vals->ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[3].ymm,
+				    &expected[3].ymm, sizeof(vals->ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[4].ymm,
+				    &expected[4].ymm, sizeof(vals->ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[5].ymm,
+				    &expected[5].ymm, sizeof(vals->ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[6].ymm,
+				    &expected[6].ymm, sizeof(vals->ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[7].ymm,
+				    &expected[7].ymm, sizeof(vals->ymm)));
 #if defined(__x86_64__)
-		FORKEE_ASSERT(!memcmp(&v_ymm[8], &ymm[8], sizeof(*ymm)));
-		FORKEE_ASSERT(!memcmp(&v_ymm[9], &ymm[9], sizeof(*ymm)));
-		FORKEE_ASSERT(!memcmp(&v_ymm[10], &ymm[10], sizeof(*ymm)));
-		FORKEE_ASSERT(!memcmp(&v_ymm[11], &ymm[11], sizeof(*ymm)));
-		FORKEE_ASSERT(!memcmp(&v_ymm[12], &ymm[12], sizeof(*ymm)));
-		FORKEE_ASSERT(!memcmp(&v_ymm[13], &ymm[13], sizeof(*ymm)));
-		FORKEE_ASSERT(!memcmp(&v_ymm[14], &ymm[14], sizeof(*ymm)));
-		FORKEE_ASSERT(!memcmp(&v_ymm[15], &ymm[15], sizeof(*ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[8].ymm,
+				    &expected[8].ymm, sizeof(vals->ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[9].ymm,
+				    &expected[9].ymm, sizeof(vals->ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[10].ymm,
+				    &expected[10].ymm, sizeof(vals->ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[11].ymm,
+				    &expected[11].ymm, sizeof(vals->ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[12].ymm,
+				    &expected[12].ymm, sizeof(vals->ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[13].ymm,
+				    &expected[13].ymm, sizeof(vals->ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[14].ymm,
+				    &expected[14].ymm, sizeof(vals->ymm)));
+				FORKEE_ASSERT(!memcmp(&vals[15].ymm,
+				    &expected[15].ymm, sizeof(vals->ymm)));
 #endif
+				break;
+			}
+			break;
+		}
 
 		DPRINTF("Before exiting of the child process\n");
 		_exit(exitval);
@@ -3623,55 +2969,417 @@ ATF_TC_BODY(x86_xstate_ymm_write, tc)
 
 	validate_status_stopped(status, sigval);
 
-	iov.iov_base = &xst;
-	iov.iov_len = sizeof(xst);
-
-	DPRINTF("Call GETXSTATE for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_GETXSTATE, child, &iov, 0) != -1);
-
-	ATF_REQUIRE(xst.xs_rfbm & XCR0_SSE);
-	ATF_REQUIRE(xst.xs_rfbm & XCR0_YMM_Hi128);
-
-	xst.xs_rfbm = XCR0_SSE | XCR0_YMM_Hi128;
-	xst.xs_xstate_bv = XCR0_SSE | XCR0_YMM_Hi128;
-
-	memcpy(&xst.xs_fxsave.fx_xmm[0], &ymm[0].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[0], &ymm[0].c, sizeof(*ymm)/2);
-	memcpy(&xst.xs_fxsave.fx_xmm[1], &ymm[1].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[1], &ymm[1].c, sizeof(*ymm)/2);
-	memcpy(&xst.xs_fxsave.fx_xmm[2], &ymm[2].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[2], &ymm[2].c, sizeof(*ymm)/2);
-	memcpy(&xst.xs_fxsave.fx_xmm[3], &ymm[3].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[3], &ymm[3].c, sizeof(*ymm)/2);
-	memcpy(&xst.xs_fxsave.fx_xmm[4], &ymm[4].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[4], &ymm[4].c, sizeof(*ymm)/2);
-	memcpy(&xst.xs_fxsave.fx_xmm[5], &ymm[5].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[5], &ymm[5].c, sizeof(*ymm)/2);
-	memcpy(&xst.xs_fxsave.fx_xmm[6], &ymm[6].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[6], &ymm[6].c, sizeof(*ymm)/2);
-	memcpy(&xst.xs_fxsave.fx_xmm[7], &ymm[7].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[7], &ymm[7].c, sizeof(*ymm)/2);
+	switch (regset) {
+	case TEST_GPREGS:
+		ATF_REQUIRE(regs < FPREGS_MM);
+		DPRINTF("Call GETREGS for the child process\n");
+		SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
+		break;
+	case TEST_XMMREGS:
+#if defined(__i386__)
+		ATF_REQUIRE(regs >= FPREGS_MM && regs < FPREGS_YMM);
+		DPRINTF("Call GETXMMREGS for the child process\n");
+		SYSCALL_REQUIRE(ptrace(PT_GETXMMREGS, child, &xmm, 0) != -1);
+		fxs = &xmm.fxstate;
+		break;
+#else
+		/*FALLTHROUGH*/
+#endif
+	case TEST_FPREGS:
+#if defined(__x86_64__)
+		ATF_REQUIRE(regs >= FPREGS_MM && regs < FPREGS_YMM);
+		fxs = &fpr.fxstate;
+#else
+		ATF_REQUIRE(regs >= FPREGS_MM && regs < FPREGS_XMM);
+#endif
+		DPRINTF("Call GETFPREGS for the child process\n");
+		SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1);
+		break;
+	case TEST_XSTATE:
+		ATF_REQUIRE(regs >= FPREGS_MM);
+		iov.iov_base = &xst;
+		iov.iov_len = sizeof(xst);
+
+		DPRINTF("Call GETXSTATE for the child process\n");
+		SYSCALL_REQUIRE(ptrace(PT_GETXSTATE, child, &iov, 0) != -1);
+
+		switch (regs) {
+		case FPREGS_MM:
+			xst_flags |= XCR0_X87;
+			break;
+		case FPREGS_YMM:
+			xst_flags |= XCR0_YMM_Hi128;
+			/*FALLTHROUGH*/
+		case FPREGS_XMM:
+			xst_flags |= XCR0_SSE;
+			break;
+		case GPREGS_32:
+		case GPREGS_32_EBP_ESP:
+		case GPREGS_64:
+		case GPREGS_64_R8:
+			__unreachable();
+			break;
+		}
+
+		ATF_REQUIRE((xst.xs_rfbm & xst_flags) == xst_flags);
+		switch (regmode) {
+		case TEST_SETREGS:
+			xst.xs_rfbm = xst_flags;
+			xst.xs_xstate_bv = xst_flags;
+			break;
+		case TEST_GETREGS:
+			ATF_REQUIRE((xst.xs_xstate_bv & xst_flags)
+			    == xst_flags);
+			break;
+		}
+
+		fxs = &xst.xs_fxsave;
+		break;
+	}
+
+#if defined(__x86_64__)
+#define MM_REG(n) fpr.fxstate.fx_87_ac[n].r.f87_mantissa
+#else
+#define MM_REG(n) fpr.fstate.s87_ac[n].f87_mantissa
+#endif
+
+	switch (regmode) {
+	case TEST_GETREGS:
+		switch (regs) {
+		case GPREGS_32:
+#if defined(__i386__)
+			ATF_CHECK_EQ((uint32_t)gpr.r_eax, expected[0].u32);
+			ATF_CHECK_EQ((uint32_t)gpr.r_ebx, expected[1].u32);
+			ATF_CHECK_EQ((uint32_t)gpr.r_ecx, expected[2].u32);
+			ATF_CHECK_EQ((uint32_t)gpr.r_edx, expected[3].u32);
+			ATF_CHECK_EQ((uint32_t)gpr.r_esi, expected[4].u32);
+			ATF_CHECK_EQ((uint32_t)gpr.r_edi, expected[5].u32);
+#endif
+			break;
+		case GPREGS_32_EBP_ESP:
+#if defined(__i386__)
+			ATF_CHECK_EQ((uint32_t)gpr.r_esp, expected[0].u32);
+			ATF_CHECK_EQ((uint32_t)gpr.r_ebp, expected[1].u32);
+#endif
+			break;
+		case GPREGS_64:
+#if defined(__x86_64__)
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RAX],
+			    expected[0].u64);
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RBX],
+			    expected[1].u64);
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RCX],
+			    expected[2].u64);
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RDX],
+			    expected[3].u64);
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RSI],
+			    expected[4].u64);
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RDI],
+			    expected[5].u64);
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RSP],
+			    expected[6].u64);
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_RBP],
+			    expected[7].u64);
+#endif
+			break;
+		case GPREGS_64_R8:
+#if defined(__x86_64__)
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R8],
+			    expected[0].u64);
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R9],
+			    expected[1].u64);
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R10],
+			    expected[2].u64);
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R11],
+			    expected[3].u64);
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R12],
+			    expected[4].u64);
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R13],
+			    expected[5].u64);
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R14],
+			    expected[6].u64);
+			ATF_CHECK_EQ((uint64_t)gpr.regs[_REG_R15],
+			    expected[7].u64);
+#endif
+			break;
+		case FPREGS_MM:
+			if (regset == TEST_FPREGS) {
+				ATF_CHECK_EQ(MM_REG(0), expected[0].u64);
+				ATF_CHECK_EQ(MM_REG(1), expected[1].u64);
+				ATF_CHECK_EQ(MM_REG(2), expected[2].u64);
+				ATF_CHECK_EQ(MM_REG(3), expected[3].u64);
+				ATF_CHECK_EQ(MM_REG(4), expected[4].u64);
+				ATF_CHECK_EQ(MM_REG(5), expected[5].u64);
+				ATF_CHECK_EQ(MM_REG(6), expected[6].u64);
+				ATF_CHECK_EQ(MM_REG(7), expected[7].u64);
+			} else {
+				ATF_CHECK_EQ(fxs->fx_87_ac[0].r.f87_mantissa,
+			    expected[0].u64);
+				ATF_CHECK_EQ(fxs->fx_87_ac[1].r.f87_mantissa,
+			    expected[1].u64);
+				ATF_CHECK_EQ(fxs->fx_87_ac[2].r.f87_mantissa,
+			    expected[2].u64);
+				ATF_CHECK_EQ(fxs->fx_87_ac[3].r.f87_mantissa,
+			    expected[3].u64);
+				ATF_CHECK_EQ(fxs->fx_87_ac[4].r.f87_mantissa,
+			    expected[4].u64);
+				ATF_CHECK_EQ(fxs->fx_87_ac[5].r.f87_mantissa,
+			    expected[5].u64);
+				ATF_CHECK_EQ(fxs->fx_87_ac[6].r.f87_mantissa,
+			    expected[6].u64);
+				ATF_CHECK_EQ(fxs->fx_87_ac[7].r.f87_mantissa,
+			    expected[7].u64);
+			}
+			break;
+		case FPREGS_YMM:
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[0],
+			    &expected[0].ymm.c, sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[1],
+			    &expected[1].ymm.c, sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[2],
+			    &expected[2].ymm.c, sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[3],
+			    &expected[3].ymm.c, sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[4],
+			    &expected[4].ymm.c, sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[5],
+			    &expected[5].ymm.c, sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[6],
+			    &expected[6].ymm.c, sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[7],
+			    &expected[7].ymm.c, sizeof(expected->ymm)/2));
+#if defined(__x86_64__)
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[8],
+			    &expected[8].ymm.c, sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[9],
+			    &expected[9].ymm.c, sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[10],
+			    &expected[10].ymm.c, sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[11],
+			    &expected[11].ymm.c, sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[12],
+			    &expected[12].ymm.c, sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[13],
+			    &expected[13].ymm.c, sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[14],
+			    &expected[14].ymm.c, sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&xst.xs_ymm_hi128.xs_ymm[15],
+			    &expected[15].ymm.c, sizeof(expected->ymm)/2));
+#endif
+			/*FALLTHROUGH*/
+		case FPREGS_XMM:
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[0], &expected[0].ymm.a,
+			    sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[1], &expected[1].ymm.a,
+			    sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[2], &expected[2].ymm.a,
+			    sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[3], &expected[3].ymm.a,
+			    sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[4], &expected[4].ymm.a,
+			    sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[5], &expected[5].ymm.a,
+			    sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[6], &expected[6].ymm.a,
+			    sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[7], &expected[7].ymm.a,
+			    sizeof(expected->ymm)/2));
+#if defined(__x86_64__)
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[8], &expected[8].ymm.a,
+			    sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[9], &expected[9].ymm.a,
+			    sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[10], &expected[10].ymm.a,
+			    sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[11], &expected[11].ymm.a,
+			    sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[12], &expected[12].ymm.a,
+			    sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[13], &expected[13].ymm.a,
+			    sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[14], &expected[14].ymm.a,
+			    sizeof(expected->ymm)/2));
+			ATF_CHECK(!memcmp(&fxs->fx_xmm[15], &expected[15].ymm.a,
+			    sizeof(expected->ymm)/2));
+#endif
+			break;
+		}
+		break;
+	case TEST_SETREGS:
+		switch (regs) {
+		case GPREGS_32:
+#if defined(__i386__)
+			gpr.r_eax = expected[0].u32;
+			gpr.r_ebx = expected[1].u32;
+			gpr.r_ecx = expected[2].u32;
+			gpr.r_edx = expected[3].u32;
+			gpr.r_esi = expected[4].u32;
+			gpr.r_edi = expected[5].u32;
+#endif
+			break;
+		case GPREGS_32_EBP_ESP:
+#if defined(__i386__)
+			gpr.r_esp = expected[0].u32;
+			gpr.r_ebp = expected[1].u32;
+#endif
+			break;
+		case GPREGS_64:
+#if defined(__x86_64__)
+			gpr.regs[_REG_RAX] = expected[0].u64;
+			gpr.regs[_REG_RBX] = expected[1].u64;
+			gpr.regs[_REG_RCX] = expected[2].u64;
+			gpr.regs[_REG_RDX] = expected[3].u64;
+			gpr.regs[_REG_RSI] = expected[4].u64;
+			gpr.regs[_REG_RDI] = expected[5].u64;
+			gpr.regs[_REG_RSP] = expected[6].u64;
+			gpr.regs[_REG_RBP] = expected[7].u64;
+#endif
+			break;
+		case GPREGS_64_R8:
+#if defined(__x86_64__)
+			gpr.regs[_REG_R8] = expected[0].u64;
+			gpr.regs[_REG_R9] = expected[1].u64;
+			gpr.regs[_REG_R10] = expected[2].u64;
+			gpr.regs[_REG_R11] = expected[3].u64;
+			gpr.regs[_REG_R12] = expected[4].u64;
+			gpr.regs[_REG_R13] = expected[5].u64;
+			gpr.regs[_REG_R14] = expected[6].u64;
+			gpr.regs[_REG_R15] = expected[7].u64;
+#endif
+			break;
+		case FPREGS_MM:
+			if (regset == TEST_FPREGS) {
+				MM_REG(0) = expected[0].u64;
+				MM_REG(1) = expected[1].u64;
+				MM_REG(2) = expected[2].u64;
+				MM_REG(3) = expected[3].u64;
+				MM_REG(4) = expected[4].u64;
+				MM_REG(5) = expected[5].u64;
+				MM_REG(6) = expected[6].u64;
+				MM_REG(7) = expected[7].u64;
+			} else {
+				fxs->fx_87_ac[0].r.f87_mantissa =
+				    expected[0].u64;
+				fxs->fx_87_ac[1].r.f87_mantissa =
+				    expected[1].u64;
+				fxs->fx_87_ac[2].r.f87_mantissa =
+				    expected[2].u64;
+				fxs->fx_87_ac[3].r.f87_mantissa =
+				    expected[3].u64;
+				fxs->fx_87_ac[4].r.f87_mantissa =
+				    expected[4].u64;
+				fxs->fx_87_ac[5].r.f87_mantissa =
+				    expected[5].u64;
+				fxs->fx_87_ac[6].r.f87_mantissa =
+				    expected[6].u64;
+				fxs->fx_87_ac[7].r.f87_mantissa =
+				    expected[7].u64;
+			}
+			break;
+		case FPREGS_YMM:
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[0],
+			    &expected[0].ymm.c, sizeof(expected->ymm)/2);
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[1],
+			    &expected[1].ymm.c, sizeof(expected->ymm)/2);
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[2],
+			    &expected[2].ymm.c, sizeof(expected->ymm)/2);
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[3],
+			    &expected[3].ymm.c, sizeof(expected->ymm)/2);
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[4],
+			    &expected[4].ymm.c, sizeof(expected->ymm)/2);
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[5],
+			    &expected[5].ymm.c, sizeof(expected->ymm)/2);
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[6],
+			    &expected[6].ymm.c, sizeof(expected->ymm)/2);
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[7],
+			    &expected[7].ymm.c, sizeof(expected->ymm)/2);
+#if defined(__x86_64__)
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[8],
+			    &expected[8].ymm.c, sizeof(expected->ymm)/2);
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[9],
+			    &expected[9].ymm.c, sizeof(expected->ymm)/2);
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[10],
+			    &expected[10].ymm.c, sizeof(expected->ymm)/2);
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[11],
+			    &expected[11].ymm.c, sizeof(expected->ymm)/2);
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[12],
+			    &expected[12].ymm.c, sizeof(expected->ymm)/2);
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[13],
+			    &expected[13].ymm.c, sizeof(expected->ymm)/2);
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[14],
+			    &expected[14].ymm.c, sizeof(expected->ymm)/2);
+			memcpy(&xst.xs_ymm_hi128.xs_ymm[15],
+			    &expected[15].ymm.c, sizeof(expected->ymm)/2);
+#endif
+			/*FALLTHROUGH*/
+		case FPREGS_XMM:
+			memcpy(&fxs->fx_xmm[0], &expected[0].ymm.a,
+			    sizeof(expected->ymm)/2);
+			memcpy(&fxs->fx_xmm[1], &expected[1].ymm.a,
+			    sizeof(expected->ymm)/2);
+			memcpy(&fxs->fx_xmm[2], &expected[2].ymm.a,
+			    sizeof(expected->ymm)/2);
+			memcpy(&fxs->fx_xmm[3], &expected[3].ymm.a,
+			    sizeof(expected->ymm)/2);
+			memcpy(&fxs->fx_xmm[4], &expected[4].ymm.a,
+			    sizeof(expected->ymm)/2);
+			memcpy(&fxs->fx_xmm[5], &expected[5].ymm.a,
+			    sizeof(expected->ymm)/2);
+			memcpy(&fxs->fx_xmm[6], &expected[6].ymm.a,
+			    sizeof(expected->ymm)/2);
+			memcpy(&fxs->fx_xmm[7], &expected[7].ymm.a,
+			    sizeof(expected->ymm)/2);
 #if defined(__x86_64__)
-	memcpy(&xst.xs_fxsave.fx_xmm[8], &ymm[8].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[8], &ymm[8].c, sizeof(*ymm)/2);
-	memcpy(&xst.xs_fxsave.fx_xmm[9], &ymm[9].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[9], &ymm[9].c, sizeof(*ymm)/2);
-	memcpy(&xst.xs_fxsave.fx_xmm[10], &ymm[10].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[10], &ymm[10].c, sizeof(*ymm)/2);
-	memcpy(&xst.xs_fxsave.fx_xmm[11], &ymm[11].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[11], &ymm[11].c, sizeof(*ymm)/2);
-	memcpy(&xst.xs_fxsave.fx_xmm[12], &ymm[12].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[12], &ymm[12].c, sizeof(*ymm)/2);
-	memcpy(&xst.xs_fxsave.fx_xmm[13], &ymm[13].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[13], &ymm[13].c, sizeof(*ymm)/2);
-	memcpy(&xst.xs_fxsave.fx_xmm[14], &ymm[14].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[14], &ymm[14].c, sizeof(*ymm)/2);
-	memcpy(&xst.xs_fxsave.fx_xmm[15], &ymm[15].a, sizeof(*ymm)/2);
-	memcpy(&xst.xs_ymm_hi128.xs_ymm[15], &ymm[15].c, sizeof(*ymm)/2);
+			memcpy(&fxs->fx_xmm[8], &expected[8].ymm.a,
+			    sizeof(expected->ymm)/2);
+			memcpy(&fxs->fx_xmm[9], &expected[9].ymm.a,
+			    sizeof(expected->ymm)/2);
+			memcpy(&fxs->fx_xmm[10], &expected[10].ymm.a,
+			    sizeof(expected->ymm)/2);
+			memcpy(&fxs->fx_xmm[11], &expected[11].ymm.a,
+			    sizeof(expected->ymm)/2);
+			memcpy(&fxs->fx_xmm[12], &expected[12].ymm.a,
+			    sizeof(expected->ymm)/2);
+			memcpy(&fxs->fx_xmm[13], &expected[13].ymm.a,
+			    sizeof(expected->ymm)/2);
+			memcpy(&fxs->fx_xmm[14], &expected[14].ymm.a,
+			    sizeof(expected->ymm)/2);
+			memcpy(&fxs->fx_xmm[15], &expected[15].ymm.a,
+			    sizeof(expected->ymm)/2);
+#endif
+			break;
+		}
+
+		switch (regset) {
+		case TEST_GPREGS:
+			DPRINTF("Call SETREGS for the child process\n");
+			SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0)
+			    != -1);
+			break;
+		case TEST_XMMREGS:
+#if defined(__i386__)
+			DPRINTF("Call SETXMMREGS for the child process\n");
+			SYSCALL_REQUIRE(ptrace(PT_SETXMMREGS, child, &xmm, 0)
+			    != -1);
+			break;
+#else
+			/*FALLTHROUGH*/
 #endif
+		case TEST_FPREGS:
+			DPRINTF("Call SETFPREGS for the child process\n");
+			SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &fpr, 0)
+			    != -1);
+			break;
+		case TEST_XSTATE:
+			DPRINTF("Call SETXSTATE for the child process\n");
+			SYSCALL_REQUIRE(ptrace(PT_SETXSTATE, child, &iov, 0)
+			    != -1);
+			break;
+		}
+		break;
+	}
 
-	DPRINTF("Call SETXSTATE for the child process\n");
-	SYSCALL_REQUIRE(ptrace(PT_SETXSTATE, child, &iov, 0) != -1);
+#undef MM_REG
 
 	DPRINTF("Before resuming the child process where it left off and "
 	    "without signal to be sent\n");
@@ -3686,6 +3394,75 @@ ATF_TC_BODY(x86_xstate_ymm_write, tc)
 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
 }
 
+#define X86_REGISTER_TEST(test, regset, regs, regmode, descr)		\
+ATF_TC(test);								\
+ATF_TC_HEAD(test, tc)							\
+{									\
+	atf_tc_set_md_var(tc, "descr", descr);				\
+}									\
+									\
+ATF_TC_BODY(test, tc)							\
+{									\
+	x86_register_test(regset, regs, regmode);			\
+}
+
+X86_REGISTER_TEST(x86_gpregs32_read, TEST_GPREGS, GPREGS_32, TEST_GETREGS,
+    "Test reading basic 32-bit gp registers from debugged program "
+    "via PT_GETREGS.");
+X86_REGISTER_TEST(x86_gpregs32_write, TEST_GPREGS, GPREGS_32, TEST_SETREGS,
+    "Test writing basic 32-bit gp registers into debugged program "
+    "via PT_SETREGS.");
+X86_REGISTER_TEST(x86_gpregs32_ebp_esp_read, TEST_GPREGS, GPREGS_32_EBP_ESP,
+    TEST_GETREGS, "Test reading ebp & esp registers from debugged program "
+    "via PT_GETREGS.");
+X86_REGISTER_TEST(x86_gpregs32_ebp_esp_write, TEST_GPREGS, GPREGS_32_EBP_ESP,
+    TEST_SETREGS, "Test writing ebp & esp registers into debugged program "
+    "via PT_SETREGS.");
+
+X86_REGISTER_TEST(x86_gpregs64_read, TEST_GPREGS, GPREGS_64, TEST_GETREGS,
+    "Test reading basic 64-bit gp registers from debugged program "
+    "via PT_GETREGS.");
+X86_REGISTER_TEST(x86_gpregs64_write, TEST_GPREGS, GPREGS_64, TEST_SETREGS,
+    "Test writing basic 64-bit gp registers into debugged program "
+    "via PT_SETREGS.");
+X86_REGISTER_TEST(x86_gpregs64_r8_read, TEST_GPREGS, GPREGS_64_R8, TEST_GETREGS,
+    "Test reading r8..r15 registers from debugged program via PT_GETREGS.");
+X86_REGISTER_TEST(x86_gpregs64_r8_write, TEST_GPREGS, GPREGS_64_R8,
+    TEST_SETREGS, "Test writing r8..r15 registers into debugged program "
+    "via PT_SETREGS.");
+
+X86_REGISTER_TEST(x86_fpregs_mm_read, TEST_FPREGS, FPREGS_MM, TEST_GETREGS,
+    "Test reading mm0..mm7 registers from debugged program "
+    "via PT_GETFPREGS.");
+X86_REGISTER_TEST(x86_fpregs_mm_write, TEST_FPREGS, FPREGS_MM, TEST_SETREGS,
+    "Test writing mm0..mm7 registers into debugged program "
+    "via PT_SETFPREGS.");
+X86_REGISTER_TEST(x86_fpregs_xmm_read, TEST_XMMREGS, FPREGS_XMM, TEST_GETREGS,
+    "Test reading xmm0..xmm15 (..xmm7 on i386) from debugged program "
+    "via PT_GETFPREGS (PT_GETXMMREGS on i386).");
+X86_REGISTER_TEST(x86_fpregs_xmm_write, TEST_XMMREGS, FPREGS_XMM, TEST_SETREGS,
+    "Test writing xmm0..xmm15 (..xmm7 on i386) into debugged program "
+    "via PT_SETFPREGS (PT_SETXMMREGS on i386).");
+
+X86_REGISTER_TEST(x86_xstate_mm_read, TEST_XSTATE, FPREGS_MM, TEST_GETREGS,
+    "Test reading mm0..mm7 registers from debugged program "
+    "via PT_GETXSTATE.");
+X86_REGISTER_TEST(x86_xstate_mm_write, TEST_XSTATE, FPREGS_MM, TEST_SETREGS,
+    "Test writing mm0..mm7 registers into debugged program "
+    "via PT_SETXSTATE.");
+X86_REGISTER_TEST(x86_xstate_xmm_read, TEST_XSTATE, FPREGS_XMM, TEST_GETREGS,
+    "Test reading xmm0..xmm15 (..xmm7 on i386) from debugged program "
+    "via PT_GETXSTATE.");
+X86_REGISTER_TEST(x86_xstate_xmm_write, TEST_XSTATE, FPREGS_XMM, TEST_SETREGS,
+    "Test writing xmm0..xmm15 (..xmm7 on i386) into debugged program "
+    "via PT_SETXSTATE.");
+X86_REGISTER_TEST(x86_xstate_ymm_read, TEST_XSTATE, FPREGS_YMM, TEST_GETREGS,
+    "Test reading ymm0..ymm15 (..ymm7 on i386) from debugged program "
+    "via PT_GETXSTATE.");
+X86_REGISTER_TEST(x86_xstate_ymm_write, TEST_XSTATE, FPREGS_YMM, TEST_SETREGS,
+    "Test writing ymm0..ymm15 (..ymm7 on i386) into debugged program "
+    "via PT_SETXSTATE.");
+
 /// ----------------------------------------------------------------------------
 
 #define ATF_TP_ADD_TCS_PTRACE_WAIT_X86() \
@@ -3751,10 +3528,18 @@ ATF_TC_BODY(x86_xstate_ymm_write, tc)
 	ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_dont_inherit_execve); \
 	ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_dont_inherit_execve); \
 	ATF_TP_ADD_TC_HAVE_DBREGS(tp, x86_cve_2018_8897); \
-	ATF_TP_ADD_TC_HAVE_FPREGS(tp, x86_regs_mm_read); \
-	ATF_TP_ADD_TC_HAVE_FPREGS(tp, x86_regs_mm_write); \
-	ATF_TP_ADD_TC_HAVE_FPREGS(tp, x86_regs_xmm_read); \
-	ATF_TP_ADD_TC_HAVE_FPREGS(tp, x86_regs_xmm_write); \
+	ATF_TP_ADD_TC(tp, x86_gpregs32_read); \
+	ATF_TP_ADD_TC(tp, x86_gpregs32_write); \
+	ATF_TP_ADD_TC(tp, x86_gpregs32_ebp_esp_read); \
+	ATF_TP_ADD_TC(tp, x86_gpregs32_ebp_esp_write); \
+	ATF_TP_ADD_TC(tp, x86_gpregs64_read); \
+	ATF_TP_ADD_TC(tp, x86_gpregs64_write); \
+	ATF_TP_ADD_TC(tp, x86_gpregs64_r8_read); \
+	ATF_TP_ADD_TC(tp, x86_gpregs64_r8_write); \
+	ATF_TP_ADD_TC(tp, x86_fpregs_mm_read); \
+	ATF_TP_ADD_TC(tp, x86_fpregs_mm_write); \
+	ATF_TP_ADD_TC(tp, x86_fpregs_xmm_read); \
+	ATF_TP_ADD_TC(tp, x86_fpregs_xmm_write); \
 	ATF_TP_ADD_TC(tp, x86_xstate_mm_read); \
 	ATF_TP_ADD_TC(tp, x86_xstate_mm_write); \
 	ATF_TP_ADD_TC(tp, x86_xstate_xmm_read); \
-- 
2.24.1



Home | Main Index | Thread Index | Old Index