#include "bittables.h"
#include "piece.h"
#include "bitmagic.h"
#include "bitpsq.h"
#include "core/core.h"
#include "zobrist.h"
#ifdef _MSC_VER
#include <intrin.h>
#pragma intrinsic(_BitScanForward64)
#pragma intrinsic(_BitScanReverse64)
#endif
// bit counts for each 16-bit parts
u8 bitCount16[ 65536 ];
i64 bitPos8[256];			// bit->pos extract table
i64 rankPos[8];				// rank pos or table
u64 knightMov[64];			// knight move table for each position
u64 kingMov[64];			// king move/attack table for each position
i8 stopRay[64];				// stop-ray table (xtra, nothing to do with bittables)
u64 oneShlTab[64];
u64 noneShlTab[64];
u8 diagFlags[64][64];		// diag flags [piece position][king position]
// values 0-8: l, ul, u, ur, r, dr, d, dl, none
u64 diagMask[9][64];		// diag mask [diag flag][king position]
u64 diagAttMask[64];		// diag-attack mask for a given position
u64 orthoAttMask[64];		// ortho-attack mask for a given position
u64 allAttMask[64];			// all-attack mask for a given position

i8 lsbit16[65536];
i8 msbit16[65536];

i8 knightAttk[64][64];		// knight-attack table (not bitbased)
i8 bishopDiag[64][64];		// bishop-diagonal-danger flags (not bitbased)
i8 rookDiag[64][64];		// rook-diagonal-danger flags (not bitbased)

u64 wpAttm[64];				// white-pawns attack mask for a given position
u64 bpAttm[64];				// black-pawns attack mask for a given position

u64 fileMask[8];			// file mask, indexed by file index (0=a, 7=h)
u8 kdistTab[64][64];		// king-piece distance table in king moves
u8 kproxTab[64][64];		// king proximity table [king][pos], returns 1 if close to king
u64 betweenMask[64][64];	// for diag/ortho sliders: squares between [from][to] squares, not including from, to
// or 0 if invalid
u8 sliderValid[64][64];		// slider validity table:
// [from][to] & (1 << piece_type)

u64 sideCoverMask[2][64];	// king side cover mask (for own pawns) [turn][kpos]
u64 sideCoverMaskFixed[2][64];	// king side cover mask (for own pawns) [turn][kpos] (up to 2 rows in front of)
u64 passPawnMask[2][64];	// passed pawn mask [turn][pawnpos]
// if there're no enemy pawns in this mask it's a passed pawn!

u64 frontMask[2][64];		// front_squares_mask [turn][pos] (same_file_only)
u64 backMask[2][64];		// back_squares_mask [turn][pos] (same_file_only)

u64 isoPawnMask[64];		// isolated pawn mask [pos] (if there're no friendly pawns on adjacent files => isolated)

void initSkipTab();			// declared in board.cpp

