// File: xocoder[P]m_kcptun/vendor/cm256/gf256.cpp
// Function: gf256_memswap
void gf256_memswap(void * GF256_RESTRICT vx, void * GF256_RESTRICT vy, int bytes)
{
#if defined(GF256_TARGET_MOBILE)
    uint64_t * GF256_RESTRICT x16 = reinterpret_cast<uint64_t *>(vx);
    uint64_t * GF256_RESTRICT y16 = reinterpret_cast<uint64_t *>(vy);

    const unsigned count = (unsigned)bytes / 8;
    for (unsigned ii = 0; ii < count; ++ii)
    {
        const uint64_t temp = x16[ii];
        x16[ii] = y16[ii];
        y16[ii] = temp;
    }

    x16 += count;
    y16 += count;
#else
    GF256_M128 * GF256_RESTRICT x16 = reinterpret_cast<GF256_M128 *>(vx);
    GF256_M128 * GF256_RESTRICT y16 = reinterpret_cast<GF256_M128 *>(vy);

    // Handle blocks of 16 bytes
    while (bytes >= 16)
    {
        GF256_M128 x0 = _mm_loadu_si128(x16);
        GF256_M128 y0 = _mm_loadu_si128(y16);
        _mm_storeu_si128(x16, y0);
        _mm_storeu_si128(y16, x0);

        bytes -= 16, ++x16, ++y16;
    }
#endif

    uint8_t * GF256_RESTRICT x1 = reinterpret_cast<uint8_t *>(x16);
    uint8_t * GF256_RESTRICT y1 = reinterpret_cast<uint8_t *>(y16);

    // Handle a block of 8 bytes
    const int eight = bytes & 8;
    if (eight)
    {
        uint64_t * GF256_RESTRICT x8 = reinterpret_cast<uint64_t *>(x1);
        uint64_t * GF256_RESTRICT y8 = reinterpret_cast<uint64_t *>(y1);

        uint64_t temp = *x8;
        *x8 = *y8;
        *y8 = temp;
    }

    // Handle a block of 4 bytes
    const int four = bytes & 4;
    if (four)
    {
        uint32_t * GF256_RESTRICT x4 = reinterpret_cast<uint32_t *>(x1 + eight);
        uint32_t * GF256_RESTRICT y4 = reinterpret_cast<uint32_t *>(y1 + eight);

        uint32_t temp = *x4;
        *x4 = *y4;
        *y4 = temp;
    }

    // Handle final bytes
    const int offset = eight + four;
    uint8_t temp;
    switch (bytes & 3)
    {
    case 3: temp = x1[offset + 2]; x1[offset + 2] = y1[offset + 2]; y1[offset + 2] = temp;
    case 2: temp = x1[offset + 1]; x1[offset + 1] = y1[offset + 1]; y1[offset + 1] = temp;
    case 1: temp = x1[offset]; x1[offset] = y1[offset]; y1[offset] = temp;
    default:
        break;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x58(%rbp)
movq %rsi, -0x60(%rbp)
movl %edx, -0x64(%rbp)
movq -0x58(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x60(%rbp), %rax
movq %rax, -0x78(%rbp)
cmpl $0x10, -0x64(%rbp)
jl 0x12c8a
movq -0x70(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movdqu (%rax), %xmm0
movdqa %xmm0, -0x90(%rbp)
movq -0x78(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movdqu (%rax), %xmm0
movdqa %xmm0, -0xa0(%rbp)
movq -0x70(%rbp), %rax
movdqa -0xa0(%rbp), %xmm0
movq %rax, -0x8(%rbp)
movdqa %xmm0, -0x20(%rbp)
movdqa -0x20(%rbp), %xmm0
movq -0x8(%rbp), %rax
movdqu %xmm0, (%rax)
movq -0x78(%rbp), %rax
movdqa -0x90(%rbp), %xmm0
movq %rax, -0x28(%rbp)
movdqa %xmm0, -0x40(%rbp)
movdqa -0x40(%rbp), %xmm0
movq -0x28(%rbp), %rax
movdqu %xmm0, (%rax)
movl -0x64(%rbp), %eax
subl $0x10, %eax
movl %eax, -0x64(%rbp)
movq -0x70(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x70(%rbp)
movq -0x78(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x78(%rbp)
jmp 0x12be6
movq -0x70(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0x78(%rbp), %rax
movq %rax, -0xb0(%rbp)
movl -0x64(%rbp), %eax
andl $0x8, %eax
movl %eax, -0xb4(%rbp)
cmpl $0x0, -0xb4(%rbp)
je 0x12d07
movq -0xa8(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0xb0(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq -0xc0(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xd0(%rbp)
movq -0xc8(%rbp), %rax
movq (%rax), %rcx
movq -0xc0(%rbp), %rax
movq %rcx, (%rax)
movq -0xd0(%rbp), %rcx
movq -0xc8(%rbp), %rax
movq %rcx, (%rax)
movl -0x64(%rbp), %eax
andl $0x4, %eax
movl %eax, -0xd4(%rbp)
cmpl $0x0, -0xd4(%rbp)
je 0x12d7c
movq -0xa8(%rbp), %rax
movslq -0xb4(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0xe0(%rbp)
movq -0xb0(%rbp), %rax
movslq -0xb4(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0xe8(%rbp)
movq -0xe0(%rbp), %rax
movl (%rax), %eax
movl %eax, -0xec(%rbp)
movq -0xe8(%rbp), %rax
movl (%rax), %ecx
movq -0xe0(%rbp), %rax
movl %ecx, (%rax)
movl -0xec(%rbp), %ecx
movq -0xe8(%rbp), %rax
movl %ecx, (%rax)
movl -0xb4(%rbp), %eax
movl -0xd4(%rbp), %ecx
addl %ecx, %eax
movl %eax, -0xf0(%rbp)
movl -0x64(%rbp), %eax
andl $0x3, %eax
movl %eax, -0xf8(%rbp)
subl $0x1, %eax
je 0x12e8d
jmp 0x12da7
movl -0xf8(%rbp), %eax
subl $0x2, %eax
je 0x12e29
jmp 0x12db4
movl -0xf8(%rbp), %eax
subl $0x3, %eax
jne 0x12edd
jmp 0x12dc5
movq -0xa8(%rbp), %rax
movl -0xf0(%rbp), %ecx
addl $0x2, %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %al
movb %al, -0xf1(%rbp)
movq -0xb0(%rbp), %rax
movl -0xf0(%rbp), %ecx
addl $0x2, %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %dl
movq -0xa8(%rbp), %rax
movl -0xf0(%rbp), %ecx
addl $0x2, %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
movb -0xf1(%rbp), %dl
movq -0xb0(%rbp), %rax
movl -0xf0(%rbp), %ecx
addl $0x2, %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
movq -0xa8(%rbp), %rax
movl -0xf0(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %al
movb %al, -0xf1(%rbp)
movq -0xb0(%rbp), %rax
movl -0xf0(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movb (%rax,%rcx), %dl
movq -0xa8(%rbp), %rax
movl -0xf0(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
movb -0xf1(%rbp), %dl
movq -0xb0(%rbp), %rax
movl -0xf0(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movb %dl, (%rax,%rcx)
movq -0xa8(%rbp), %rax
movslq -0xf0(%rbp), %rcx
movb (%rax,%rcx), %al
movb %al, -0xf1(%rbp)
movq -0xb0(%rbp), %rax
movslq -0xf0(%rbp), %rcx
movb (%rax,%rcx), %dl
movq -0xa8(%rbp), %rax
movslq -0xf0(%rbp), %rcx
movb %dl, (%rax,%rcx)
movb -0xf1(%rbp), %dl
movq -0xb0(%rbp), %rax
movslq -0xf0(%rbp), %rcx
movb %dl, (%rax,%rcx)
jmp 0x12edf
addq $0x80, %rsp
popq %rbp
retq
nopl (%rax,%rax)