mirror of
https://github.com/ctm/syn68k.git
synced 2024-11-29 03:50:27 +00:00
69 lines
1.7 KiB
C
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_ */
|