void bitInit()
{
	initZobrist();
    i32 i, j;

    // init distance table
    for (i=0; i<64; i++)
    {
        i32 j;
        i32 x0, y0;
        x0 = i & 7;
        y0 = i >> 3;
        for (j=0; j<64; j++)
        {
            i32 x1, y1;
            x1 = j & 7;
            y1 = j >> 3;
            i32 dx = abs( x1 - x0 );
            i32 dy = abs( y1 - y0 );
            kdistTab[ i ][ j ] = (dx >= dy) ? dx : dy;
            kproxTab[ i ][ j ] = (dx <= 1) && (dy <= 1);
        }
    }

    for (i=0; i<8; i++)
    {
        u64 t = (u64)1 << i;
        t |= t << 8;
        t |= t << 8;
        t |= t << 8;
        t |= t << 8;
        t |= t << 8;
        t |= t << 8;
        t |= t << 8;
        fileMask[i] = t;
    }
    for (i=0; i<64; i++)
    {
        oneShlTab[i] = (u64)1 << i;
        noneShlTab[i] = ~oneShlTab[i];
        stopRay[i] = ((i+7) / 7 * 7) - 1;
        // build wpAttm, bpAttm

        u64 t = oneShlTab[i];
        wpAttm[ i ] = (( t << 9 ) & L1MASK) | (( t << 7 ) & R1MASK);
        bpAttm[ i ] = (( t >> 9 ) & R1MASK) | (( t >> 7 ) & L1MASK);
    }
    initSkipTab();
    // build diagFlags table
    for (i=0; i<64; i++)
    {
        i32 x = i & 7, y = i >> 3;
        for (j=0; j<64; j++)
        {
            i32 kx = j & 7, ky = j >> 3;
            i32 dx = kx - x;
            i32 dy = ky - y;
            u8 res = 8;
            if ( dy == 0 && dx )
            {
                res = (dx > 0) ? 0 : 4;
            }
            if ( dx == 0 && dy )
            {
                res = (dy > 0) ? 2 : 6;
            }
            if ( abs(dx) == abs(dy) )
            {
                if ( dx > 0 && dy > 0 )
                    res = 1;
                if ( dx < 0 && dy > 0 )
                    res = 3;
                if ( dx < 0 && dy < 0 )
                    res = 5;
                if ( dx > 0 && dy < 0 )
                    res = 7;
            }
            diagFlags[ i ][ j ] = res;
        }
    }
    // build diagMask table
    for (i=0; i<=8; i++)
    {
        for (j=0; j<64; j++)
        {
            u64 b = (u64)1 << j;
            i32 k;
            u64 m = 0;
            switch (i)
            {
            case 0:
                m = b;
                for (k=0; k<7; k++)
                {
                    m |= (m >> 1) & R1MASK;
                }
                break;
            case 1:
                m = b;
                for (k=0; k<7; k++)
                {
                    m |= (m >> 9) & R1MASK;
                }
                break;
            case 2:
                m = b;
                for (k=0; k<7; k++)
                {
                    m |= (m >> 8);
                }
                break;
            case 3:
                m = b;
                for (k=0; k<7; k++)
                {
                    m |= (m >> 7) & L1MASK;
                }
                break;
            case 4:
                m = b;
                for (k=0; k<7; k++)
                {
                    m |= (m << 1) & L1MASK;
                }
                break;
            case 5:
                m = b;
                for (k=0; k<7; k++)
                {
                    m |= (m << 9) & L1MASK;
                }
                break;
            case 6:
                m = b;
                for (k=0; k<7; k++)
                {
                    m |= (m << 8);
                }
                break;
            case 7:
                m = b;
                for (k=0; k<7; k++)
                {
                    m |= (m << 7) & R1MASK;
                }
                break;
            }
            diagMask[i][j] = m & ~b;
        }
    }
    for (i=0; i<65536; i++)
    {
        i32 bc = 0;
        for (j=0; j<16; j++)
        {
            if ( i & (1 << j) )
                bc++;
        }
        bitCount16[ i ] = bc;

        for (j=0; j<16; j++)
        {
            if ( i & (1<<j) )
                break;
        }
        lsbit16[ i ] = j < 16 ? j : -1;

        for (j=15; j>=0; j--)
        {
            if ( i & (1<<j) )
                break;
        }
        msbit16[ i ] = j;
    }
    for (i=0; i<64; i++)
    {
        u64 b = (u64)1 << i;
        u64 t = 0;
        t |= (b << 17) & L1MASK;
        t |= (b << 15) & R1MASK;
        t |= (b >> 17) & R1MASK;
        t |= (b >> 15) & L1MASK;
        t |= (b << 10) & L2MASK;
        t |= (b << 6) & R2MASK;
        t |= (b >> 10) & R2MASK;
        t |= (b >> 6) & L2MASK;
        knightMov[i] = t;

        t = 0;
        t |= (b << 1) & L1MASK;
        t |= (b >> 1) & R1MASK;
        t |= (t << 8);
        t |= (t >> 8);
        t |= (b << 8);
        t |= (b >> 8);
        kingMov[i] = t;
    }
    for (i=0; i<8; i++)
    {
        u64 t = i<<3;
        t |= t << 8;
        t |= t << 16;
        t |= t << 32;
        rankPos[i] = t;
    }
    for (i=0; i<256; i++)
    {
        i64 t = -1;
        for (j=0; j<8; j++)
        {
            if ( i & (1<<j) )
            {
                // add_pos...
                t <<= 8;
                t |= j;
            }
        }
        bitPos8[ i ] = t;
    }
    // build allAttMask
    for (i=0; i<64; i++)
    {
        u64 m = oneShlTab[ i ];
        i32 j;

        u64 diag = 0, ortho = 0, all = 0;

        u64 b;

        b = m;
        for (j=0; j<8; j++)
        {
            b = ( b << 9 ) & L1MASK;
            if ( !b )
                break;
            diag |= b;
            all |= b;
        }
        b = m;
        for (j=0; j<8; j++)
        {
            b = ( b << 7 ) & R1MASK;
            if ( !b )
                break;
            diag |= b;
            all |= b;
        }
        b = m;
        for (j=0; j<8; j++)
        {
            b = ( b >> 9 ) & R1MASK;
            if ( !b )
                break;
            diag |= b;
            all |= b;
        }
        b = m;
        for (j=0; j<8; j++)
        {
            b = ( b >> 7 ) & L1MASK;
            if ( !b )
                break;
            diag |= b;
            all |= b;
        }

        b = m;
        for (j=0; j<8; j++)
        {
            b = ( b << 1 ) & L1MASK;
            if ( !b )
                break;
            ortho |= b;
            all |= b;
        }
        b = m;
        for (j=0; j<8; j++)
        {
            b = ( b >> 1 ) & R1MASK;
            if ( !b )
                break;
            ortho |= b;
            all |= b;
        }
        b = m;
        for (j=0; j<8; j++)
        {
            b >>= 8;
            if ( !b )
                break;
            ortho |= b;
            all |= b;
        }
        b = m;
        for (j=0; j<8; j++)
        {
            b <<= 8;
            if ( !b )
                break;
            ortho |= b;
            all |= b;
        }

        diagAttMask[ i ] = diag;
        orthoAttMask[ i ] = ortho;
        allAttMask[ i ] = all | knightMov[ i ];
    }
    for (i=0; i<64; i++)
    {
        i32 j;
        i32 x, y;
        x = i & 7;
        y = i >> 3;
        for (j=0; j<64; j++)
        {
            i32 nx = j & 7;
            i32 ny = j >> 3;
            i32 dx, dy;
            dx = abs(nx - x);
            dy = abs(ny - y);
            knightAttk[ i ][ j ] = (dx == 1 && dy == 2) || (dx == 2 && dy == 1 );
            bishopDiag[ i ][ j ] = dx == dy;
            rookDiag[ i ][ j ] = !dx || !dy;
        }
    }
    // build "between" mask table
    for (i=0; i<64; i++)
    {
        i32 j;
        i32 x = (i & 7);
        i32 y = (i >> 3);
        for (j=0; j<64; j++)
        {
            sliderValid[i][j] = 0;
            u64 msk = 0;
            if ( i == j )
            {
                betweenMask[i][j] = 0;
                continue;
            }
            i32 x0 = (j & 7);
            i32 y0 = (j >> 3);

            i32 dx = x0 - x;
            i32 dy = y0 - y;

            if ( abs(dx) == 2 && abs(dy) == 1 )
            {
                sliderValid[i][j] |= (1 << knight);
            }
            if ( abs(dx) == 1 && abs(dy) == 2 )
            {
                sliderValid[i][j] |= (1 << knight);
            }

            i32 xinc = 0, yinc = 0;
            if ( !dx )
            {
                // vertical
                sliderValid[i][j] |= (1 << rook) | (1 << queen);
                if ( abs(dy) == 1 )
                {
                    sliderValid[i][j] |= (1 << pawn);		// pawn advance
                    sliderValid[i][j] |= (1 << king);
                }
                if ( (i >> 3) == 1 && dy == 2 )
                {
                    sliderValid[i][j] |= (1 << pawn);		// black pawn advance by 2
                }
                if ( (i >> 3) == 6 && dy == -2 )
                {
                    sliderValid[i][j] |= (1 << pawn);		// white pawn advance by 2
                }
                yinc = dy > 0 ? 1 : -1;
            }
            else if ( !dy )
            {
                // horizontal
                // FIXME: castling not handled here. ok?! I think so!
                if ( abs(dx) == 1 )
                {
                    sliderValid[i][j] |= (1 << king);
                }
                sliderValid[i][j] |= (1 << rook) | (1 << queen);
                xinc = dx > 0 ? 1 : -1;
            }
            else if ( abs(dx) == abs(dy) )
            {
                // diagonal
                sliderValid[i][j] |= (1 << bishop) | (1 << queen);
                if ( abs(dx) == 1 && abs(dy) == 1 )
                {
                    sliderValid[i][j] |= (1 << pawn);		// pawn capture
                    sliderValid[i][j] |= (1 << king);
                }

                xinc = dx > 0 ? 1 : -1;
                yinc = dy > 0 ? 1 : -1;
            }
            else
            {
                // invalid
                betweenMask[i][j] = 0;
                continue;
            }
            i32 tx = x;
            i32 ty = y;
            i32 k;
            for (k=0; k<8; k++)
            {
                tx += xinc;
                ty += yinc;
                if ( (u32)tx >= 8 || (u32)ty >= 8 )
                {
                    msk = 0;
                    break;				// out => should never happen!
                }
                i32 sq = (ty << 3) | tx;
                if ( sq == j )
                    break;
                msk |= oneShlTab[ sq ];
            }
            betweenMask[i][j] = msk;
        }
    }
    // build side cover masks
    for (i=0; i<2; i++)
    {
        i32 j;
        for (j=0; j<64; j++)
        {
            u64 t = oneShlTab[j];
            sideCoverMask[i][j] = 0;
            i32 kpx = j & 7;
            u64 b0 = 0, b1 = 0;
            if ( kpx <= 1 )
            {
                if ( kpx == 0 )
                {
                    if ( i == white )
                    {
                        b0 = (t >> 7) & L1MASK;
                        b1 = t >> 8;
                    }
                    else
                    {
                        b0 = (t << 9) & R1MASK;
                        b1 = t << 8;
                    }
                }
                else
                {
                    u64 l = (j & ~7) | 0;		// left-bit
                    b0 = oneShlTab[l];
                    b1 = (i == white) ? t >> 8 : t << 8;
                }
            }
            else if ( kpx >= 6 )
            {
                if ( kpx == 7 )
                {
                    if ( i == white )
                    {
                        b0 = (t >> 9) & R1MASK;
                        b1 = t >> 8;
                    }
                    else
                    {
                        b0 = (t << 7) & L1MASK;
                        b1 = t << 8;
                    }
                }
                else
                {
                    u64 r = (j & ~7) | 7;		// right-bit
                    b0 = oneShlTab[r];
                    b1 = (i == white) ? t >> 8 : t << 8;
                }
            }
            i32 k;
            for (k=0; k<8; k++)
            {
                if ( i == white )
                {
                    b0 |= b0 >> 8;
                    b1 |= b1 >> 8;
                }
                else
                {
                    b0 |= b0 << 8;
                    b1 |= b1 << 8;
                }
            }
            sideCoverMask[i][j] = b0 | b1;
#if 0
            if ( sideCoverMask[i][j] )
            {
                char pos[3] = {0,0,0};
                pos[0] = 'a' + (j & 7);
                pos[1] = '8' - (j / 8);
                logFmt("color: %d position: %s mask: %I64x\n", i, pos, sideCoverMask[i][j]);
                // dump_squares!
                u8 ps[64];
                i32 npos = getPos( sideCoverMask[i][j], ps );
                i32 k;
                logFmt("squares_mask: ");
                for (k=0; k<npos; k++)
                {
                    u8 p = ps[k];
                    pos[0] = 'a' + (p & 7);
                    pos[1] = '8' - (p / 8);
                    logFmt("%s ", pos);
                }
                logFmt("\n");
            }
#endif
        }
    }
    // build fixed sidecover masks
    for (i=0; i<2; i++)
    {
        i32 j;
        for (j=0; j<64; j++)
        {
            sideCoverMaskFixed[i][j] = sideCoverMask[i][j];
            u64 msk = U64C(0) - 1;

            i32 y = j >> 3;

            if ( i == white )
            {
                msk = U64C(0xff) << (y*8);
                msk |= msk >> 8;
                msk |= msk >> 8;
            }
            else
            {
                msk = U64C(0xff) << (y*8);
                msk |= msk << 8;
                msk |= msk << 8;
            }

            if ( i == white && j < 32 )
                msk = 0;
            else
                if ( i == black && j >= 32 )
                    msk = 0;

            sideCoverMaskFixed[i][j] &= msk;
#if 0
            if ( sideCoverMaskFixed[i][j] )
            {
                char pos[3] = {0,0,0};
                pos[0] = 'a' + (j & 7);
                pos[1] = '8' - (j / 8);
                logFmt("color: %d position: %s mask: %I64x\n", i, pos, sideCoverMaskFixed[i][j]);
                // dump_squares!
                u8 ps[64];
                i32 npos = getPos( sideCoverMaskFixed[i][j], ps );
                i32 k;
                logFmt("squares_mask: ");
                for (k=0; k<npos; k++)
                {
                    u8 p = ps[k];
                    pos[0] = 'a' + (p & 7);
                    pos[1] = '8' - (p / 8);
                    logFmt("%s ", pos);
                }
                logFmt("\n");
            }
#endif
        }
    }
    // build passpawn masks
    for (i=0; i<2; i++)
    {
        i32 j;
        for (j=0; j<64; j++)
        {
            u64 t = oneShlTab[j];
            t |= (t >> 1) & R1MASK;
            t |= (t << 1) & L1MASK;
            i32 k;
            if ( i == white )
            {
                t >>= 8;
            }
            else
            {
                t <<= 8;
            }
            for (k=0; k<8; k++)
            {
                t |= (i == white) ? t >> 8 : t << 8;
            }
            passPawnMask[i][j] = t;
        }
    }

    // front/backMask tables:
    for (i=0; i<2; i++)
    {
        i32 j;
        for (j=0; j<64; j++)
        {
            u64 b = oneShlTab[j];
            if ( i == white )
            {
                // front
                u64 t = b >> 8;
                i32 k;
                for (k=0; k<8; k++)
                {
                    t |= t >> 8;
                }
                frontMask[i][j] = t;
                // back
                t = b << 8;
                for (k=0; k<8; k++)
                {
                    t |= t << 8;
                }
                backMask[i][j] = t;
            }
            else
            {
                // front
                u64 t = b << 8;
                i32 k;
                for (k=0; k<8; k++)
                {
                    t |= t << 8;
                }
                frontMask[i][j] = t;
                // back
                t = b >> 8;
                for (k=0; k<8; k++)
                {
                    t |= t >> 8;
                }
                backMask[i][j] = t;
            }
        }
    }

    // isolated pawn masks
    for (i=0; i<64; i++)
    {
        u64 t = fileMask[ i & 7 ];
        isoPawnMask[ i ] = ((t << 1) & L1MASK) | ((t >> 1) & R1MASK);
    }

#if 0
    // build random ordering table
    Random rg;
    for (i=0; i<=256; i++)
    {
        u8 ord[256];
        i32 j;
        for (j=0; j<i; j++)
        {
            randomOrderingTable[i][j] = j;
        }
        for (j=0; j<i; j++)
        {
            // do_permutations!
            i32 a = (u32)rg.rand32() % i;
            i32 b = (u32)rg.rand32() % i;
            std::swap( randomOrderingTable[i][a], randomOrderingTable[i][b] );
        }
    }
#endif
    bitMagicInit();
    initPSQ();
}

