2929
3030// Simple macro to wrap a very common while loop, no facny, no flexibility,
3131// hardcoded list name 'mlist' and from square 'from'.
32- #define SERIALIZE_MOVES (b ) while (b) (*mlist++).move = make_move(from, pop_1st_bit<false >(&b))
32+ #define SERIALIZE_MOVES (b, bsf ) while (b) (*mlist++).move = make_move(from, pop_1st_bit<bsf >(&b))
3333
3434// //
3535// // Local definitions
@@ -83,22 +83,22 @@ namespace {
8383 }
8484
8585 // Template generate_piece_checks() with specializations
86- template <PieceType>
86+ template <PieceType, bool HasBSF >
8787 MoveStack* generate_piece_checks (const Position&, MoveStack*, Color, Bitboard, Square);
8888
8989 template <>
90- inline MoveStack* generate_piece_checks<PAWN >(const Position& p, MoveStack* m, Color us, Bitboard dc, Square ksq) {
90+ inline MoveStack* generate_piece_checks<PAWN , false >(const Position& p, MoveStack* m, Color us, Bitboard dc, Square ksq) {
9191
9292 return (us == WHITE ? generate_pawn_checks<WHITE >(p, dc, ksq, m)
9393 : generate_pawn_checks<BLACK >(p, dc, ksq, m));
9494 }
9595
9696 // Template generate_piece_moves() with specializations and overloads
97- template <PieceType>
97+ template <PieceType, bool HasBSF >
9898 MoveStack* generate_piece_moves (const Position&, MoveStack*, Color us, Bitboard);
9999
100100 template <>
101- MoveStack* generate_piece_moves<KING >(const Position&, MoveStack*, Color, Bitboard);
101+ MoveStack* generate_piece_moves<KING , false >(const Position&, MoveStack*, Color, Bitboard);
102102
103103 template <PieceType Piece, MoveType Type>
104104 inline MoveStack* generate_piece_moves (const Position& p, MoveStack* m, Color us) {
@@ -113,12 +113,12 @@ namespace {
113113 : generate_pawn_noncaptures<BLACK >(p, m));
114114 }
115115
116- template <PieceType>
116+ template <PieceType, bool HasBSF >
117117 MoveStack* generate_piece_moves (const Position&, MoveStack*, Color us, Bitboard, Bitboard);
118118
119119 template <>
120- inline MoveStack* generate_piece_moves<PAWN >(const Position& p, MoveStack* m,
121- Color us, Bitboard t, Bitboard pnd) {
120+ inline MoveStack* generate_piece_moves<PAWN , false >(const Position& p, MoveStack* m,
121+ Color us, Bitboard t, Bitboard pnd) {
122122
123123 return (us == WHITE ? generate_pawn_blocking_evasions<WHITE >(p, pnd, t, m)
124124 : generate_pawn_blocking_evasions<BLACK >(p, pnd, t, m));
@@ -133,7 +133,7 @@ namespace {
133133
134134// / generate_captures generates() all pseudo-legal captures and queen
135135// / promotions. The return value is the number of moves generated.
136-
136+ template < bool HasBSF>
137137int generate_captures (const Position& pos, MoveStack* mlist) {
138138
139139 assert (pos.is_ok ());
@@ -143,19 +143,25 @@ int generate_captures(const Position& pos, MoveStack* mlist) {
143143 Bitboard target = pos.pieces_of_color (opposite_color (us));
144144 MoveStack* mlist_start = mlist;
145145
146- mlist = generate_piece_moves<QUEEN >(pos, mlist, us, target);
147- mlist = generate_piece_moves<ROOK >(pos, mlist, us, target);
148- mlist = generate_piece_moves<BISHOP >(pos, mlist, us, target);
149- mlist = generate_piece_moves<KNIGHT >(pos, mlist, us, target);
146+ mlist = generate_piece_moves<QUEEN , HasBSF >(pos, mlist, us, target);
147+ mlist = generate_piece_moves<ROOK , HasBSF >(pos, mlist, us, target);
148+ mlist = generate_piece_moves<BISHOP , HasBSF >(pos, mlist, us, target);
149+ mlist = generate_piece_moves<KNIGHT , HasBSF >(pos, mlist, us, target);
150150 mlist = generate_piece_moves<PAWN , CAPTURE >(pos, mlist, us);
151- mlist = generate_piece_moves<KING >(pos, mlist, us, target);
151+ mlist = generate_piece_moves<KING , false >(pos, mlist, us, target);
152152 return int (mlist - mlist_start);
153153}
154154
155+ int generate_captures (const Position& pos, MoveStack* mlist) {
156+
157+ return CpuHasPOPCNT ? generate_captures<true >(pos, mlist)
158+ : generate_captures<false >(pos, mlist);
159+ }
160+
155161
156162// / generate_noncaptures() generates all pseudo-legal non-captures and
157163// / underpromotions. The return value is the number of moves generated.
158-
164+ template < bool HasBSF>
159165int generate_noncaptures (const Position& pos, MoveStack* mlist) {
160166
161167 assert (pos.is_ok ());
@@ -166,20 +172,26 @@ int generate_noncaptures(const Position& pos, MoveStack* mlist) {
166172 MoveStack* mlist_start = mlist;
167173
168174 mlist = generate_piece_moves<PAWN , NON_CAPTURE >(pos, mlist, us);
169- mlist = generate_piece_moves<KNIGHT >(pos, mlist, us, target);
170- mlist = generate_piece_moves<BISHOP >(pos, mlist, us, target);
171- mlist = generate_piece_moves<ROOK >(pos, mlist, us, target);
172- mlist = generate_piece_moves<QUEEN >(pos, mlist, us, target);
173- mlist = generate_piece_moves<KING >(pos, mlist, us, target);
175+ mlist = generate_piece_moves<KNIGHT , HasBSF >(pos, mlist, us, target);
176+ mlist = generate_piece_moves<BISHOP , HasBSF >(pos, mlist, us, target);
177+ mlist = generate_piece_moves<ROOK , HasBSF >(pos, mlist, us, target);
178+ mlist = generate_piece_moves<QUEEN , HasBSF >(pos, mlist, us, target);
179+ mlist = generate_piece_moves<KING , false >(pos, mlist, us, target);
174180 mlist = generate_castle_moves<KING_SIDE >(pos, mlist);
175181 mlist = generate_castle_moves<QUEEN_SIDE >(pos, mlist);
176182 return int (mlist - mlist_start);
177183}
178184
185+ int generate_noncaptures (const Position& pos, MoveStack* mlist) {
186+
187+ return CpuHasPOPCNT ? generate_noncaptures<true >(pos, mlist)
188+ : generate_noncaptures<false >(pos, mlist);
189+ }
190+
179191
180192// / generate_non_capture_checks() generates all pseudo-legal non-capturing,
181193// / non-promoting checks. It returns the number of generated moves.
182-
194+ template < bool HasBSF>
183195int generate_non_capture_checks (const Position& pos, MoveStack* mlist, Bitboard dc) {
184196
185197 assert (pos.is_ok ());
@@ -192,12 +204,12 @@ int generate_non_capture_checks(const Position& pos, MoveStack* mlist, Bitboard
192204 assert (pos.piece_on (ksq) == piece_of_color_and_type (opposite_color (us), KING ));
193205
194206 // Pieces moves
195- mlist = generate_piece_checks<PAWN >(pos, mlist, us, dc, ksq);
196- mlist = generate_piece_checks<KNIGHT >(pos, mlist, us, dc, ksq);
197- mlist = generate_piece_checks<BISHOP >(pos, mlist, us, dc, ksq);
198- mlist = generate_piece_checks<ROOK >(pos, mlist, us, dc, ksq);
199- mlist = generate_piece_checks<QUEEN >(pos, mlist, us, dc, ksq);
200- mlist = generate_piece_checks<KING >(pos, mlist, us, dc, ksq);
207+ mlist = generate_piece_checks<PAWN , false >(pos, mlist, us, dc, ksq);
208+ mlist = generate_piece_checks<KNIGHT , HasBSF >(pos, mlist, us, dc, ksq);
209+ mlist = generate_piece_checks<BISHOP , HasBSF >(pos, mlist, us, dc, ksq);
210+ mlist = generate_piece_checks<ROOK , HasBSF >(pos, mlist, us, dc, ksq);
211+ mlist = generate_piece_checks<QUEEN , HasBSF >(pos, mlist, us, dc, ksq);
212+ mlist = generate_piece_checks<KING , false >(pos, mlist, us, dc, ksq);
201213
202214 // Castling moves that give check. Very rare but nice to have!
203215 if ( pos.can_castle_queenside (us)
@@ -213,11 +225,17 @@ int generate_non_capture_checks(const Position& pos, MoveStack* mlist, Bitboard
213225 return int (mlist - mlist_start);
214226}
215227
228+ int generate_non_capture_checks (const Position& pos, MoveStack* mlist, Bitboard dc) {
229+
230+ return CpuHasPOPCNT ? generate_non_capture_checks<true >(pos, mlist, dc)
231+ : generate_non_capture_checks<false >(pos, mlist, dc);
232+ }
233+
216234
217235// / generate_evasions() generates all check evasions when the side to move is
218236// / in check. Unlike the other move generation functions, this one generates
219237// / only legal moves. It returns the number of generated moves.
220-
238+ template < bool HasBSF>
221239int generate_evasions (const Position& pos, MoveStack* mlist, Bitboard pinned) {
222240
223241 assert (pos.is_ok ());
@@ -313,11 +331,11 @@ int generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pinned) {
313331
314332 if (blockSquares != EmptyBoardBB)
315333 {
316- mlist = generate_piece_moves<PAWN >(pos, mlist, us, blockSquares, pinned);
317- mlist = generate_piece_moves<KNIGHT >(pos, mlist, us, blockSquares, pinned);
318- mlist = generate_piece_moves<BISHOP >(pos, mlist, us, blockSquares, pinned);
319- mlist = generate_piece_moves<ROOK >(pos, mlist, us, blockSquares, pinned);
320- mlist = generate_piece_moves<QUEEN >(pos, mlist, us, blockSquares, pinned);
334+ mlist = generate_piece_moves<PAWN , false >(pos, mlist, us, blockSquares, pinned);
335+ mlist = generate_piece_moves<KNIGHT , HasBSF >(pos, mlist, us, blockSquares, pinned);
336+ mlist = generate_piece_moves<BISHOP , HasBSF >(pos, mlist, us, blockSquares, pinned);
337+ mlist = generate_piece_moves<ROOK , HasBSF >(pos, mlist, us, blockSquares, pinned);
338+ mlist = generate_piece_moves<QUEEN , HasBSF >(pos, mlist, us, blockSquares, pinned);
321339 }
322340 }
323341
@@ -350,6 +368,12 @@ int generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pinned) {
350368 return int (mlist - mlist_start);
351369}
352370
371+ int generate_evasions (const Position& pos, MoveStack* mlist, Bitboard pinned) {
372+
373+ return CpuHasPOPCNT ? generate_evasions<true >(pos, mlist, pinned)
374+ : generate_evasions<false >(pos, mlist, pinned);
375+ }
376+
353377
354378// / generate_legal_moves() computes a complete list of legal moves in the
355379// / current position. This function is not very fast, and should be used
@@ -566,7 +590,7 @@ bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) {
566590
567591namespace {
568592
569- template <PieceType Piece>
593+ template <PieceType Piece, bool HasBSF >
570594 MoveStack* generate_piece_moves (const Position& pos, MoveStack* mlist, Color us, Bitboard target) {
571595
572596 Square from;
@@ -576,12 +600,12 @@ namespace {
576600 {
577601 from = pos.piece_list (us, Piece, i);
578602 b = pos.piece_attacks <Piece>(from) & target;
579- SERIALIZE_MOVES (b);
603+ SERIALIZE_MOVES (b, HasBSF );
580604 }
581605 return mlist;
582606 }
583607
584- template <PieceType Piece>
608+ template <PieceType Piece, bool HasBSF >
585609 MoveStack* generate_piece_moves (const Position& pos, MoveStack* mlist,
586610 Color us, Bitboard target, Bitboard pinned) {
587611 Square from;
@@ -594,19 +618,19 @@ namespace {
594618 continue ;
595619
596620 b = pos.piece_attacks <Piece>(from) & target;
597- SERIALIZE_MOVES (b);
621+ SERIALIZE_MOVES (b, HasBSF );
598622 }
599623 return mlist;
600624 }
601625
602626 template <>
603- MoveStack* generate_piece_moves<KING >(const Position& pos, MoveStack* mlist, Color us, Bitboard target) {
627+ MoveStack* generate_piece_moves<KING , false >(const Position& pos, MoveStack* mlist, Color us, Bitboard target) {
604628
605629 Bitboard b;
606630 Square from = pos.king_square (us);
607631
608632 b = pos.piece_attacks <KING >(from) & target;
609- SERIALIZE_MOVES (b);
633+ SERIALIZE_MOVES (b, false );
610634 return mlist;
611635 }
612636
@@ -816,7 +840,7 @@ namespace {
816840 return mlist;
817841 }
818842
819- template <PieceType Piece>
843+ template <PieceType Piece, bool HasBSF >
820844 MoveStack* generate_piece_checks (const Position& pos, MoveStack* mlist, Color us,
821845 Bitboard dc, Square ksq) {
822846
@@ -831,7 +855,7 @@ namespace {
831855 if (Piece == KING )
832856 bb &= ~QueenPseudoAttacks[ksq];
833857
834- SERIALIZE_MOVES (bb);
858+ SERIALIZE_MOVES (bb, HasBSF );
835859 }
836860
837861 // Direct checks
@@ -851,7 +875,7 @@ namespace {
851875 continue ;
852876
853877 Bitboard bb = pos.piece_attacks <Piece>(from) & checkSqs;
854- SERIALIZE_MOVES (bb);
878+ SERIALIZE_MOVES (bb, HasBSF );
855879 }
856880 }
857881 return mlist;
0 commit comments