// File: cpirc[P]Monochrome/src/move_gen.cpp
// Function: void add_moves<true, (Piece)0>(Position const&, unsigned int*, int&)
void add_moves<true, PAWN>(const Position& pos, Move* ml, int& idx) {
    std::uint64_t pawns = get_piece(pos, PAWN, US);
    std::uint64_t them = get_colour(pos, THEM);
    std::uint64_t dest_bb;

    // Left captures
    dest_bb = ((pawns & ~file_mask[FILE_A]) << 7) & them & ~rank_mask[RANK_8];

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

        ml[idx] = get_move(dest - 7, dest, CAPTURE);
        idx++;

        dest_bb &= dest_bb - 1;
    }

    // Left capture-promotions
    dest_bb = ((pawns & ~file_mask[FILE_A]) << 7) & them & rank_mask[RANK_8];

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

        ml[idx] = get_move(dest - 7, dest, PROM_CAPTURE, TO_KNIGHT);
        idx++;

        ml[idx] = get_move(dest - 7, dest, PROM_CAPTURE, TO_BISHOP);
        idx++;

        ml[idx] = get_move(dest - 7, dest, PROM_CAPTURE, TO_ROOK);
        idx++;

        ml[idx] = get_move(dest - 7, dest, PROM_CAPTURE, TO_QUEEN);
        idx++;

        dest_bb &= dest_bb - 1;
    }

    // Right captures
    dest_bb = ((pawns & ~file_mask[FILE_H]) << 9) & them & ~rank_mask[RANK_8];

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

        ml[idx] = get_move(dest - 9, dest, CAPTURE);
        idx++;

        dest_bb &= dest_bb - 1;
    }

    // Right capture-promotions
    dest_bb = ((pawns & ~file_mask[FILE_H]) << 9) & them & rank_mask[RANK_8];

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

        ml[idx] = get_move(dest - 9, dest, PROM_CAPTURE, TO_KNIGHT);
        idx++;

        ml[idx] = get_move(dest - 9, dest, PROM_CAPTURE, TO_BISHOP);
        idx++;

        ml[idx] = get_move(dest - 9, dest, PROM_CAPTURE, TO_ROOK);
        idx++;

        ml[idx] = get_move(dest - 9, dest, PROM_CAPTURE, TO_QUEEN);
        idx++;

        dest_bb &= dest_bb - 1;
    }

    // En passant
    if (pos.epsq != INVALID_SQUARE) {
        pawns &= pawn_attacks(pos.epsq, THEM);

        while (pawns) {
            Square from = lsb(pawns);

            ml[idx] = get_move(from, pos.epsq, ENPASSANT);
            idx++;

            pawns &= pawns - 1;
        }
    }

    add_moves<true, 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
