syn68k/runtime/include/checksum.h
2008-09-26 08:25:10 -06:00

69 lines
1.7 KiB
C

#ifndef _checksum_h_
#define _checksum_h_
#include "syn68k_private.h"
#ifdef CHECKSUM_BLOCKS
#include "block.h"
extern uint32 compute_block_checksum (const Block *b);
#ifdef INLINE_CHECKSUM
#include "callback.h"
static __inline__ uint32
inline_compute_block_checksum (const Block *b)
{
const uint16 *code;
uint32 sum;
long n;
syn68k_addr_t start;
/* Don't actually checksum the bytes at a callback! */
start = b->m68k_start_address;
if (IS_CALLBACK (start))
return (start
+ (unsigned long) callback_argument (start)
+ (unsigned long) callback_function (start));
else if (start >= MAGIC_ADDRESS_BASE
&& start < CALLBACK_STUB_BASE)
return 0;
code = SYN68K_TO_US (start);
for (sum = 0, n = b->m68k_code_length / sizeof (uint16); --n >= 0; )
{
/* Bizarre but fast checksum. A good checksum like CRC is
* probably too slow.
*/
#if defined (__GNUC__) && defined(i386)
uint32 tmp1, tmp2;
/* This is taking lots of CPU time for HyperCard, and gcc was generating
* lousy code, so I've hand-coded and hand-scheduled this for the
* Pentium. This should do the same thing as the C code below.
*/
asm ("movl %0,%2\n\t"
"movl %0,%1\n\t"
"sall $5,%2\n\t"
"shrl $14,%1\n\t"
"addl %0,%2\n\t"
"xorl %2,%1\n\t"
"xorw (%4,%5,2),%w0\n\t"
"xorl %1,%0"
: "=r" (sum), "=&r" (tmp1), "=&r" (tmp2)
: "0" (sum), "r" (code), "r" (n)
: "cc");
#else /* !__GNUC__ || !i386 */
sum = (sum >> 14) ^ (sum * 33) ^ code[n];
#endif /* !__GNUC__ || !i386 */
}
return sum;
}
#endif /* INLINE_CHECKSUM */
#endif /* CHECKSUM_BLOCKS */
#endif /* Not _checksum_h_ */