前言:这个东西老早就应该贴了,因为我已经在Nowcan的Blog帖子里说过了,一直没贴是因为没有心情,或者觉得自己还没有整理得足够好,现在先发未经过整理的上来冲冲数先吧。
这段代码是WZebra的作者Gunnar Andersson写的,作用是计算《黑白棋》双方的行动力,其中使用了bitboard技术和MMX指令,作者说他已经考虑了指令配对,请不要随意修改代码的先后顺序,除非你真的确定你是对的。原来的代码是gcc下的汇编格式,我把他转换过来而已,这个是在VC++ 6.0编译的版本,希望对你有点用处。
另:由于是很久很久以前弄的,大概有快2,3年了吧(当时我的汇编也不怎么样),所以你会看到头和尾的int count处理不是很科学(也许这样比较直观一些),其实你可以让他更有效率,我也懒得改了,修改一下代码会更快一点儿,留给你自己去做了,其实相当简单的。
static unsigned __int64 dir_mask0; static unsigned __int64 dir_mask1; static unsigned __int64 dir_mask2; static unsigned __int64 dir_mask3; static unsigned __int64 dir_mask4; static unsigned __int64 dir_mask5; static unsigned __int64 dir_mask6; static unsigned __int64 dir_mask7; static unsigned __int64 c0f; static unsigned __int64 c33; static unsigned __int64 c55;
void init_mmx( void ) { dir_mask0 = 0x007e7e7e7e7e7e00; dir_mask1 = 0x00ffffffffffff00; dir_mask2 = 0x007e7e7e7e7e7e00; dir_mask3 = 0x7e7e7e7e7e7e7e7e; dir_mask4 = 0x7e7e7e7e7e7e7e7e; dir_mask5 = 0x007e7e7e7e7e7e00; dir_mask6 = 0x00ffffffffffff00; dir_mask7 = 0x007e7e7e7e7e7e00; c0f = 0x0f0f0f0f0f0f0f0f; c33 = 0x3333333333333333; c55 = 0x5555555555555555; }
typedef struct { unsigned long high; unsigned long low; } BitBoard;
int bitboard_mobility( const BitBoard my_bits, const BitBoard opp_bits ) { unsigned int count;
__asm {
/* Ready for init data */ mov ebx, my_bits.high ; mov ecx, my_bits.low ; mov edi, opp_bits.high ; mov esi, opp_bits.low ;
// movd mm0, ebx ; psllq mm0, 32 ; movd mm3, ecx ; por mm0, mm3 ; mm0 is BitBoard of my_bits movd mm1, edi ; psllq mm1, 32 ; movd mm4, esi ; por mm1, mm4 ; mm1 is BitBoard of opp_bits pxor mm2, mm2 ; mm2 <- 0x0000000000000000
/* shift=-9 rowDelta=-1 colDelta=-1 */ /* shift=+9 rowDelta=+1 colDelta=+1 */
/* Disc #1, flip direction 0. */ /* Disc #1, flip direction 7. */ movq mm3, mm1 ; mm3 <- opp_bits movq mm4, mm0 ; mm4 <- my_bits movq mm6, mm0 ; mm6 <- backup of my_bits pand mm3, dir_mask0 ; 0x007e7e7e7e7e7e00 ; dir_mask0 of value: ; 00000000 ; 01111110 ; 01111110 ; 01111110 ; 01111110 ; 01111110 ; 01111110 ; 00000000 push esi ; psllq mm4, 9 ; psrlq mm6, 9 ; push edi ; pand mm4, mm3 ; pand mm6, mm3 ; push ecx ;
/* Disc #2, flip direction 0. */ /* Disc #2, flip direction 7. */ movq mm5, mm4 ; movq mm7, mm6 ; psllq mm5, 9 ; psrlq mm7, 9 ; push ebx ; pand mm5, mm3 ; pand mm7, mm3 ; and edi, 0x7e7e7e7e ; 0x7e7e7e7e and esi, 0x7e7e7e7e ; 0x7e7e7e7e ; value of: ; 011111110 ; 011111110 ; 011111110 ; 011111110 por mm4, mm5 ; por mm6, mm7 ; shl ebx, 1 ; shl ecx, 1 ;
/* Disc #3, flip direction 0. */ /* Disc #3, flip direction 7. */ movq mm5, mm4 ; movq mm7, mm6 ; and ebx, edi ; and ecx, esi ; psllq mm5, 9 ; psrlq mm7, 9 ; mov eax, ebx ; mov edx, ecx ; pand mm5, mm3 ; pand mm7, mm3 ; shl edx, 1 ; shl eax, 1 ; por mm4, mm5 ; por mm6, mm7 ; and eax, edi ; and edx, esi ;
/* Disc #4, flip direction 0. */ /* Disc #4, flip direction 7. */ movq mm5, mm4 ; movq mm7, mm6 ; or ebx, eax ; or ecx, edx ; psllq mm5, 9 ; psrlq mm7, 9 ; mov eax, ebx ; mov edx, ecx ; pand mm5, mm3 ; pand mm7, mm3 ; shl edx, 1 ; shl eax, 1 ; por mm4, mm5 ; por mm6, mm7 ; and eax, edi ; and edx, esi ;
/* Disc #5, flip direction 0. */ /* Disc #5, flip direction 7. */ movq mm5, mm4 ; movq mm7, mm6 ; or ebx, eax ; or ecx, edx ; psllq mm5, 9 ; psrlq mm7, 9 ; mov eax, ebx ; mov edx, ecx ; pand mm5, mm3 ; pand mm7, mm3 ; shl edx, 1 ; shl eax, 1 ; por mm4, mm5 ; por mm6, mm7 ; and eax, edi ; and edx, esi ;
/* Disc #6, flip direction 0. */ /* Disc #6, flip direction 7. */ movq mm5, mm4 ; movq mm7, mm6 ; or ebx, eax ; or ecx, edx ; psrlq mm7, 9 ; psllq mm5, 9 ; mov eax, ebx ; mov edx, ecx ; pand mm5, mm3 ; pand mm7, mm3 ; shl edx, 1 ; shl eax, 1 ; por mm4, mm5 ; por mm6, mm7 ; and eax, edi ; and edx, esi ; psllq mm4, 9 ; psrlq mm6, 9 ; or ebx, eax ; or ecx, edx ; por mm2, mm4 ; por mm2, mm6 ; mov eax, ebx ; mov edx, ecx ;
/* shift=-8 rowDelta=-1 colDelta=0 */ /* shift=+8 rowDelta=1 colDelta=0 */
/* Disc #1, flip direction 1. */ /* Disc #1, flip direction 6. */ movq mm3, mm1 ; movq mm4, mm0 ; movq mm6, mm0 ; pand mm3, dir_mask1 ; 0x00ffffffffffff00; ; dir_mask1 of value: ; 00000000 ; 11111111 ; 11111111 ; 11111111 ; 11111111 ; 11111111 ; 11111111 ; 00000000 psllq mm4, 8 ; psrlq mm6, 8 ; shl edx, 1 ; shl eax, 1 ; pand mm4, mm3 ; pand mm6, mm3 ; and eax, edi ; and edx, esi ; /* Disc #2, flip direction 1. */ /* Disc #2, flip direction 6. */ movq mm5, mm4 ; movq mm7, mm6 ; or ebx, eax ; or ecx, edx ; psllq mm5, 8 ; psrlq mm7, 8 ; shl ebx, 1 ; shl ecx, 1 ; pand mm5, mm3 ; pand mm7, mm3 ; por mm4, mm5 ; por mm6, mm7 ;
/* serialize here: add horizontal shl flips. */
movd mm5, ebx ; psllq mm5, 32 ; movd mm7, ecx ; por mm5, mm7 ; por mm2, mm5 ;
/* Disc #3, flip direction 1. */ /* Disc #3, flip direction 6. */ movq mm5, mm4 ; movq mm7, mm6 ; psllq mm5, 8 ; psrlq mm7, 8 ; pop ebx ; pand mm5, mm3 ; pand mm7, mm3 ; pop ecx ; por mm4, mm5 ; por mm6, mm7 ; push ecx ;
/* Disc #4, flip direction 1. */ /* Disc #4, flip direction 6. */ movq mm5, mm4 ; movq mm7, mm6 ; push ebx ; psllq mm5, 8 ; psrlq mm7, 8 ; shr ebx, 1 ; shr ecx, 1 ; pand mm5, mm3 ; pand mm7, mm3 ; and ebx, edi ; and ecx, esi ; por mm4, mm5 ; por mm6, mm7 ;
/* Disc #5, flip direction 1. */ /* Disc #5, flip direction 6. */ movq mm5, mm4 ; movq mm7, mm6 ; psllq mm5, 8 ; psrlq mm7, 8 ; mov eax, ebx ; mov edx, ecx ; pand mm5, mm3 ; pand mm7, mm3 ; shr eax, 1 ; shr edx, 1 ; por mm4, mm5 ; por mm6, mm7 ; and eax, edi ; and edx, esi ;
/* Disc #6, flip direction 1. */ /* Disc #6, flip direction 6. */ movq mm5, mm4 ; movq mm7, mm6 ; or ebx, eax ; or ecx, edx ; psllq mm5, 8 ; psrlq mm7, 8 ; mov eax, ebx ; mov edx, ecx ; pand mm5, mm3 ; pand mm7, mm3 ; shr eax, 1 ; shr edx, 1 ; por mm4, mm5 ; por mm6, mm7 ; and eax, edi ; and edx, esi ; psllq mm4, 8 ; psrlq mm6, 8 ; or ebx, eax ; or ecx, edx ; por mm2, mm4 ; por mm2, mm6 ;
/* shift=-7 rowDelta=-1 colDelta=1 */ /* shift=+7 rowDelta=1 colDelta=-1 */
/* Disc #1, flip direction 2. */ /* Disc #1, flip direction 5. */ movq mm3, mm1 ; movq mm4, mm0 ; movq mm6, mm0 ; pand mm3, dir_mask2 ; 0x007e7e7e7e7e7e00; ; dir_mask2 of value: ; 00000000 ; 01111110 ; 01111110 ; 01111110 ; 01111110 ; 01111110 ; 01111110 ; 00000000 psllq mm4, 7 ; psrlq mm6, 7 ; mov eax, ebx ; mov edx, ecx ; pand mm4, mm3 ; pand mm6, mm3 ; shr eax, 1 ; shr edx, 1 ;
/* Disc #2, flip direction 2. */ /* Disc #2, flip direction 5. */ movq mm5, mm4 ; movq mm7, mm6 ; and eax, edi ; and edx, esi ; psllq mm5, 7 ; psrlq mm7, 7 ; or ebx, eax ; or ecx, edx ; pand mm5, mm3 ; pand mm7, mm3 ; mov eax, ebx ; mov edx, ecx ; por mm4, mm5 ; por mm6, mm7 ; shr eax, 1 ; shr edx, 1 ;
/* Disc #3, flip direction 2. */ /* Disc #3, flip direction 5. */ movq mm5, mm4 ; movq mm7, mm6 ; and eax, edi ; and edx, esi ; psllq mm5, 7 ; psrlq mm7, 7 ; or ebx, eax ; or ecx, edx ; pand mm5, mm3 ; pand mm7, mm3 ; mov eax, ebx ; mov edx, ecx ; por mm4, mm5 ; por mm6, mm7 ; shr eax, 1 ; shr edx, 1 ;
/* Disc #4, flip direction 2. */ /* Disc #4, flip direction 5. */ movq mm5, mm4 ; movq mm7, mm6 ; and eax, edi ; and edx, esi ; psllq mm5, 7 ; psrlq mm7, 7 ; or ebx, eax ; or ecx, edx ; pand mm5, mm3 ; pand mm7, mm3 ; mov eax, ebx ; mov edx, ecx ; por mm4, mm5 ; por mm6, mm7 ; shr eax, 1 ; shr edx, 1 ;
/* Disc #5, flip direction 2. */ /* Disc #5, flip direction 5. */ movq mm5, mm4 ; movq mm7, mm6 ; and eax, edi ; and edx, esi ; psllq mm5, 7 ; psrlq mm7, 7 ; or ebx, eax ; or ecx, edx ; pand mm5, mm3 ; pand mm7, mm3 ; shr ebx, 1 ; shr ecx, 1 ; por mm4, mm5 ; por mm6, mm7 ;
/* serialize here: add horizontal shr flips. */
movd mm5, ebx ; psllq mm5, 32 ; movd mm7, ecx ; por mm5, mm7 ; por mm2, mm5 ; pop ebx ;
/* Disc #6, flip direction 2. */ /* Disc #6, flip direction 5. */ movq mm5, mm4 ; movq mm7, mm6 ; psllq mm5, 7 ; psrlq mm7, 7 ; pop ecx ; pand mm5, mm3 ; pand mm7, mm3 ; pop edi ; por mm4, mm5 ; por mm6, mm7 ; pop esi ; psllq mm4, 7 ; psrlq mm6, 7 ; por mm2, mm4 ; por mm2, mm6 ;
/* mm2 is the pseudo-feasible moves at this point. */ /* Let mm7 be the feasible moves, i.e., mm2 restricted to empty squares. */
movq mm7, mm0 ; por mm7, mm1 ; pandn mm7, mm2 ;
/* Count the moves, i.e., the number of bits set in mm7. */
movq mm1, mm7 ; psrld mm7, 1 ; pand mm7, c55 ; c55 = 0x5555555555555555 psubd mm1, mm7 ; movq mm7, mm1 ; psrld mm1, 2 ; pand mm7, c33 ; c33 = 0x3333333333333333; pand mm1, c33 ; c33 = 0x3333333333333333; paddd mm7, mm1 ; movq mm1, mm7 ; psrld mm7, 4 ; paddd mm7, mm1 ; pand mm7, c0f ; c0f = 0x0f0f0f0f0f0f0f0f;
movq mm1, mm7 ; psrld mm7, 8 ; paddd mm7, mm1 ; movq mm1, mm7 ; psrld mm7, 16 ; paddd mm7, mm1 ; movq mm1, mm7 ; psrlq mm7, 32 ; paddd mm7, mm1 ; movd eax, mm7 ; and eax, 63 ; mov count, eax ;
// emms ; } return count; }

|