#define BSFLO	\
	__asm bsf eax, esi	\
	__asm jz _done1	\
	__asm mov [ebx], al	\
	__asm btc esi, eax	\
	__asm inc ebx	\
 
#define BSFLO4	\
	BSFLO	\
	BSFLO	\
	BSFLO	\
	BSFLO

#define BSFLO16	\
	BSFLO4	\
	BSFLO4	\
	BSFLO4	\
	BSFLO4

#define BSFHI	\
	__asm bsf eax, edi	\
	__asm jz _done2	\
	__asm btc edi, eax	\
	__asm lea eax, [eax + 32]	\
	__asm mov [ebx], al	\
	__asm inc ebx	\
 
#define BSFHI4	\
	BSFHI	\
	BSFHI	\
	BSFHI	\
	BSFHI

#define BSFHI16	\
	BSFHI4	\
	BSFHI4	\
	BSFHI4	\
	BSFHI4

i32 getLSB( u64 m )
{
#ifndef _MSC_VER
#if defined(__GNUC__) && defined(__i386__)
    i32 res;
    asm(
        "bsfl (%1),%%eax;"
        "jnz 0f;"
        "bsfl 4(%1),%%eax;"
        "jnz 1f;"
        "movl $-1,%%eax;"
        "1:orl $0x20,%%eax;"
        "0:movl %%eax,%0" :
              "=r" (res) :
              "r" (&m) :
              "eax"
    );
    return res;
#else
    i32 i;
    for (i=0; m && i<4*16; i+=16, m >>= 16)
    {
        u16 p = (u16)m;
        if ( !p )
            continue;
        return lsbit16[ p ] + i;
    }
    return -1;
#endif
#else
#if defined ( _M_AMD64 ) || defined ( _M_X64 )
   unsigned long index;
   unsigned char isNonzero;
   isNonzero = _BitScanForward64(&index, m);
   return index;
#else
	ASSERT( m != 0 );
    __asm
    {
//		mov esi, dword ptr [m]
//		mov edi, dword ptr [m+4]
        bsf eax, dword ptr [m]		//esi
        jnz done
        bsf eax, dword ptr [m+4]	//edi
/*        jnz done1
        mov eax, -1
#if defined(DEBUG) || defined(_DEBUG)
		int 1
#endif*/
done1:
        or eax, 32
done:
    }
#endif
#endif
}

