/*
* 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