movl $0x1, %esi
callq 0x4420
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
movq 0xb7be(%rip), %rcx      # 0x13b50
xorq $-0x1, %rcx
andq %rcx, %rax
shlq $0x7, %rax
andq -0x28(%rbp), %rax
movq 0xb7a0(%rip), %rcx      # 0x13b48
xorq $-0x1, %rcx
andq %rcx, %rax
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
je 0x8414
movq -0x30(%rbp), %rdi
callq 0x3e50
movb %al, -0x31(%rbp)
movl $0x7, %esi
movzbl -0x31(%rbp), %edi
callq 0x6870
movl $0x2000, %edx           # imm = 0x2000
xorl %ecx, %ecx
movzbl %al, %edi
movzbl -0x31(%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 0x83b3
movq -0x20(%rbp), %rax
movq 0xb731(%rip), %rcx      # 0x13b50
xorq $-0x1, %rcx
andq %rcx, %rax
shlq $0x7, %rax
andq -0x28(%rbp), %rax
andq 0xb713(%rip), %rax      # 0x13b48
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
je 0x8561
movq -0x30(%rbp), %rdi
callq 0x3e50
movb %al, -0x32(%rbp)
movl $0x7, %esi
movzbl -0x32(%rbp), %edi
callq 0x6870
movl $0x6000, %edx           # imm = 0x6000
movl $0x8000, %ecx           # imm = 0x8000
movzbl %al, %edi
movzbl -0x32(%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 $0x7, %esi
movzbl -0x32(%rbp), %edi
callq 0x6870
movl $0x6000, %edx           # imm = 0x6000
movl $0x10000, %ecx          # imm = 0x10000
movzbl %al, %edi
movzbl -0x32(%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 $0x7, %esi
movzbl -0x32(%rbp), %edi
callq 0x6870
movl $0x6000, %edx           # imm = 0x6000
movl $0x18000, %ecx          # imm = 0x18000
movzbl %al, %edi
movzbl -0x32(%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 $0x7, %esi
movzbl -0x32(%rbp), %edi
callq 0x6870
movl $0x6000, %edx           # imm = 0x6000
movl $0x20000, %ecx          # imm = 0x20000
movzbl %al, %edi
movzbl -0x32(%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 0x8439
movq -0x20(%rbp), %rax
movq 0xb61c(%rip), %rcx      # 0x13b88
xorq $-0x1, %rcx
andq %rcx, %rax
shlq $0x9, %rax
andq -0x28(%rbp), %rax
movq 0xb5c6(%rip), %rcx      # 0x13b48
xorq $-0x1, %rcx
andq %rcx, %rax
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
je 0x85ee
movq -0x30(%rbp), %rdi
callq 0x3e50
movb %al, -0x33(%rbp)
movl $0x9, %esi
movzbl -0x33(%rbp), %edi
callq 0x6870
movl $0x2000, %edx           # imm = 0x2000
xorl %ecx, %ecx
movzbl %al, %edi
movzbl -0x33(%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 0x858d
movq -0x20(%rbp), %rax
movq 0xb58f(%rip), %rcx      # 0x13b88
xorq $-0x1, %rcx
andq %rcx, %rax
shlq $0x9, %rax
andq -0x28(%rbp), %rax
andq 0xb539(%rip), %rax      # 0x13b48
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
je 0x873b
movq -0x30(%rbp), %rdi
callq 0x3e50
movb %al, -0x34(%rbp)
movl $0x9, %esi
movzbl -0x34(%rbp), %edi
callq 0x6870
movl $0x6000, %edx           # imm = 0x6000
movl $0x8000, %ecx           # imm = 0x8000
movzbl %al, %edi
movzbl -0x34(%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 $0x9, %esi
movzbl -0x34(%rbp), %edi
callq 0x6870
movl $0x6000, %edx           # imm = 0x6000
movl $0x10000, %ecx          # imm = 0x10000
movzbl %al, %edi
movzbl -0x34(%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 $0x9, %esi
movzbl -0x34(%rbp), %edi
callq 0x6870
movl $0x6000, %edx           # imm = 0x6000
movl $0x18000, %ecx          # imm = 0x18000
movzbl %al, %edi
movzbl -0x34(%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 $0x9, %esi
movzbl -0x34(%rbp), %edi
callq 0x6870
movl $0x6000, %edx           # imm = 0x6000
movl $0x20000, %ecx          # imm = 0x20000
movzbl %al, %edi
movzbl -0x34(%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 0x8613
movq -0x8(%rbp), %rax
movzbl 0x42(%rax), %eax
cmpl $0x40, %eax
je 0x87c0
movq -0x8(%rbp), %rax
movl $0x1, %esi
movzbl 0x42(%rax), %edi
callq 0x75d0
andq -0x20(%rbp), %rax
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x87be
movq -0x20(%rbp), %rdi
callq 0x3e50
movb %al, -0x35(%rbp)
movb -0x35(%rbp), %sil
movq -0x8(%rbp), %rax
movl $0x3000, %edx           # imm = 0x3000
xorl %ecx, %ecx
movzbl %sil, %edi
movzbl 0x42(%rax), %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 -0x20(%rbp), %rax
subq $0x1, %rax
andq -0x20(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x8762
jmp 0x87c0
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
callq 0x8cb0
addq $0x40, %rsp
popq %rbp
retq
nopw (%rax,%rax)