void* Memory::SetBytes( void* b, int c, size_t n) { if(n < 1) return NULL; #if defined(VD_USE_ASMLIB) return A_memset(b, c, n); #else return ::memset(b, c, n); #endif }
int main () { int ao, bo, os, len; int version; const int pagesize = 0x1000; // 4 kbytes const int n = 16*pagesize; char a[n], b[n], c[n]; int instrset = InstructionSet(); // CacheBypassLimit = 5; printf("\nmemcpy cache limit = 0x%X, memset cache limit 0x%X\n", (int)GetMemcpyCacheLimit(), (int)GetMemsetCacheLimit()); printf("\nTest memcpy"); int i, x = 91; for (i=0; i<n; i++) { x += 23; a[i] = (char)x; } A_memset(b, -1, n); SetMemcpyCacheLimit(0); // default #if 1 // Test memcpy for correctness // Loop through versions for (version = 0; version < NUMFUNC; version++) { printf("\n%s", DispatchNames[version]); if (instrset < isetreq[version]) { // instruction set not supported printf(" skipped"); continue; } for (len=0; len<514; len++) { for (ao = 0; ao <=20; ao++) { for (bo = 0; bo <=32; bo++) { A_memset(b, -1, len+96); (*memcpyTab[version])(b+bo, a+ao, len); if (bo && b[bo-1] != -1) error("A", ao, bo, len); if (b[bo+len] != -1) error("B", ao, bo, len); if (len==0) continue; if (b[bo] != a[ao]) error("C", ao, bo, len); if (b[bo+len-1] != a[ao+len-1]) error("D", ao, bo, len); if (memcmp(b+bo, a+ao, len)) error("E", ao, bo, len); } } } // check false memory dependence branches len = 300; A_memcpy(b, a, 3*pagesize); for (ao = pagesize-300; ao < pagesize+200; ao++) { for (bo = 3*pagesize; bo <=3*pagesize+33; bo++) { A_memset(b+bo-64, -1, len+128); (*memcpyTab[version])(b+bo, b+ao, len); if (b[bo-1] != -1) error("A1", ao, bo, len); if (b[bo+len] != -1) error("B1", ao, bo, len); if (memcmp(b+bo, b+ao, len)) error("E1", ao, bo, len); } } // check false memory dependence branches with overlap // src > dest and overlap: must copy forwards len = pagesize+1000; for (ao = 2*pagesize; ao <=2*pagesize+33; ao++) { for (bo = pagesize-200; bo < pagesize+300; bo++) { A_memcpy(b, a, 4*pagesize); A_memcpy(c, a, 4*pagesize); (*memcpyTab[version])(b+bo, b+ao, len); //memcpy(c+bo, c+ao, len); // Most library versions of memcpy are actually memmove memcpySSE2(c+bo, c+ao, len); if (memcmp(b, c, 4*pagesize)) { error("E2", ao-pagesize, bo-2*pagesize, len); } } } // check false memory dependence branches with overlap // dest > src and overlap: undefined behavior #if 1 len = pagesize+1000; for (ao = pagesize-200; ao < pagesize+200; ao++) { for (bo = 2*pagesize; bo <=2*pagesize+33; bo++) { A_memcpy(b, a, 4*pagesize); A_memcpy(c, a, 4*pagesize); (*memcpyTab[version])(b+bo, b+ao, len); //memcpy(c+bo, c+ao, len); // MS Most library versions of memcpy are actually memmove memcpySSE2(c+bo, c+ao, len); if (memcmp(b, c, 4*pagesize)) { error("E3", ao-pagesize, bo-2*pagesize, len); } } } #endif } printf("\n\nTest memmove"); // Test memmove for correctness for (i=0; i<n; i++) { x += 23; a[i] = char(x); } // Loop through versions for (version = 0; version < NUMFUNC; version++) { printf("\n%s", DispatchNames[version]); if (instrset < isetreq[version]) { // instruction set not supported printf(" skipped"); continue; } // move forward for (len=0; len<400; len++) { for (bo = 0; bo <=33; bo++) { for (os = 0; os <= 33; os++) { A_memcpy(b, a, len+100); (*memmoveTab[version])(b+bo+os, b+bo, len); for (i=0; i<bo+os; i++) if (b[i]!=a[i]) error("E", i, bo, os, len); for (i=bo+os; i<bo+os+len; i++) if (b[i] != a[i-os]) error("F", i, bo, os, len); for (;i < bo+os+len+20; i++) if (b[i]!=a[i]) error("G", i, bo, os, len); } } } // move backwards for (len=0; len<400; len++) { for (bo = 0; bo <=33; bo++) { for (os = 0; os < 33; os++) { A_memcpy(b, a, len+96); (*memmoveTab[version])(b+bo, b+bo+os, len); for (i=0; i<bo; i++) if (b[i]!=a[i]) error("H", i, bo, os, len); for (i=bo; i<bo+len; i++) if (b[i] != a[i+os]) error("I", i, bo, os, len); for (;i < bo+len+20; i++) if (b[i]!=a[i]) error("J", i, bo, os, len); } } } } printf("\n\nSame, with non-temporal moves"); SetMemcpyCacheLimit(1); // bypass cache // Loop through versions for (version = 0; version < NUMFUNC; version++) { printf("\n%s", DispatchNames[version]); if (instrset < isetreq[version]) { // instruction set not supported printf(" skipped"); continue; } for (len=0; len<514; len++) { for (ao = 0; ao <=20; ao++) { for (bo = 0; bo <=32; bo++) { A_memset(b, -1, len+96); (*memcpyTab[version])(b+bo, a+ao, len); if (bo && b[bo-1] != -1) error("A", ao, bo, len); if (b[bo+len] != -1) error("B", ao, bo, len); if (len==0) continue; if (b[bo] != a[ao]) error("C", ao, bo, len); if (b[bo+len-1] != a[ao+len-1]) error("D", ao, bo, len); if (memcmp(b+bo, a+ao, len)) error("E", ao, bo, len); } } } // check false memory dependence branches len = 300; A_memcpy(b, a, 3*pagesize); for (ao = pagesize-200; ao < pagesize+200; ao++) { for (bo = 3*pagesize; bo <=3*pagesize+33; bo++) { A_memset(b+bo-64, -1, len+128); (*memcpyTab[version])(b+bo, b+ao, len); if (b[bo-1] != -1) error("A1", ao, bo, len); if (b[bo+len] != -1) error("B1", ao, bo, len); if (memcmp(b+bo, b+ao, len)) error("E1", ao, bo, len); } } // check false memory dependence branches with overlap // src > dest and overlap: must copy forwards len = pagesize+1000; for (ao = 2*pagesize; ao <=2*pagesize+33; ao++) { for (bo = pagesize-200; bo < pagesize+200; bo++) { A_memcpy(b, a, 4*pagesize); A_memcpy(c, a, 4*pagesize); (*memcpyTab[version])(b+bo, b+ao, len); //memcpy(c+bo, c+ao, len); // Most library versions of memcpy are actually memmove memcpySSE2(c+bo, c+ao, len); if (memcmp(b, c, 4*pagesize)) { error("E2", ao-pagesize, bo-2*pagesize, len); } } } // (check false memory dependence branches with overlap. skipped) } printf("\n\nTest memmove"); // Test memmove for correctness for (i=0; i<n; i++) { x += 23; a[i] = char(x); } // Loop through versions for (version = 0; version < NUMFUNC; version++) { printf("\n%s", DispatchNames[version]); if (instrset < isetreq[version]) { // instruction set not supported printf(" skipped"); continue; } // move forward for (len=0; len<400; len++) { for (bo = 0; bo <=33; bo++) { for (os = 0; os <= 33; os++) { A_memcpy(b, a, len+100); (*memmoveTab[version])(b+bo+os, b+bo, len); for (i=0; i<bo+os; i++) if (b[i]!=a[i]) error("E", i, bo, os, len); for (i=bo+os; i<bo+os+len; i++) if (b[i] != a[i-os]) error("F", i, bo, os, len); for (;i < bo+os+len+20; i++) if (b[i]!=a[i]) error("G", i, bo, os, len); } } } // move backwards for (len=0; len<400; len++) { for (bo = 0; bo <=33; bo++) { for (os = 0; os < 33; os++) { A_memcpy(b, a, len+96); (*memmoveTab[version])(b+bo, b+bo+os, len); for (i=0; i<bo; i++) if (b[i]!=a[i]) error("H", i, bo, os, len); for (i=bo; i<bo+len; i++) if (b[i] != a[i+os]) error("I", i, bo, os, len); for (;i < bo+len+20; i++) if (b[i]!=a[i]) error("J", i, bo, os, len); } } } } #endif SetMemcpyCacheLimit(0); // back to default SetMemsetCacheLimit(0); printf("\n\nTest memset"); // test memset const int val1 = 0x4C, val2 = 0xA2, len2 = 1024; for (version = 0; version < MEMSETFUNCS; version++) { memsetF * func = memsetTab[version]; printf("\n%s", memsetNames[version]); if (instrset < memsetreq[version]) { // instruction set not supported printf(" skipped"); continue; } for (os = 0; os < 34; os++) { for (len = 0; len < 500; len++) { memset(a, val1, len2); memset(a+os, val2, len); (*func)(b, val1, len2); (*func)(b+os, val2, len); if (memcmp(a, b, len2)) { error("MS", version, os, len); } } } for (len=0; len<200; len++) { for (os = 0; os <= 33; os++) { A_memcpy(b, a, len+64); A_memset(b+os, 55, len); for (i=0; i<os; i++) if (b[i] != a[i]) error("K", i, os, len); for (; i<os+len; i++) if (b[i] != 55) error("L", i, os, len); for (; i<os+len+17; i++) if (b[i] != a[i]) error("M", i, os, len); } } } printf("\n\nSame, with non-temporal moves"); SetMemsetCacheLimit(1); // bypass cache for (version = 0; version < MEMSETFUNCS; version++) { memsetF * func = memsetTab[version]; printf("\n%s", memsetNames[version]); if (instrset < memsetreq[version]) { // instruction set not supported printf(" skipped"); continue; } for (os = 0; os < 34; os++) { for (len = 0; len < 500; len++) { memset(a, val1, len2); memset(a+os, val2, len); (*func)(b, val1, len2); (*func)(b+os, val2, len); if (memcmp(a, b, len2)) { error("MS", version, os, len); } } } } SetMemsetCacheLimit(0); // back to default printf("\n\nTest strlen"); // test strlen for (len=0; len<400; len++) { for (os = 0; os <= 32; os++) { A_memset(b, 0, len+64); A_memset(b+os, 'a', len); x = A_strlen(b+os); if (x != len) error("N", 0, os, len); A_memset(b, 1, len+64); b[os+len] = 0; x = A_strlen(b+os); if (x != len) error("O", 0, os, len); } } printf("\n\nTest strcpy and strcat"); // test strcpy and strcat for (i=0; i<n; i++) { x += 23; a[i] = char(x) | 1; } for (len=0; len<400; len++) { for (os = 0; os <= 16; os++) { for (i=0; i<33; i++) { A_memmove(b, a, len+64); b[os+len] = 0; A_strcpy(c+5, b+os); if (A_strlen(c+5) != len) error("P", 0, os, len); A_memmove(b+55, a, i+4); b[55+i] = 0; A_strcat(c+5, b+55); if (A_strlen(c+5) != len+i) error("R", 0, os, len); } } } printf("\n\nSuccess\n"); return 0; }
int main () { // test InstructionSet() printf("\nInstructionSet = %i", InstructionSet()); // test cpuid_abcd int abcd[4]; char s[16]; cpuid_abcd(abcd, 0); *(int*)(s+0) = abcd[1]; // ebx *(int*)(s+4) = abcd[3]; // edx *(int*)(s+8) = abcd[2]; // ecx s[12] = 0; // terminate string printf("\nVendor string = %s", s); // test ProcessorName() printf("\nProcessorName = %s", ProcessorName()); // test CpuType int vendor, family, model; CpuType(&vendor, &family, &model); printf("\nCpuType: vendor %i, family 0x%X, model 0x%X", vendor, family, model); // test DataCacheSize printf("\nData cache size: L1 %ikb, L2 %ikb, L3 %ikb", (int)DataCacheSize(1)/1024, (int)DataCacheSize(2)/1024, (int)DataCacheSize(3)/1024); // test ReadTSC() ReadTSC(); int tsc = (int)ReadTSC(); tsc = (int)ReadTSC() - tsc; printf("\nReadTSC takes %i clocks\n\n", tsc); // test Round(); double d; for (d = -1; d <= 1; d += 0.5) { printf("Round %f = %i = %i\n", d, Round(d), Round(float(d))); } // Test memory and string functions int i, n; const int strsize = 256; char string1[strsize], string2[strsize]; const char * teststring = "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 @`'{}[]()<>"; // Initialize strings A_memset(string1, 0, strsize); A_memset(string2, 0, strsize); // Test A_strcpy, A_strcat, A_strlen A_strcpy(string1, teststring); n = strsize/(int)A_strlen(teststring); for (i = 0; i < n-1; i++) { A_strcat(string1, teststring); } if (A_strlen(string1) != n * A_strlen(teststring)) Failure("A_strcpy, A_strcat, A_strlen"); // Test A_stricmp A_memcpy(string2, string1, strsize); string2[4] ^= 0x20; string1[30] ^= 0x20; // Change case if (A_stricmp(string1, string2) != 0) Failure("A_stricmp"); string2[8] += 2; // Make strings different if (A_stricmp(string1, string2) >= 0) Failure("A_stricmp"); string2[7] -= 2; // Make strings different if (A_stricmp(string1, string2) <= 0) Failure("A_stricmp"); // test A_strtolower and A_strtoupper A_strcpy(string1, teststring); A_strcpy(string2, teststring); A_strtolower(string1); A_strtoupper(string2); printf("\nstring converted to lower and upper case:\n%s\n%s\n%s", teststring, string1, string2); // test strspn and strcspn int n1, n2; const int nset = 4; const char * tset[] = {"abc", "", "01234567890123456789", "abcdefghijklmnopqrstuvwxyz"}; for (i = 0; i < nset; i++) { n1 = A_strspn(teststring, tset[i]); n2 = strspn(teststring, tset[i]); if (n1 != n2) Failure("A_strspn"); n1 = A_strcspn(teststring, tset[i]); n2 = strcspn(teststring, tset[i]); if (n1 != n2) Failure("A_strcspn"); } // Test A_memmove with overlapping source and destination A_memcpy(string2, string1, strsize); A_memcpy(string1+5, string1+12, 12); memcpy (string2+5, string2+12, 12); if (A_stricmp(string1, string2) != 0) Failure("memcpy"); A_memcpy(string1+5, string1+12, 130); memcpy (string2+5, string2+12, 130); if (A_stricmp(string1, string2) != 0) Failure("memcpy"); A_memmove(string1+5, string1+2, 12); memmove (string2+5, string2+2, 12); if (A_stricmp(string1, string2) != 0) Failure("A_memmove"); A_memmove(string1+3, string1+8, 12); memmove (string2+3, string2+8, 12); if (A_stricmp(string1, string2) != 0) Failure("A_memmove"); A_memmove(string1+41, string1+30, 100); memmove (string2+41, string2+30, 100); if (A_stricmp(string1, string2) != 0) Failure("A_memmove"); A_memmove(string1+32, string1+48, 177); memmove (string2+32, string2+48, 177); if (A_stricmp(string1, string2) != 0) Failure("A_memmove"); printf("\n\nTests passed OK\n"); return 0; }
/* Asm replacment for memset */ void * __cdecl memset_nontemporal_tt ( void *dest, int c, size_t count ) { return A_memset(dest, c, count); }