i32 popLSB( u64 &m )
{
    i32 res = getLSB(m);
//	if ( res >= 0 )
//	{
    m &= noneShlTab[ res ];
//	}
    return res;
}

i32 getMSB( u64 m )
{
#ifndef _MSC_VER
#if defined(__GNUC__) && defined(__i386__)
    i32 res;
    asm(
        "bsrl 4(%1),%%eax;"
        "jnz 1f;"
        "bsrl (%1),%%eax;"
        "jnz 0f;"
        "movl $-1,%%eax;"
        "1:orl $0x20,%%eax;"
        "0:movl %%eax,%0" :
              "=r" (res) :
              "r" (&m) :
              "eax"
    );
    return res;
#else
    i32 i;
    for (i=3*16; m && i>=0; i-=16, m <<= 16)
    {
        u16 p = (u16)(m >> 48);
        if ( !p )
            continue;
        return msbit16[ p ] + i;
    }
    return -1;
#endif
#else
#if defined ( _M_AMD64 ) || defined ( _M_X64 )
   unsigned long index;
   unsigned char isNonzero;
   isNonzero = _BitScanReverse64(&index, m);
   return index;
#else
    __asm
    {
//		mov esi, dword ptr [m]
//		mov edi, dword ptr [m+4]
        bsr eax, dword ptr [m+4]	//edi
		lea eax, [eax+32]
        jnz done1
        bsr eax, dword ptr [m]		//esi
//        jnz done
/*        mov eax, -1
#if defined(DEBUG) || defined(_DEBUG)
		int 1
#endif*/
done1:
//        or eax, 32
done:
    }
#endif
#endif
}

