/* * This file is part of uniaud.dll. * * based on xine project memcpy.c * * These are the MMX/MMX2/SSE optimized versions of memcpy * * This code was adapted from Linux Kernel sources by Nick Kurshev to * the mplayer program. (http://mplayer.sourceforge.net) * * Miguel Freitas split the #ifdefs into several specialized functions that * are benchmarked at runtime by xine. Some original comments from Nick * have been preserved documenting some MMX/SSE oddities. * Also added kernel memcpy function that seems faster than glibc one. * * Copyright (c) 2010 Mensys BV * Copyright (c) 2007 Vlad Stelmahovsky aka Vladest * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License and the GNU General Public License along with this library. * If not, see . */ #include #include #include "fastmemcpy.h" #include "internal.h" void *(* fast_memcpy)(void *to, const void *from, size_t len); void * _memcpy(void * to, const void * from, size_t len); void * sse_memcpy(void * to, const void * from, size_t len); void * mmx_memcpy(void * to, const void * from, size_t len); void * mmx2_memcpy(void * to, const void * from, size_t len); #ifndef FASTMEMCPY_TEST int init_fast_memcpy(int mm_flgs) { if (mm_flgs & MM_MMXEXT) { // MMXEXT fast_memcpy = mmx2_memcpy; if (DebugMode) printf("Using MMXEXT for fastmemcpy\n"); return 0; } if (mm_flgs & MM_MMX) { // MMX fast_memcpy = mmx_memcpy; if (DebugMode) printf("Using MMX for fastmemcpy\n"); return 0; } if (mm_flgs & MM_SSE) { // SSE fast_memcpy = sse_memcpy; if (DebugMode) printf("Using SSE for fastmemcpy\n"); return 0; } fast_memcpy = _memcpy; if (DebugMode) printf("No accelerated fastmemcpy\n"); return 0; } #else #define INCL_DOSMISC #include #include #include "uniaud.h" #define BUFFER_SIZE 1024*1024 int main() { int x; int count = 500; char *src_buffer; char *dst_buffer; ULONG start_time, end_time; int mm_flags; mm_flags = mm_support(); printf("mm_flags=%x, size: %d, count: %d\n", mm_flags, BUFFER_SIZE, count); src_buffer = malloc(BUFFER_SIZE); dst_buffer = malloc(BUFFER_SIZE); // no optimised memcpy fast_memcpy = _memcpy; printf("\nTiming _memcpy...\n"); DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &start_time, sizeof(ULONG)); for(x = 0; x < count; x++) { fast_memcpy(dst_buffer, src_buffer, BUFFER_SIZE); } DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &end_time, sizeof(ULONG)); printf("no optimised: %d ms\n", end_time - start_time); if (mm_flags & MM_MMXEXT) { // mmx2 memcpy fast_memcpy = mmx2_memcpy; printf("\nTiming mmx2_memcpy...\n"); DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &start_time, sizeof(ULONG)); for(x = 0; x < count; x++) { fast_memcpy(dst_buffer, src_buffer, BUFFER_SIZE); } DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &end_time, sizeof(ULONG)); printf("mmx2: %d ms\n", end_time - start_time); } if (mm_flags & MM_MMX) { // mmx memcpy fast_memcpy = mmx_memcpy; printf("\nTiming mmx_memcpy...\n"); DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &start_time, sizeof(ULONG)); for(x = 0; x < count; x++) { fast_memcpy(dst_buffer, src_buffer, BUFFER_SIZE); } DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &end_time, sizeof(ULONG)); printf("mmx: %d ms\n", end_time - start_time); } if (mm_flags & MM_SSE) { // sse memcpy fast_memcpy = sse_memcpy; printf("\nTiming sse_memcpy...\n"); DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &start_time, sizeof(ULONG)); for(x = 0; x < count; x++) { fast_memcpy(dst_buffer, src_buffer, BUFFER_SIZE); } DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &end_time, sizeof(ULONG)); printf("sse: %d ms\n", end_time - start_time); } return(0); } #endif