// File: cpirc[P]Monochrome/src/move_gen.cpp
// Function: void add_moves<false, (Piece)0>(Position const&, unsigned int*, int&)
void add_moves<false, PAWN>(const Position& pos, Move* ml, int& idx) {
    std::uint64_t pawns = get_piece(pos, PAWN, US);
    std::uint64_t empty = ~get_occupancy(pos);
    std::uint64_t singles, doubles;

    // Single push
    singles = (pawns << 8) & empty;

    // Separate promotions
    singles &= ~rank_mask[RANK_8];

    while (singles) {
        Square dest = lsb(singles);

        ml[idx] = get_move(dest - 8, dest, NORMAL);
        idx++;

        singles &= singles - 1;
    }

    // Double push
    singles = ((pawns & rank_mask[RANK_2]) << 8) & empty;
    doubles = (singles << 8) & empty;

    while (doubles) {
        Square dest = lsb(doubles);

        ml[idx] = get_move(dest - 16, dest, DOUBLE_PUSH);
        idx++;

        doubles &= doubles - 1;
    }

    // Promotions
    singles = ((pawns & rank_mask[RANK_7]) << 8) & empty;

    while (singles) {
        Square dest = lsb(singles);

        ml[idx] = get_move(dest - 8, dest, PROMOTION, TO_KNIGHT);
        idx++;

        ml[idx] = get_move(dest - 8, dest, PROMOTION, TO_BISHOP);
        idx++;

        ml[idx] = get_move(dest - 8, dest, PROMOTION, TO_ROOK);
        idx++;

        ml[idx] = get_move(dest - 8, dest, PROMOTION, TO_QUEEN);
        idx++;

        singles &= singles - 1;
    }

    add_moves<false, KNIGHT>(pos, ml, idx);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rdi
xorl %edx, %edx
movl %edx, %esi
callq 0x3cf0
movq %rax, -0x20(%rbp)
movq -0x8(%rbp), %rdi
callq 0x3ea0
xorq $-0x1, %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
shlq $0x8, %rax
andq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
movq 0xba4b(%rip), %rax      # 0x13b48
xorq $-0x1, %rax
andq -0x30(%rbp), %rax
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
je 0x8167
movq -0x30(%rbp), %rdi
callq 0x3e50
movb %al, -0x39(%rbp)
movl $0x8, %esi
movzbl -0x39(%rbp), %edi
callq 0x6870
xorl %ecx, %ecx
movzbl %al, %edi
movzbl -0x39(%rbp), %esi
movl %ecx, %edx
callq 0x69a0
movl %eax, %edx
movq -0x10(%rbp), %rax
movq -0x18(%rbp), %rcx
movslq (%rcx), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x18(%rbp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movq -0x30(%rbp), %rax
subq $0x1, %rax
andq -0x30(%rbp), %rax
movq %rax, -0x30(%rbp)
jmp 0x8109
movq -0x20(%rbp), %rax
andq 0xb9a6(%rip), %rax      # 0x13b18
shlq $0x8, %rax
andq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
shlq $0x8, %rax
andq -0x28(%rbp), %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0x81ef
movq -0x38(%rbp), %rdi
callq 0x3e50
movb %al, -0x3a(%rbp)
movl $0x10, %esi
movzbl -0x3a(%rbp), %edi
callq 0x6870
movl $0x5000, %edx           # imm = 0x5000
xorl %ecx, %ecx
movzbl %al, %edi
movzbl -0x3a(%rbp), %esi
callq 0x69a0
movl %eax, %edx
movq -0x10(%rbp), %rax
movq -0x18(%rbp), %rcx
movslq (%rcx), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x18(%rbp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movq -0x38(%rbp), %rax
subq $0x1, %rax
andq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
jmp 0x818e
movq -0x20(%rbp), %rax
andq 0xb946(%rip), %rax      # 0x13b40
shlq $0x8, %rax
andq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
je 0x832e
movq -0x30(%rbp), %rdi
callq 0x3e50
movb %al, -0x3b(%rbp)
movl $0x8, %esi
movzbl -0x3b(%rbp), %edi
callq 0x6870
movl $0x4000, %edx           # imm = 0x4000
movl $0x8000, %ecx           # imm = 0x8000
movzbl %al, %edi
movzbl -0x3b(%rbp), %esi
callq 0x69a0
movl %eax, %edx
movq -0x10(%rbp), %rax
movq -0x18(%rbp), %rcx
movslq (%rcx), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x18(%rbp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movl $0x8, %esi
movzbl -0x3b(%rbp), %edi
callq 0x6870
movl $0x4000, %edx           # imm = 0x4000
movl $0x10000, %ecx          # imm = 0x10000
movzbl %al, %edi
movzbl -0x3b(%rbp), %esi
callq 0x69a0
movl %eax, %edx
movq -0x10(%rbp), %rax
movq -0x18(%rbp), %rcx
movslq (%rcx), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x18(%rbp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movl $0x8, %esi
movzbl -0x3b(%rbp), %edi
callq 0x6870
movl $0x4000, %edx           # imm = 0x4000
movl $0x18000, %ecx          # imm = 0x18000
movzbl %al, %edi
movzbl -0x3b(%rbp), %esi
callq 0x69a0
movl %eax, %edx
movq -0x10(%rbp), %rax
movq -0x18(%rbp), %rcx
movslq (%rcx), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x18(%rbp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movl $0x8, %esi
movzbl -0x3b(%rbp), %edi
callq 0x6870
movl $0x4000, %edx           # imm = 0x4000
movl $0x20000, %ecx          # imm = 0x20000
movzbl %al, %edi
movzbl -0x3b(%rbp), %esi
callq 0x69a0
movl %eax, %edx
movq -0x10(%rbp), %rax
movq -0x18(%rbp), %rcx
movslq (%rcx), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x18(%rbp), %rax
movl (%rax), %ecx
addl $0x1, %ecx
movl %ecx, (%rax)
movq -0x30(%rbp), %rax
subq $0x1, %rax
andq -0x30(%rbp), %rax
movq %rax, -0x30(%rbp)
jmp 0x8206
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
callq 0x8bb0
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)