
Bitwise functions, for Euphoria 2.4 or higher.
All functions are written in assembler, as M.S. standard calls.

The functions can be called in two different ways:

1) as a standard Euphoria function
   x = rol_d(n,p)

2) as a external C function
   x = c_func(ROL_D,{n,p})
   - the address is the function name in uppercase
   - Euphoria 2.5, calling the simpler functions like ROL_D in this manner can be 2 to 4 times faster
   - than using the wrapped function. For more complex functions like BIT_TEST there is little
   - difference between using c_func(BIT_TEST,{n,p}) and the wrapped function, bit_test(n,p).

BITS.E is getting to be fairly large, most of the functions require only the constant DWORD and 
define_asm_func(), you can just copy and paste what's needed into your code rather than
including the whole file.

The functions:

-- Rotate ---------------------------------------------------------------------

rol_d(atom n, integer p) : function
 - Left rotate 32 bit n by p  bit 31 moves around to bit 0

ror_d(atom n, integer p) : function
 - Right rotate 32 bit n by p  bit 0 moves around to bit 31

rol_w(atom n, integer p) : function
 - Left rotate 16 bit n by p  bit 15 moves around to bit 0
 - bits 16-31 are unaffected
 
ror_w(atom n, integer p) : function
 - Right rotate 16 bit n by p  bit 0 moves around to bit 15
 - bits 16-31 are unaffected

rol_b(atom n, integer p) : function
 - Left rotate 8 bit n by p  bit 7 moves around to bit 0
 - bits 8-31 are unaffected
 
ror_b(atom n, integer p) : function
 - Right rotate 8 bit n by p  bit 0 moves around to bit 7
 - bits 8-31 are unaffected

-- Logical Shift --------------------------------------------------------------

shl_d(atom n, integer p) : function
 - Left shift 32 bit n by p  low order bits vacated by shift are filled with 0

shr_d(atom n, integer p) : function
 - Right shift 32 bit n by p  high order bits vacated by shift are filled with 0

shl_w(atom n, integer p) : function
 - Left shift 16 bit n by p  low order bits vacated by shift are filled with 0
 - bits 16-31 are unaffected

shr_w(atom n, integer p) : function
 - Right shift 16 bit n by p  high order bits vacated by shift are filled with 0
 - bits 16-31 are unaffected

shl_b(atom n, integer p) : function
 - Left shift 8 bit n by p  low order bits vacated by shift are filled with 0
 - bits 7-31 are unaffected

shr_b(atom n, integer p) : function
 - Right shift 8 bit n by p  high order bits vacated by shift are filled with 0
 - bits 7-31 are unaffected

-- Bit Scan -------------------------------------------------------------------

bit_scanf(atom n) : function
 - find the least significant set bit
 - scans from the least to most significant bit
 - returns -1 if no bit is set otherwise returns the position of first set bit
 - bit 0 is least significant bit 31 is most significant

bit_scanr(atom n) : function
 - find most significant set bit
 - scans from bit 31 down to bit 0
 - returns -1 if no bit is set otherwise returns the position of last set bit

-- Bit Test & Set -------------------------------------------------------------

bit_test(atom n, integer bit) : function
 - returns 1 (TRUE) if bit is set otherwise returns 0 (FALSE)

clr_bit(atom n, integer bit) : function
 - sets bit in n to 0

set_bit(atom n, integer bit) : function
 - sets bit in n to 1

not_bit(atom n, integer bit) : function
 - inverts bit in n

-- Byte Swap ------------------------------------------------------------------

bswp_d(atom n) : function
 - reverses the order of bytes in a 32 bit number
 - bits 0-7 <-> bits 24-31  bits 8-15 <-> bits 16-23

bswp_w(atom n) : function
 - swaps the bytes in the low order word
 - bits 0-7 <-> bits 8-15
 - bits 16-31 are unaffected

-- Word Swap ------------------------------------------------------------------

wswp_d(atom n) : function
 - swaps the high and low order 16 bit words in a 32 bit integer
 - bits 0-15 <-> bits 16-31

-- Cpu Id ---------------------------------------------------------------------

cpu_id(integer input) : function
 - returns 4 unsigned dwords with information about the processor
 - see cpu_id in bits.e for a brief documentation
 - or pg. 151 in the Intel Instruction Set Reference  24319102.PDF
 - also this web page, http://www.sandpile.org/ia32/cpuid.htm

-- Block Move -----------------------------------------------------------------

blkmov(atom destination, atom source, atom ccnt) : procedure 
 - the same as Euphoria mem_copy()
 - Smart move (won't overwrite it's self) moves 64 byte blocks with movsd,
 - using MMX registers you only gain about 7-8% and complicate the code.
 - Not really worth it from my point of view.
 
-------------------------------------------------------------------------------

A table ( pwrs2 ) of powers of 2 from 0 thru 32 is also available.

The function below is quite a bit faster than the wrapped assembler function
shl_d(n,p) and only a little slower than c_func(SHL_D,{n,p}). It will however
break if called with p<0 or p>31. The same is true for shr_d() and bit_test(),
both will be faster as Euphoria routines.

function lshift(atom n, integer p)
    return floor(n*pwrs2[p+1]) 
end function

There are also some constants and macros for writing assembler functions,
procedures, building stack frames and such at the beginning of bits.e.

-------------------------------------------------------------------------------
New Stuff added Jan 6 2005
-------------------------------------------------------------------------------

-- Debug ----------------------------------------------------------------------

See the source code for ICEBP and BREAK. There is a truly excellent Windows
debugger at, http://www.ollydbg.de/, it's free.


-- Search and Compare ---------------------------------------------------------

byte_scan(integer b, atom addr, integer ccnt) : function
 - scans for byte b from address addr up to addr + ccnt
 - returns the address of the first occurrence of b if matched
 - otherwise returns 0

word_scan(integer w, atom addr, integer ccnt) : function
 - same as byte_scan() but searches for a 16 bit WORD

dword_scan(atom d, atom addr, integer ccnt) : function
 - same as byte_scan() but searches for a 32 bit DWORD

char_scan(integer c, atom addr, atom ccnt, integer f) : function
 - like byte_scan with the following exception
 - if f = 0 char_scan is case sensitive
 - if f <> 0 the scan is case insensitive

cmps(atom addr1, atom addr2, atom ccnt, integer f) : function
 - compare string at addr1 to string at addr2
 - ccnt is the number of bytes to compare
 - if f = 0 the comparison is case sensitive
 - if f <> 0 comparison is case insensitive
 - returns 1 (TRUE) if strings match otherwise returns 0 (FALSE)

finds(sequence s, atom addr, atom ccnt, integer f) : function
 - this is actually a mixed euphoria assembler function
 - searches memory from addr up to addr + ccnt for string s
 - integer f is the case flag as above
 - returns the address at which the string was matched
 - or 0 if no match was made

-- Hash Code ------------------------------------------------------------------

hash_string(atom addr, integer ccnt) : function
 - atom addr is the address of a string in memory
 - ccnt is the number of characters (string length)
 - returns a 32 bit (atom) hash key for the string

 - this is a simple 32 bit hash code generator, it's not
 - guaranteed to produce unique keys 100% of the time it, but
 - should be good enough for hashing variable names and such things.
 - a web search for 'Perfect Hash Function' or 'Perfect Hashing' will
 - get you plenty of information if you need a better function.

 - Please see the comments about hash_string() in bits.e,
 - for integer returns and other programming considerations.

-------------------------------------------------------------------------------

Mike Duffy
e-mail: eagleranchco@frontiernet.net
