about summary refs log tree commit diff stats
path: root/tests32/extensions
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-08-26 17:45:13 +0200
committerGitHub <noreply@github.com>2024-08-26 17:45:13 +0200
commitb5105a1e57bba3305d5dce93ab4d2f7faab6b34a (patch)
treeab26b700d3c48f2c8e32a1084ae7c2e7a8448b06 /tests32/extensions
parent9beb745765e9c99bad6410094a97bf0bf9ebc1eb (diff)
downloadbox64-b5105a1e57bba3305d5dce93ab4d2f7faab6b34a.tar.gz
box64-b5105a1e57bba3305d5dce93ab4d2f7faab6b34a.zip
Added preliminary Box32 support (#1760)
* Improve the ReserveHigMemory helper function

* [BOX32] Added some wrapping infrastructure

* [BOX32] More wrapped 32bits lib infrastructure

* [BOX32] Added callback and tls 32bits handling

* [BOX32] Added more 32bits, around wrappers and elfs

* [BOX32] Added the 32bits version of myalign

* [BOX32] More wrapped libs and 32bits fixes and imrpovments

* [BOX32] Added some 32bits tests

* [BOX32] Try to enable some Box32 build and test on the CI

* [BOX32] Disable Box32 testing on CI platform that use qemu

* [BOX32] Another attempt to disable Box32 testing on CI platform that use qemu

* [BOX32] Small fix for another attempt to disable Box32 testing on CI platform that use qemu

* [BOX32] Yet another fix for another attempt to disable Box32 testing on CI platform that use qemu

* [BOX32] Fixed a typo in CI script

* [BOX32] Better scratch alighnment and enabled more tests

* [BOX32] Added (partial) wrapped 32bits librt

* [BOX32] Added mention of Box32 in README

* [BOX32] Added phtread handling, and numerous fixes to 32bits handling. [ARM64_DYNAREC] Fixed access to segment with negative offset

* [BOX32] Added system libs and cpp testing, plus some more fixes

* [BOX32] Fix previous commit

* [BOX32] Better stack adjustment for 32bits processes

* [BOX32] Added getenv wrapped 32bits function and friends

* [BOX32] Don't look for box86 for a Box32 build

* [BOX32] Don't do 32bits cppThreads test for now on CI

* [BOX32] Enabled a few more 32bits tests

* [BOX32] For ld_lib_path for both CppThreads tests

* [BOX32] [ANDROID] Some Fixes for Android Build

* [BOX32] Still need to disable cppThread_32bits test on CI for some reason

* [BOX32] [ANDROID] Don't show PreInit Array Warning (#1751)

* [BOX32] [ANDROID] One More Fix for Android Build That I forgotten to … (#1752)

* [BOX32] [ANDROID] One More Fix for Android Build That I forgotten to push before

* [BOX32] [ANDROID] Try to Create __libc_init

* [BOX32] [ANDROID] Try to disable NEEDED_LIBS for now (libdl is not wrapped)

* [BOX32] Updated generated files

* [BOX32] Added 32bits context functions

* [BOX32] Added 32bits signal handling

* [BOX32] Added some missing 32bits elfloader functions

* [BOX32] Fix build on x86_64 machine

* [BOX32] Better fix for x86_64 build

* [BOX32] Actually added missing libs, and re-enabled cppThreads_32bits test

* [BOX32] Added wrapped 32bits libdl

* [BOX32] Try to re-enabled Box32 test on CI for ARM64 builds

* [BOX32] fine-tuning Box32 test on CI for ARM64 builds

* [BOX32] More fine-tuning to Box32 test on CI for ARM64 builds

* [BOX32] Enabled Box32 test on CI for LA64 and RV64 builds too

* [BOX32] re-Disabled Box32 test on CI for LA64 and RV64 builds, not working for now

* [BOX32] Temporarily disabled cppThreads_32bits test on CI

---------

Co-authored-by: KreitinnSoftware <pablopro5051@gmail.com>
Co-authored-by: KreitinnSoftware <80591934+KreitinnSoftware@users.noreply.github.com>
Diffstat (limited to 'tests32/extensions')
-rwxr-xr-xtests32/extensions/mmxbin0 -> 287144 bytes
-rw-r--r--tests32/extensions/mmx.c674
-rw-r--r--tests32/extensions/mmx.txt106
3 files changed, 780 insertions, 0 deletions
diff --git a/tests32/extensions/mmx b/tests32/extensions/mmx
new file mode 100755
index 00000000..65b66532
--- /dev/null
+++ b/tests32/extensions/mmx
Binary files differdiff --git a/tests32/extensions/mmx.c b/tests32/extensions/mmx.c
new file mode 100644
index 00000000..a43f9759
--- /dev/null
+++ b/tests32/extensions/mmx.c
@@ -0,0 +1,674 @@
+#include<stdint.h>
+#include<stdio.h>
+#include<stdbool.h>
+#include<limits.h>
+#include<immintrin.h>
+#include<cpuid.h>
+
+
+
+typedef uint8_t u8;
+typedef int8_t i8;
+typedef uint16_t u16;
+typedef int16_t i16;
+typedef uint32_t u32;
+typedef int32_t i32;
+typedef uint64_t u64;
+typedef int64_t i64;
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define I8_MAX  0x7F
+#define I8_MIN -0x80
+#define U8_MAX  0xFF
+#define U8_MIN  0
+
+#define I16_MAX  0x7FFF
+#define I16_MIN -0x8000
+#define U16_MAX  0xFFFF
+#define U16_MIN  0
+
+#define I32_MAX  0x7FFFFFFF
+#define I32_MIN -0x80000000
+#define U32_MAX  0xFFFFFFFF
+#define U32_MIN  0
+
+#define I64_MAX  0x7FFFFFFFFFFFFFFF
+#define I64_MIN -0x8000000000000000
+#define U64_MAX  0xFFFFFFFFFFFFFFFF
+#define U64_MIN  0
+
+#define MMX_TEST_STRUCT(sz) \
+	typedef struct mmx_##sz##_test { \
+		sz a; \
+		sz b; \
+		sz result; \
+	} mmx_##sz##_test_t
+
+MMX_TEST_STRUCT(u8);
+MMX_TEST_STRUCT(i8);
+MMX_TEST_STRUCT(u16);
+MMX_TEST_STRUCT(i16);
+MMX_TEST_STRUCT(u32);
+MMX_TEST_STRUCT(i32);
+MMX_TEST_STRUCT(u64);
+MMX_TEST_STRUCT(i64);
+
+// Binary compare two mm registers
+bool mm_raw_compare(__m64 a, __m64 b) {
+	__m64 a_upper_reg = _mm_srli_si64(a, 32);
+	__m64 b_upper_reg = _mm_srli_si64(b, 32);
+
+	int a_lower = _m_to_int(a);
+	int a_upper = _m_to_int(a_upper_reg);
+
+	int b_lower = _m_to_int(b);
+	int b_upper = _m_to_int(b_upper_reg);
+
+	return (a_lower == b_lower) && (a_upper == b_upper);
+}
+
+// Load a 64 bit value into a mm register
+__m64 mm_load64(u64 val) {
+	__m64 lower = _m_from_int(val & 0xFFFFFFFF);
+	__m64 upper = _m_from_int((val >> 32) & 0xFFFFFFFF);
+
+	__m64 shifted = _mm_slli_si64(upper, 32);
+	__m64 final = _m_por(shifted, lower);
+
+	return final;
+}
+
+#define MMX_ARITH_TEST(name, testcases, testcase_type, type, size, testfunc) \
+bool name() { \
+	printf("TEST: " #name "\n"); \
+	int errors = 0; \
+\
+	for (size_t i = 0; i < ARRAY_SIZE(testcases); i++ ) { \
+		testcase_type test_data = testcases[i]; \
+\
+		__m64 a = _mm_set1_pi##size(test_data.a); \
+		__m64 b = _mm_set1_pi##size(test_data.b); \
+		__m64 expected = _mm_set1_pi##size(test_data.result); \
+		__m64 result = testfunc(a, b); \
+\
+		bool success = mm_raw_compare(expected, result); \
+		errors += (int) (!success); \
+	} \
+\
+	_m_empty(); \
+	printf("TEST: finished with: %d errors\n", errors); \
+	return errors; \
+}
+
+#define MMX_SHIFT_TEST(name, testcases, testfunc) \
+bool name() { \
+	printf("TEST: " #name "\n"); \
+	int errors = 0; \
+\
+	for (size_t i = 0; i < ARRAY_SIZE(testcases); i++ ) { \
+		mmx_u64_test_t test_data = testcases[i]; \
+\
+		__m64 a = mm_load64(test_data.a); \
+		__m64 expected = mm_load64(test_data.result); \
+		__m64 result = testfunc(a, test_data.b); \
+\
+		bool success = mm_raw_compare(expected, result); \
+		if (!success) { \
+			printf( \
+				"Failed; Expected: 0x%08x_%08x\tGot: 0x%08x_%08x\n", \
+				_m_to_int(_mm_srli_si64(expected, 32)), \
+				_m_to_int(expected), \
+				_m_to_int(_mm_srli_si64(result, 32)), \
+				_m_to_int(result) \
+			); \
+		} \
+		errors += (int) (!success); \
+	} \
+\
+	_m_empty(); \
+	printf("TEST: finished with: %d errors\n", errors); \
+	return errors; \
+}
+
+
+
+// Loads 2 64 bit immediates and compares with the third
+// Test data must be of type mmx_u64_test_t
+#define MMX_64_TEST(name, testcases, testfunc) \
+bool name() { \
+	printf("TEST: " #name "\n"); \
+	int errors = 0; \
+\
+	for (size_t i = 0; i < ARRAY_SIZE(testcases); i++ ) { \
+		mmx_u64_test_t test_data = testcases[i]; \
+\
+		__m64 a = mm_load64(test_data.a); \
+		__m64 b = mm_load64(test_data.b); \
+		__m64 expected = mm_load64(test_data.result); \
+		__m64 result = testfunc(a, b); \
+\
+		bool success = mm_raw_compare(expected, result); \
+		if (!success) { \
+			printf( \
+				"Failed; Expected: 0x%08x_%08x\tGot: 0x%08x_%08x\n", \
+				_m_to_int(_mm_srli_si64(expected, 32)), \
+				_m_to_int(expected), \
+				_m_to_int(_mm_srli_si64(result, 32)), \
+				_m_to_int(result) \
+			); \
+		} \
+		errors += (int) (!success); \
+	} \
+\
+	_m_empty(); \
+	printf("TEST: finished with: %d errors\n", errors); \
+	return errors; \
+}
+
+
+mmx_i8_test_t mmx_i8_add_test_data[] = {
+	{ .a = 1, .b = 2, .result = 3 },
+	{ .a = 0, .b = 1, .result = 1 },
+	{ .a = I8_MAX, .b = 1, .result = I8_MIN },
+	{ .a = I8_MIN, .b = -1, .result = I8_MAX },
+	{ .a = 0, .b = U8_MAX, .result = U8_MAX },
+};
+mmx_i8_test_t mmx_i8_add_sat_test_data[] = {
+	{ .a = 1, .b = 2, .result = 3 },
+	{ .a = 0, .b = 1, .result = 1 },
+	{ .a = I8_MAX, .b = 1, .result = I8_MAX },
+	{ .a = I8_MIN, .b = -1, .result = I8_MIN },
+};
+mmx_u8_test_t mmx_u8_add_sat_test_data[] = {
+	{ .a = 1, .b = 2, .result = 3 },
+	{ .a = 0, .b = 1, .result = 1 },
+	{ .a = U8_MAX, .b = 1, .result = U8_MAX },
+	{ .a = 0, .b = U8_MAX, .result = U8_MAX },
+};
+
+mmx_i16_test_t mmx_i16_add_test_data[] = {
+	{ .a = 1, .b = 2, .result = 3 },
+	{ .a = 0, .b = 1, .result = 1 },
+	{ .a = I16_MAX, .b = 1, .result = I16_MIN },
+	{ .a = I16_MIN, .b = -1, .result = I16_MAX },
+};
+mmx_i16_test_t mmx_i16_add_sat_test_data[] = {
+	{ .a = 1, .b = 2, .result = 3 },
+	{ .a = 0, .b = 1, .result = 1 },
+	{ .a = I16_MAX, .b = 1, .result = I16_MAX },
+	{ .a = I16_MIN, .b = -1, .result = I16_MIN },
+};
+mmx_u16_test_t mmx_u16_add_sat_test_data[] = {
+	{ .a = 1, .b = 2, .result = 3 },
+	{ .a = 0, .b = 1, .result = 1 },
+	{ .a = U16_MAX, .b = 1, .result = U16_MAX },
+	{ .a = 0, .b = U16_MAX, .result = U16_MAX },
+};
+
+mmx_i32_test_t mmx_i32_add_test_data[] = {
+	{ .a = 1, .b = 2, .result = 3 },
+	{ .a = 0, .b = 1, .result = 1 },
+	{ .a = I32_MAX, .b = 1, .result = I32_MIN },
+	{ .a = I32_MIN, .b = -1, .result = I32_MAX },
+};
+
+MMX_ARITH_TEST(test_mmx_paddb, mmx_i8_add_test_data, mmx_i8_test_t, i8, 8, _m_paddb);
+MMX_ARITH_TEST(test_mmx_paddsb, mmx_i8_add_sat_test_data, mmx_i8_test_t, i8, 8, _m_paddsb);
+MMX_ARITH_TEST(test_mmx_paddusb, mmx_u8_add_sat_test_data, mmx_u8_test_t, u8, 8, _m_paddusb);
+
+MMX_ARITH_TEST(test_mmx_paddw, mmx_i16_add_test_data, mmx_i16_test_t, i16, 16, _m_paddw);
+MMX_ARITH_TEST(test_mmx_paddsw, mmx_i16_add_sat_test_data, mmx_i16_test_t, i16, 16, _m_paddsw);
+MMX_ARITH_TEST(test_mmx_paddusw, mmx_u16_add_sat_test_data, mmx_u16_test_t, u16, 16, _m_paddusw);
+
+MMX_ARITH_TEST(test_mmx_paddd, mmx_i32_add_test_data, mmx_i32_test_t, i32, 32, _m_paddd);
+
+
+
+mmx_i8_test_t mmx_i8_sub_test_data[] = {
+	{ .a = 3, .b = 2, .result = 1 },
+	{ .a = 1, .b = 1, .result = 0 },
+	{ .a = I8_MIN, .b = 1, .result = I8_MAX },
+	{ .a = I8_MAX, .b = -1, .result = I8_MIN },
+	{ .a = U8_MAX, .b = U8_MAX, .result = 0 },
+};
+mmx_i8_test_t mmx_i8_sub_sat_test_data[] = {
+	{ .a = 3, .b = 2, .result = 1 },
+	{ .a = 1, .b = 1, .result = 0 },
+	{ .a = I8_MIN, .b = 1, .result = I8_MIN },
+	{ .a = I8_MAX, .b = -1, .result = I8_MAX },
+};
+mmx_u8_test_t mmx_u8_sub_sat_test_data[] = {
+	{ .a = 3, .b = 2, .result = 1 },
+	{ .a = 1, .b = 1, .result = 0 },
+	{ .a = U8_MIN, .b = 1, .result = U8_MIN },
+	{ .a = U8_MAX, .b = U8_MAX, .result = 0 },
+};
+
+mmx_i16_test_t mmx_i16_sub_test_data[] = {
+	{ .a = 3, .b = 2, .result = 1 },
+	{ .a = 1, .b = 1, .result = 0 },
+	{ .a = I16_MIN, .b = 1, .result = I16_MAX },
+	{ .a = I16_MAX, .b = -1, .result = I16_MIN },
+};
+mmx_i16_test_t mmx_i16_sub_sat_test_data[] = {
+	{ .a = 3, .b = 2, .result = 1 },
+	{ .a = 1, .b = 1, .result = 0 },
+	{ .a = I16_MIN, .b = 1, .result = I16_MIN },
+	{ .a = I16_MAX, .b = -1, .result = I16_MAX },
+};
+mmx_u16_test_t mmx_u16_sub_sat_test_data[] = {
+	{ .a = 3, .b = 2, .result = 1 },
+	{ .a = 1, .b = 1, .result = 0 },
+	{ .a = U16_MIN, .b = 1, .result = U16_MIN },
+	{ .a = U16_MIN, .b = U16_MIN, .result = 0 },
+};
+
+mmx_i32_test_t mmx_i32_sub_test_data[] = {
+	{ .a = 3, .b = 2, .result = 1 },
+	{ .a = 1, .b = 1, .result = 0 },
+	{ .a = I32_MIN, .b = 1, .result = I32_MAX },
+	{ .a = I32_MAX, .b = -1, .result = I32_MIN },
+};
+
+MMX_ARITH_TEST(test_mmx_psubb, mmx_i8_sub_test_data, mmx_i8_test_t, i8, 8, _m_psubb);
+MMX_ARITH_TEST(test_mmx_psubsb, mmx_i8_sub_sat_test_data, mmx_i8_test_t, i8, 8, _m_psubsb);
+MMX_ARITH_TEST(test_mmx_psubusb, mmx_u8_sub_sat_test_data, mmx_u8_test_t, u8, 8, _m_psubusb);
+
+MMX_ARITH_TEST(test_mmx_psubw, mmx_i16_sub_test_data, mmx_i16_test_t, i16, 16, _m_psubw);
+MMX_ARITH_TEST(test_mmx_psubuw, mmx_i16_sub_sat_test_data, mmx_i16_test_t, i16, 16, _m_psubsw);
+MMX_ARITH_TEST(test_mmx_psubusw, mmx_u16_sub_sat_test_data, mmx_u16_test_t, u16, 16, _m_psubusw);
+
+MMX_ARITH_TEST(test_mmx_psubd, mmx_i32_sub_test_data, mmx_i32_test_t, i32, 32, _m_psubd);
+
+
+
+
+mmx_u64_test_t mmx_por_test_data[] = {
+	{ .a = 0xAAAAAAAAAAAAAAAA,
+	  .b = 0x5555555555555555,
+	  .result = 0xFFFFFFFFFFFFFFFF },
+	{ .a = 0x0000000000000000,
+	  .b = 0x1111111111111111,
+	  .result = 0x1111111111111111 },
+};
+
+mmx_u64_test_t mmx_pand_test_data[] = {
+	{ .a = 0xAAAAAAAAAAAAAAAA,
+	  .b = 0x5555555555555555,
+	  .result = 0x0000000000000000 },
+	{ .a = 0xFFFFFFFFFFFFFFFF,
+	  .b = 0xFFFFFFFFFFFFFFFF,
+	  .result = 0xFFFFFFFFFFFFFFFF },
+};
+
+mmx_u64_test_t mmx_pandn_test_data[] = {
+	{ .a = 0x0000000000000000,
+	  .b = 0xFFFFFFFFFFFFFFFF,
+	  .result = 0xFFFFFFFFFFFFFFFF },
+	{ .a = 0xFFFFFFFFFFFFFFFF,
+	  .b = 0x0000000000000000,
+	  .result = 0x0000000000000000 },
+};
+
+
+mmx_u64_test_t mmx_pxor_test_data[] = {
+	{ .a = 0xAAAAAAAAAAAAAAAA,
+	  .b = 0x5555555555555555,
+	  .result = 0xFFFFFFFFFFFFFFFF },
+	{ .a = 0xFFFFFFFFFFFFFFFF,
+	  .b = 0xFFFFFFFFFFFFFFFF,
+	  .result = 0x0000000000000000 },
+};
+
+
+MMX_64_TEST(test_mmx_por, mmx_por_test_data, _m_por);
+MMX_64_TEST(test_mmx_pand, mmx_pand_test_data, _m_pand);
+MMX_64_TEST(test_mmx_pandn, mmx_pandn_test_data, _m_pandn);
+MMX_64_TEST(test_mmx_pxor, mmx_pxor_test_data, _m_pxor);
+
+
+
+
+
+mmx_i16_test_t mmx_pmullw_test_data[] = {
+	{ .a = 10, .b = 10, .result = 100 },
+	{ .a = 32000, .b = 10, .result = 0xE200 },
+	{ .a = 20000, .b = 20000, .result = 0x8400 },
+};
+mmx_i16_test_t mmx_pmulhw_test_data[] = {
+	{ .a = 10, .b = 10, .result = 0 },
+	{ .a = 32000, .b = 10, .result = 4 },
+	{ .a = 20000, .b = 20000, .result = 0x17D7 },
+};
+mmx_u64_test_t mmx_pmaddwd_test_data[] = {
+	{ .a = 0x0000000100000001,
+	  .b = 0x0000000100000001,
+	  .result = 0x0000000100000001 },
+	{ .a = 0x0000000200000004,
+	  .b = 0x0000000200000004,
+	  .result = 0x0000000400000010 },
+
+	{ .a = 0x000000007FFFFFFF,
+	  .b = 0x000000007FFFFFFF,
+	  .result = 0x000000003FFF0002 },
+
+	// -1 * -1 = 2
+	{ .a = 0x00000000FFFFFFFF,
+	  .b = 0x00000000FFFFFFFF,
+	  .result = 0x0000000000000002 },
+};
+
+
+MMX_ARITH_TEST(test_mmx_pmullw, mmx_pmullw_test_data, mmx_i16_test_t, i16, 16, _m_pmullw);
+MMX_ARITH_TEST(test_mmx_pmulhw, mmx_pmulhw_test_data, mmx_i16_test_t, i16, 16, _m_pmulhw);
+MMX_64_TEST(test_mmx_pmaddwd, mmx_pmaddwd_test_data, _m_pmaddwd);
+
+
+
+
+
+mmx_u64_test_t mmx_packssdw_test_data[] = {
+	{ .a = 0x0000000200000001,
+	  .b = 0x0000000400000003,
+	  .result = 0x0004000300020001 },
+	{ .a = 0x7FFFFFFF7FFFFFFF,
+	  .b = 0x7FFFFFFF7FFFFFFF,
+	  .result = 0x7FFF7FFF7FFF7FFF },
+	{ .a = 0x8000000080000000,
+	  .b = 0x8000000080000000,
+	  .result = 0x8000800080008000 },
+};
+mmx_u64_test_t mmx_packsswb_test_data[] = {
+	{ .a = 0x0004000300020001,
+	  .b = 0x0008000700060005,
+	  .result = 0x0807060504030201 },
+	{ .a = 0x7FFF7FFF7FFF7FFF,
+	  .b = 0x7FFF7FFF7FFF7FFF,
+	  .result = 0x7F7F7F7F7F7F7F7F },
+	{ .a = 0x8000800080008000,
+	  .b = 0x8000800080008000,
+	  .result = 0x8080808080808080 },
+};
+mmx_u64_test_t mmx_packuswb_test_data[] = {
+	{ .a = 0x0004000300020001,
+	  .b = 0x0008000700060005,
+	  .result = 0x0807060504030201 },
+	{ .a = 0x7FFF7FFF7FFF7FFF,
+	  .b = 0x7FFF7FFF7FFF7FFF,
+	  .result = 0xFFFFFFFFFFFFFFFF },
+	{ .a = 0x8000800080008000,
+	  .b = 0x8000800080008000,
+	  .result = 0x0000000000000000 },
+};
+
+
+MMX_64_TEST(test_mmx_packssdw, mmx_packssdw_test_data, _m_packssdw);
+MMX_64_TEST(test_mmx_packsswb, mmx_packsswb_test_data, _m_packsswb);
+MMX_64_TEST(test_mmx_packuswb, mmx_packuswb_test_data, _m_packuswb);
+
+
+
+mmx_u64_test_t mmx_punpckhbw_test_data[] = {
+	{ .a = 0x4433221100000000,
+	  .b = 0x8877665500000000,
+	  .result = 0x8844773366225511 },
+};
+mmx_u64_test_t mmx_punpckhdq_test_data[] = {
+	{ .a = 0xAAAAAAAA00000000,
+	  .b = 0xBBBBBBBB00000000,
+	  .result = 0xBBBBBBBBAAAAAAAA },
+};
+mmx_u64_test_t mmx_punpckhwd_test_data[] = {
+	{ .a = 0xBBBBAAAA00000000,
+	  .b = 0xDDDDCCCC00000000,
+	  .result = 0xDDDDBBBBCCCCAAAA },
+};
+mmx_u64_test_t mmx_punpcklbw_test_data[] = {
+	{ .a = 0x0000000044332211,
+	  .b = 0x0000000088776655,
+	  .result = 0x8844773366225511 },
+};
+mmx_u64_test_t mmx_punpckldq_test_data[] = {
+	{ .a = 0x00000000AAAAAAAA,
+	  .b = 0x00000000BBBBBBBB,
+	  .result = 0xBBBBBBBBAAAAAAAA },
+};
+mmx_u64_test_t mmx_punpcklwd_test_data[] = {
+	{ .a = 0x00000000BBBBAAAA,
+	  .b = 0x00000000DDDDCCCC,
+	  .result = 0xDDDDBBBBCCCCAAAA },
+};
+
+
+MMX_64_TEST(test_mmx_punpckhbw, mmx_punpckhbw_test_data, _m_punpckhbw);
+MMX_64_TEST(test_mmx_punpckhdq, mmx_punpckhdq_test_data, _m_punpckhdq);
+MMX_64_TEST(test_mmx_punpckhwd, mmx_punpckhwd_test_data, _m_punpckhwd);
+MMX_64_TEST(test_mmx_punpcklbw, mmx_punpcklbw_test_data, _m_punpcklbw);
+MMX_64_TEST(test_mmx_punpckldq, mmx_punpckldq_test_data, _m_punpckldq);
+MMX_64_TEST(test_mmx_punpcklwd, mmx_punpcklwd_test_data, _m_punpcklwd);
+
+
+
+
+
+
+mmx_u64_test_t mmx_pcmpeqb_test_data[] = {
+	{ .a = 0x8877665544332211,
+	  .b = 0x0077005500330011,
+	  .result = 0x00FF00FF00FF00FF },
+};
+mmx_u64_test_t mmx_pcmpeqw_test_data[] = {
+	{ .a = 0x4444333322221111,
+	  .b = 0x0000333300001111,
+	  .result = 0x0000FFFF0000FFFF },
+};
+mmx_u64_test_t mmx_pcmpeqd_test_data[] = {
+	{ .a = 0x2222222211111111,
+	  .b = 0x2222222200000000,
+	  .result = 0xFFFFFFFF00000000 },
+};
+
+mmx_u64_test_t mmx_pcmpgtb_test_data[] = {
+	{ .a = 0x0000000000002201,
+	  .b = 0x0000000000002300,
+	  .result = 0x00000000000000FF },
+};
+mmx_u64_test_t mmx_pcmpgtw_test_data[] = {
+	{ .a = 0x4444333322221111,
+	  .b = 0x0000333300001112,
+	  .result = 0xFFFF0000FFFF0000 },
+};
+mmx_u64_test_t mmx_pcmpgtd_test_data[] = {
+	{ .a = 0x2222222111111111,
+	  .b = 0x2222222200000000,
+	  .result = 0x00000000FFFFFFFF },
+};
+
+
+MMX_64_TEST(test_mmx_pcmpeqb, mmx_pcmpeqb_test_data, _m_pcmpeqb);
+MMX_64_TEST(test_mmx_pcmpeqw, mmx_pcmpeqw_test_data, _m_pcmpeqw);
+MMX_64_TEST(test_mmx_pcmpeqd, mmx_pcmpeqd_test_data, _m_pcmpeqd);
+MMX_64_TEST(test_mmx_pcmpgtb, mmx_pcmpgtb_test_data, _m_pcmpgtb);
+MMX_64_TEST(test_mmx_pcmpgtw, mmx_pcmpgtw_test_data, _m_pcmpgtw);
+MMX_64_TEST(test_mmx_pcmpgtd, mmx_pcmpgtd_test_data, _m_pcmpgtd);
+
+
+
+
+mmx_u64_test_t mmx_pslld_test_data[] = {
+	{ .a = 1, .b = 1, .result = 2 },
+	{ .a = 16, .b = 1, .result = 32 },
+	{ .a = 16, .b = 32, .result = 0 },
+	{ .a = 16, .b = 0, .result = 16 },
+};
+mmx_u64_test_t mmx_psllq_test_data[] = {
+	{ .a = 1, .b = 1, .result = 2 },
+	{ .a = 16, .b = 1, .result = 32 },
+	{ .a = 16, .b = 64, .result = 0 },
+	{ .a = 16, .b = 0, .result = 16 },
+};
+mmx_u64_test_t mmx_psllw_test_data[] = {
+	{ .a = 1, .b = 1, .result = 2 },
+	{ .a = 16, .b = 1, .result = 32 },
+	{ .a = 16, .b = 16, .result = 0 },
+	{ .a = 16, .b = 0, .result = 16 },
+};
+mmx_u64_test_t mmx_psrad_test_data[] = {
+	{ .a = 1, .b = 1, .result = 0 },
+	{ .a = 16, .b = 1, .result = 8 },
+	{ .a = 16, .b = 0, .result = 16 },
+	{ .a = 0x7FFFFFFF, .b = 1, .result = 0x3FFFFFFF },
+
+	{ .a = I32_MAX, .b = 32, .result = 0 },
+	{ .a = I32_MIN, .b = 32, .result = U32_MAX },
+};
+mmx_u64_test_t mmx_psraw_test_data[] = {
+	{ .a = 1, .b = 1, .result = 0 },
+	{ .a = 16, .b = 1, .result = 8 },
+	{ .a = 16, .b = 0, .result = 16 },
+	{ .a = 0x7FFF, .b = 1, .result = 0x3FFF },
+
+	{ .a = I16_MAX, .b = 16, .result = 0 },
+	{ .a = U16_MAX, .b = 16, .result = U16_MAX },
+};
+mmx_u64_test_t mmx_psrld_test_data[] = {
+	{ .a = 1, .b = 1, .result = 0 },
+	{ .a = 16, .b = 1, .result = 8 },
+	{ .a = 16, .b = 0, .result = 16 },
+	{ .a = 0x7FFFFFFF, .b = 1, .result = 0x3FFFFFFF },
+
+	{ .a = I32_MAX, .b = 32, .result = 0 },
+	{ .a = I32_MIN, .b = 32, .result = 0 },
+};
+mmx_u64_test_t mmx_psrlq_test_data[] = {
+	{ .a = 1, .b = 1, .result = 0 },
+	{ .a = 16, .b = 1, .result = 8 },
+	{ .a = 16, .b = 0, .result = 16 },
+
+	{ .a = I64_MAX, .b = 64, .result = 0 },
+	{ .a = I64_MIN, .b = 64, .result = 0 },
+};
+mmx_u64_test_t mmx_psrlw_test_data[] = {
+	{ .a = 1, .b = 1, .result = 0 },
+	{ .a = 16, .b = 1, .result = 8 },
+	{ .a = 16, .b = 0, .result = 16 },
+
+	{ .a = I16_MAX, .b = 16, .result = 0 },
+
+	// TODO: Works on my machine
+	// { .a = I16_MIN, .b = 16, .result = 0 },
+};
+
+
+
+MMX_64_TEST(test_mmx_pslld, mmx_pslld_test_data, _m_pslld);
+MMX_64_TEST(test_mmx_psllq, mmx_psllq_test_data, _m_psllq);
+MMX_64_TEST(test_mmx_psllw, mmx_psllw_test_data, _m_psllw);
+MMX_64_TEST(test_mmx_psrad, mmx_psrad_test_data, _m_psrad);
+MMX_64_TEST(test_mmx_psraw, mmx_psraw_test_data, _m_psraw);
+MMX_64_TEST(test_mmx_psrld, mmx_psrld_test_data, _m_psrld);
+MMX_64_TEST(test_mmx_psrlq, mmx_psrlq_test_data, _m_psrlq);
+MMX_64_TEST(test_mmx_psrlw, mmx_psrlw_test_data, _m_psrlw);
+
+MMX_SHIFT_TEST(test_mmx_pslldi, mmx_pslld_test_data, _m_pslldi);
+MMX_SHIFT_TEST(test_mmx_psllqi, mmx_psllq_test_data, _m_psllqi);
+MMX_SHIFT_TEST(test_mmx_psllwi, mmx_psllw_test_data, _m_psllwi);
+MMX_SHIFT_TEST(test_mmx_psradi, mmx_psrad_test_data, _m_psradi);
+MMX_SHIFT_TEST(test_mmx_psrawi, mmx_psraw_test_data, _m_psrawi);
+MMX_SHIFT_TEST(test_mmx_psrldi, mmx_psrld_test_data, _m_psrldi);
+MMX_SHIFT_TEST(test_mmx_psrlqi, mmx_psrlq_test_data, _m_psrlqi);
+MMX_SHIFT_TEST(test_mmx_psrlwi, mmx_psrlw_test_data, _m_psrlwi);
+
+
+
+
+bool test_mmx_cpuid() {
+	printf("TEST: test_mmx_cpuid\n");
+
+	unsigned int eax, ebx, ecx, edx;
+	asm volatile(
+		"cpuid"
+		: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
+		: "a" (1), "c" (0)
+	);
+
+	int has_mmx = !!(edx & (1 << 23));
+	if (has_mmx) {
+		return 0;
+	} 
+		return 1;
+	
+}
+
+int main() {
+	int errors = 0;
+
+	errors += (int) test_mmx_cpuid();
+
+
+	errors += (int) test_mmx_paddb();
+	errors += (int) test_mmx_paddsb();
+	errors += (int) test_mmx_paddusb();
+	errors += (int) test_mmx_paddw();
+	errors += (int) test_mmx_paddsw();
+	errors += (int) test_mmx_paddusw();
+	errors += (int) test_mmx_paddd();
+
+	errors += (int) test_mmx_psubb();
+	errors += (int) test_mmx_psubsb();
+	errors += (int) test_mmx_psubusb();
+	errors += (int) test_mmx_psubw();
+	errors += (int) test_mmx_psubuw();
+	errors += (int) test_mmx_psubusw();
+	errors += (int) test_mmx_psubd();
+
+	errors += (int) test_mmx_por();
+	errors += (int) test_mmx_pand();
+	errors += (int) test_mmx_pandn();
+	errors += (int) test_mmx_pxor();
+
+	errors += (int) test_mmx_pmullw();
+	errors += (int) test_mmx_pmulhw();
+	errors += (int) test_mmx_pmaddwd();
+
+	errors += (int) test_mmx_packssdw();
+	errors += (int) test_mmx_packsswb();
+	errors += (int) test_mmx_packuswb();
+
+	errors += (int) test_mmx_punpckhbw();
+	errors += (int) test_mmx_punpckhdq();
+	errors += (int) test_mmx_punpckhwd();
+	errors += (int) test_mmx_punpcklbw();
+	errors += (int) test_mmx_punpckldq();
+	errors += (int) test_mmx_punpcklwd();
+
+	errors += (int) test_mmx_pcmpeqb();
+	errors += (int) test_mmx_pcmpeqw();
+	errors += (int) test_mmx_pcmpeqd();
+	errors += (int) test_mmx_pcmpgtb();
+	errors += (int) test_mmx_pcmpgtw();
+	errors += (int) test_mmx_pcmpgtd();
+
+	errors += (int) test_mmx_psllw();
+	errors += (int) test_mmx_psllwi();
+	errors += (int) test_mmx_pslld();
+	errors += (int) test_mmx_pslldi();
+	errors += (int) test_mmx_psllq();
+	errors += (int) test_mmx_psllqi();
+	errors += (int) test_mmx_psraw();
+	errors += (int) test_mmx_psrawi();
+	errors += (int) test_mmx_psrad();
+	errors += (int) test_mmx_psradi();
+	errors += (int) test_mmx_psrld();
+	errors += (int) test_mmx_psrldi();
+	errors += (int) test_mmx_psrlq();
+	errors += (int) test_mmx_psrlqi();
+	errors += (int) test_mmx_psrlw();
+	errors += (int) test_mmx_psrlwi();
+
+
+	printf("Errors: %d\n", errors);
+	return errors;
+}
+
diff --git a/tests32/extensions/mmx.txt b/tests32/extensions/mmx.txt
new file mode 100644
index 00000000..673647b6
--- /dev/null
+++ b/tests32/extensions/mmx.txt
@@ -0,0 +1,106 @@
+TEST: test_mmx_cpuid
+TEST: test_mmx_paddb
+TEST: finished with: 0 errors
+TEST: test_mmx_paddsb
+TEST: finished with: 0 errors
+TEST: test_mmx_paddusb
+TEST: finished with: 0 errors
+TEST: test_mmx_paddw
+TEST: finished with: 0 errors
+TEST: test_mmx_paddsw
+TEST: finished with: 0 errors
+TEST: test_mmx_paddusw
+TEST: finished with: 0 errors
+TEST: test_mmx_paddd
+TEST: finished with: 0 errors
+TEST: test_mmx_psubb
+TEST: finished with: 0 errors
+TEST: test_mmx_psubsb
+TEST: finished with: 0 errors
+TEST: test_mmx_psubusb
+TEST: finished with: 0 errors
+TEST: test_mmx_psubw
+TEST: finished with: 0 errors
+TEST: test_mmx_psubuw
+TEST: finished with: 0 errors
+TEST: test_mmx_psubusw
+TEST: finished with: 0 errors
+TEST: test_mmx_psubd
+TEST: finished with: 0 errors
+TEST: test_mmx_por
+TEST: finished with: 0 errors
+TEST: test_mmx_pand
+TEST: finished with: 0 errors
+TEST: test_mmx_pandn
+TEST: finished with: 0 errors
+TEST: test_mmx_pxor
+TEST: finished with: 0 errors
+TEST: test_mmx_pmullw
+TEST: finished with: 0 errors
+TEST: test_mmx_pmulhw
+TEST: finished with: 0 errors
+TEST: test_mmx_pmaddwd
+TEST: finished with: 0 errors
+TEST: test_mmx_packssdw
+TEST: finished with: 0 errors
+TEST: test_mmx_packsswb
+TEST: finished with: 0 errors
+TEST: test_mmx_packuswb
+TEST: finished with: 0 errors
+TEST: test_mmx_punpckhbw
+TEST: finished with: 0 errors
+TEST: test_mmx_punpckhdq
+TEST: finished with: 0 errors
+TEST: test_mmx_punpckhwd
+TEST: finished with: 0 errors
+TEST: test_mmx_punpcklbw
+TEST: finished with: 0 errors
+TEST: test_mmx_punpckldq
+TEST: finished with: 0 errors
+TEST: test_mmx_punpcklwd
+TEST: finished with: 0 errors
+TEST: test_mmx_pcmpeqb
+TEST: finished with: 0 errors
+TEST: test_mmx_pcmpeqw
+TEST: finished with: 0 errors
+TEST: test_mmx_pcmpeqd
+TEST: finished with: 0 errors
+TEST: test_mmx_pcmpgtb
+TEST: finished with: 0 errors
+TEST: test_mmx_pcmpgtw
+TEST: finished with: 0 errors
+TEST: test_mmx_pcmpgtd
+TEST: finished with: 0 errors
+TEST: test_mmx_psllw
+TEST: finished with: 0 errors
+TEST: test_mmx_psllwi
+TEST: finished with: 0 errors
+TEST: test_mmx_pslld
+TEST: finished with: 0 errors
+TEST: test_mmx_pslldi
+TEST: finished with: 0 errors
+TEST: test_mmx_psllq
+TEST: finished with: 0 errors
+TEST: test_mmx_psllqi
+TEST: finished with: 0 errors
+TEST: test_mmx_psraw
+TEST: finished with: 0 errors
+TEST: test_mmx_psrawi
+TEST: finished with: 0 errors
+TEST: test_mmx_psrad
+TEST: finished with: 0 errors
+TEST: test_mmx_psradi
+TEST: finished with: 0 errors
+TEST: test_mmx_psrld
+TEST: finished with: 0 errors
+TEST: test_mmx_psrldi
+TEST: finished with: 0 errors
+TEST: test_mmx_psrlq
+TEST: finished with: 0 errors
+TEST: test_mmx_psrlqi
+TEST: finished with: 0 errors
+TEST: test_mmx_psrlw
+TEST: finished with: 0 errors
+TEST: test_mmx_psrlwi
+TEST: finished with: 0 errors
+Errors: 0