|
|
uae-0.6.8
/*
* UAE - The Un*x Amiga Emulator
*
* Miscellaneous machine dependent support functions and definitions
*
* Copyright 1996 Bernd Schmidt
*/
#include "sysconfig.h"
#include "sysdeps.h"
#include "config.h"
#include "options.h"
#include "machdep/m68k.h"
#include "machdep/penguin.h"
struct flag_struct regflags;
/*
* Careful: No unique labels. Unfortunately, not each installation of GCC
* comes with GAS. Bletch.
*/
int fast_memcmp(const void *foo, const void *bar, int len)
{
int differs, baz;
__asm__ __volatile__ ("subl $4, %2\n"
"jc LLA2\n"
"LLA1:\n"
"movl (%0),%%ebx\n"
"cmpl (%1),%%ebx\n"
"jne LLA5\n"
"addl $4, %0\n"
"addl $4, %1\n"
"subl $4, %2\n"
"jnc LLA1\n"
"LLA2:\n"
"addl $4, %2\n"
"jz LLA4\n"
"LLA3:\n"
"movb (%0),%%bl\n"
"cmpb (%1),%%bl\n"
"jne LLA5\n"
"incl %0\n"
"incl %1\n"
"decl %2\n"
"jnz LLA3\n"
"LLA4:\n"
"movl $0, %3\n"
"jmp LLA6\n"
"LLA5:\n"
"movl $1, %3\n"
"LLA6:\n"
: "=&r" (foo), "=&r" (bar), "=&rm" (len), "=rm" (differs),
"=&b" (baz)
: "0" (foo), "1" (bar), "2" (len), "3" (baz) : "cc");
return differs;
}
int memcmpy(void *foo, const void *bar, int len)
{
int differs, baz = 0, uupzuq = 0;
__asm__ __volatile__ ("subl %1, %2\n"
"subl $16, %3\n"
"jc LLB7\n"
".align 16\n"
"LLB8:\n"
"movl (%2,%1),%%ebx\n"
"movl (%1),%%ecx\n"
"cmpl %%ebx, %%ecx\n"
"jne LLC1\n"
"movl 4(%2,%1),%%ebx\n"
"movl 4(%1),%%ecx\n"
"cmpl %%ebx, %%ecx\n"
"jne LLC2\n"
"movl 8(%2,%1),%%ebx\n"
"movl 8(%1),%%ecx\n"
"cmpl %%ebx, %%ecx\n"
"jne LLC3\n"
"movl 12(%2,%1),%%ebx\n"
"movl 12(%1),%%ecx\n"
"cmpl %%ebx, %%ecx\n"
"jne LLC4\n"
"addl $16, %1\n"
"subl $16, %3\n"
"jnc LLB8\n"
"LLB7:\n"
"addl $16, %3\n"
"subl $4, %3\n"
"jc LLB2\n"
"LLB1:\n"
"movl (%2,%1),%%ebx\n"
"movl (%1),%%ecx\n"
"cmpl %%ebx, %%ecx\n"
"jne LLC5\n"
"addl $4, %1\n"
"subl $4, %3\n"
"jnc LLB1\n"
"LLB2:\n"
"addl $4, %3\n"
"jz LLB6\n"
"LLB3:\n"
"movb (%2,%1),%%bl\n"
"movb (%1),%%cl\n"
"cmpb %%bl,%%cl\n"
"jne LLC6\n"
"incl %1\n"
"decl %3\n"
"jnz LLB3\n"
"LLB6:\n"
"movl $0,%0\n"
"jmp LLB9\n"
".align 16\n"
/* Once we find a difference, we switch to plain memcpy() */
"LLC01:\n"
"movl (%2,%1),%%ebx\n"
"LLC1:\n"
"movl %%ebx, (%1)\n"
"movl 4(%2,%1),%%ebx\n"
"LLC2:\n"
"movl %%ebx, 4(%1)\n"
"movl 8(%2,%1),%%ebx\n"
"LLC3:\n"
"movl %%ebx, 8(%1)\n"
"movl 12(%2,%1),%%ebx\n"
"LLC4:\n"
"movl %%ebx, 12(%1)\n"
"addl $16, %1\n"
"subl $16, %3\n"
/* There's a choice here whether we want to jump to LLB8 or LLC01. Jumping to LLB8
* might be a little more efficient if there's little change in the line, but is
* probably a loss if the line is completely different. */
"jnc LLC01\n"
"addl $16, %3\n"
"subl $4, %3\n"
"jc LLC03\n"
"LLC02:\n"
"movl (%2,%1),%%ebx\n"
"LLC5:\n"
"movl %%ebx, (%1)\n"
"addl $4, %1\n"
"subl $4, %3\n"
"jnc LLC02\n"
"LLC03:\n"
"addl $4, %3\n"
"jz LLC05\n"
"LLC04:\n"
"movb (%2,%1),%%bl\n"
"LLC6:\n"
"movb %%bl,(%1)\n"
"incl %1\n"
"decl %3\n"
"jnz LLC04\n"
"LLC05:\n"
"movl $1,%0\n"
"LLB9:"
: "=m" (differs)
: "r" (foo), "r" (bar), "r" (len), "b" (baz), "c" (uupzuq) : "cc", "memory");
/* Now tell the compiler that foo, bar and len have been modified
* If someone finds a way to express all this cleaner in constraints that
* GCC 2.7.2 understands, please FIXME */
__asm__ __volatile__ ("" : "=rm" (foo), "=rm" (bar), "=rm" (len) : : "ebx", "ecx", "edx", "eax", "esi", "memory");
return differs;
}
#ifdef SUPPORT_PENGUINS
#include <linux/sched.h>
#include <linux/unistd.h>
static __inline__ _syscall2 (int, clone, unsigned long, flags, void *, sp);
penguin_id start_penguin (void (*f) ())
{
penguin_id n;
n = clone (CLONE_VM | CLONE_FILES | CLONE_FS | SIGCHLD, ((char *)malloc (10000)) + 8000 /* Whatever */);
if (n == 0) {
f();
printf("Penguin returned!\n");
abort();
}
return n;
}
#endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.