// get (extract) positions from bit mask
// pos: position buffer (must be able to hold 64 values!)
// returns number of positions (0..64)
i32 getPos( u64 m, u8 *pos )
{
#if !defined( _MSC_VER ) || defined ( _M_AMD64 ) || defined ( _M_X64 )
    if ( !m )
        return 0;
    if ( !pos )
        return bitCount( m );
    i32 res = 0;
    i32 i, j;
    for (i=0; m && i<8; i++, m >>= 8)
    {
        u8 p = (u8)m;
        if ( !p )
            continue;
        i64 t = bitPos8[ p ] | rankPos[ i ];
        for (j=0; j<8; j++)
        {
            u8 pb = (u8)t;
            if ( pb == 255 )
                continue;
            pos[ res++ ] = pb;
            t >>= 8;
            if ( t == -1 )
                break;
        }
    }
    return res;
#else
    __asm
    {
        mov ebx, pos
        mov edx, pos
        mov esi, dword ptr [m]
        mov edi, dword ptr [m+4]
    }
    BSFLO16
    BSFLO16
_done1:
    BSFHI16
    BSFHI16
_done2:
    __asm {
        mov eax, ebx
        sub eax, edx
    }
#endif
}

i32 getPosFast( u64 m, u8 *pos )
{
#if defined( _MSC_VER ) && !defined ( _M_AMD64 ) && !defined ( _M_X64 )
    __asm
    {
        mov ebx, pos
        mov edx, pos
        mov esi, dword ptr [m]
        mov edi, dword ptr [m+4]

_loop1:
    }
    BSFLO16
    BSFLO16
    /*		bsf eax, esi
    		jz _done1
    		mov [ebx], al
    		btc esi, eax
    		inc ebx*/


    __asm {
////		jmp _loop1
_done1:
_loop2:
    }
    /*		bsf eax, edi
    		jz _done2
    		mov [ebx], al
    		inc ebx
    		btc edi, eax*/
    BSFHI16
    BSFHI16
    __asm {
////		jmp _loop2
_done2:

        mov eax, ebx
        sub eax, edx
    }
#else
    return getPos( m, pos );
#endif
}
