// File: xocoder[P]m_kcptun/vendor/cm256/gf256.cpp
// Function: gf256_self_test()
static bool gf256_self_test()
{
    if ((uintptr_t)m_SelfTestBuffers.A % GF256_ALIGN_BYTES != 0)
        return false;
    if ((uintptr_t)m_SelfTestBuffers.A % GF256_ALIGN_BYTES != 0)
        return false;
    if ((uintptr_t)m_SelfTestBuffers.B % GF256_ALIGN_BYTES != 0)
        return false;
    if ((uintptr_t)m_SelfTestBuffers.C % GF256_ALIGN_BYTES != 0)
        return false;

    // Check multiplication/division
    for (unsigned i = 0; i < 256; ++i)
    {
        for (unsigned j = 0; j < 256; ++j)
        {
            uint8_t prod = gf256_mul((uint8_t)i, (uint8_t)j);
            if (i != 0 && j != 0)
            {
                uint8_t div1 = gf256_div(prod, (uint8_t)i);
                if (div1 != j)
                    return false;
                uint8_t div2 = gf256_div(prod, (uint8_t)j);
                if (div2 != i)
                    return false;
            }
            else if (prod != 0)
                return false;
            if (j == 1 && prod != i)
                return false;
        }
    }

    // Check for overruns
    m_SelfTestBuffers.A[kTestBufferBytes] = 0x5a;
    m_SelfTestBuffers.B[kTestBufferBytes] = 0x5a;
    m_SelfTestBuffers.C[kTestBufferBytes] = 0x5a;

    // Test gf256_add_mem()
    for (unsigned i = 0; i < kTestBufferBytes; ++i)
    {
        m_SelfTestBuffers.A[i] = 0x1f;
        m_SelfTestBuffers.B[i] = 0xf7;
    }
    gf256_add_mem(m_SelfTestBuffers.A, m_SelfTestBuffers.B, kTestBufferBytes);
    for (unsigned i = 0; i < kTestBufferBytes; ++i)
        if (m_SelfTestBuffers.A[i] != (0x1f ^ 0xf7))
            return false;

    // Test gf256_add2_mem()
    for (unsigned i = 0; i < kTestBufferBytes; ++i)
    {
        m_SelfTestBuffers.A[i] = 0x1f;
        m_SelfTestBuffers.B[i] = 0xf7;
        m_SelfTestBuffers.C[i] = 0x71;
    }
    gf256_add2_mem(m_SelfTestBuffers.A, m_SelfTestBuffers.B, m_SelfTestBuffers.C, kTestBufferBytes);
    for (unsigned i = 0; i < kTestBufferBytes; ++i)
        if (m_SelfTestBuffers.A[i] != (0x1f ^ 0xf7 ^ 0x71))
            return false;

    // Test gf256_addset_mem()
    for (unsigned i = 0; i < kTestBufferBytes; ++i)
    {
        m_SelfTestBuffers.A[i] = 0x55;
        m_SelfTestBuffers.B[i] = 0xaa;
        m_SelfTestBuffers.C[i] = 0x6c;
    }
    gf256_addset_mem(m_SelfTestBuffers.A, m_SelfTestBuffers.B, m_SelfTestBuffers.C, kTestBufferBytes);
    for (unsigned i = 0; i < kTestBufferBytes; ++i)
        if (m_SelfTestBuffers.A[i] != (0xaa ^ 0x6c))
            return false;

    // Test gf256_muladd_mem()
    for (unsigned i = 0; i < kTestBufferBytes; ++i)
    {
        m_SelfTestBuffers.A[i] = 0xff;
        m_SelfTestBuffers.B[i] = 0xaa;
    }
    const uint8_t expectedMulAdd = gf256_mul(0xaa, 0x6c);
    gf256_muladd_mem(m_SelfTestBuffers.A, 0x6c, m_SelfTestBuffers.B, kTestBufferBytes);
    for (unsigned i = 0; i < kTestBufferBytes; ++i)
        if (m_SelfTestBuffers.A[i] != (expectedMulAdd ^ 0xff))
            return false;

    // Test gf256_mul_mem()
    for (unsigned i = 0; i < kTestBufferBytes; ++i)
    {
        m_SelfTestBuffers.A[i] = 0xff;
        m_SelfTestBuffers.B[i] = 0x55;
    }
    const uint8_t expectedMul = gf256_mul(0xa2, 0x55);
    gf256_mul_mem(m_SelfTestBuffers.A, m_SelfTestBuffers.B, 0xa2, kTestBufferBytes);
    for (unsigned i = 0; i < kTestBufferBytes; ++i)
        if (m_SelfTestBuffers.A[i] != expectedMul)
            return false;

    if (m_SelfTestBuffers.A[kTestBufferBytes] != 0x5a)
        return false;
    if (m_SelfTestBuffers.B[kTestBufferBytes] != 0x5a)
        return false;
    if (m_SelfTestBuffers.C[kTestBufferBytes] != 0x5a)
        return false;

    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
leaq 0x2a771(%rip), %rax     # 0x3abb0
andq $0xf, %rax
cmpq $0x0, %rax
je 0x10452
movb $0x0, -0xb(%rbp)
jmp 0x10989
leaq 0x2a757(%rip), %rax     # 0x3abb0
andq $0xf, %rax
cmpq $0x0, %rax
je 0x1046c
movb $0x0, -0xb(%rbp)
jmp 0x10989
leaq 0x2a73d(%rip), %rax     # 0x3abb0
addq $0x40, %rax
andq $0xf, %rax
cmpq $0x0, %rax
je 0x1048a
movb $0x0, -0xb(%rbp)
jmp 0x10989
leaq 0x2a71f(%rip), %rax     # 0x3abb0
addq $0x80, %rax
andq $0xf, %rax
cmpq $0x0, %rax
je 0x104aa
movb $0x0, -0xb(%rbp)
jmp 0x10989
movl $0x0, -0x10(%rbp)
cmpl $0x100, -0x10(%rbp)     # imm = 0x100
jae 0x105e4
movl $0x0, -0x14(%rbp)
cmpl $0x100, -0x14(%rbp)     # imm = 0x100
jae 0x105d4
movl -0x10(%rbp), %eax
movb %al, %cl
movl -0x14(%rbp), %eax
movb %cl, -0x1(%rbp)
movb %al, -0x2(%rbp)
movzbl -0x2(%rbp), %eax
shll $0x8, %eax
movzbl -0x1(%rbp), %ecx
addl %ecx, %eax
movl %eax, %eax
movl %eax, %ecx
leaq 0x7e98(%rip), %rax      # 0x18390
movb 0x2000(%rax,%rcx), %al
movb %al, -0x15(%rbp)
cmpl $0x0, -0x10(%rbp)
je 0x10598
cmpl $0x0, -0x14(%rbp)
je 0x10598
movb -0x15(%rbp), %cl
movl -0x10(%rbp), %eax
movb %cl, -0x7(%rbp)
movb %al, -0x8(%rbp)
movzbl -0x8(%rbp), %eax
shll $0x8, %eax
movzbl -0x7(%rbp), %ecx
addl %ecx, %eax
movl %eax, %eax
movl %eax, %ecx
leaq 0x7e56(%rip), %rax      # 0x18390
movb 0x12000(%rax,%rcx), %al
movb %al, -0x16(%rbp)
movzbl -0x16(%rbp), %eax
cmpl -0x14(%rbp), %eax
je 0x10556
movb $0x0, -0xb(%rbp)
jmp 0x10989
movb -0x15(%rbp), %cl
movl -0x14(%rbp), %eax
movb %cl, -0x9(%rbp)
movb %al, -0xa(%rbp)
movzbl -0xa(%rbp), %eax
shll $0x8, %eax
movzbl -0x9(%rbp), %ecx
addl %ecx, %eax
movl %eax, %eax
movl %eax, %ecx
leaq 0x7e16(%rip), %rax      # 0x18390
movb 0x12000(%rax,%rcx), %al
movb %al, -0x17(%rbp)
movzbl -0x17(%rbp), %eax
cmpl -0x10(%rbp), %eax
je 0x10596
movb $0x0, -0xb(%rbp)
jmp 0x10989
jmp 0x105ac
movzbl -0x15(%rbp), %eax
cmpl $0x0, %eax
je 0x105aa
movb $0x0, -0xb(%rbp)
jmp 0x10989
jmp 0x105ac
cmpl $0x1, -0x14(%rbp)
jne 0x105c4
movzbl -0x15(%rbp), %eax
cmpl -0x10(%rbp), %eax
je 0x105c4
movb $0x0, -0xb(%rbp)
jmp 0x10989
jmp 0x105c6
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x104c5
jmp 0x105d6
movl -0x10(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x10(%rbp)
jmp 0x104b1
movb $0x5a, 0x2a604(%rip)    # 0x3abef
movb $0x5a, 0x2a63d(%rip)    # 0x3ac2f
movb $0x5a, 0x2a676(%rip)    # 0x3ac6f
movl $0x0, -0x1c(%rbp)
cmpl $0x3f, -0x1c(%rbp)
jae 0x10632
movl -0x1c(%rbp), %eax
movl %eax, %ecx
leaq 0x2a59e(%rip), %rax     # 0x3abb0
movb $0x1f, (%rax,%rcx)
movl -0x1c(%rbp), %eax
movl %eax, %ecx
leaq 0x2a58e(%rip), %rax     # 0x3abb0
movb $-0x9, 0x40(%rax,%rcx)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x10600
leaq 0x2a577(%rip), %rdi     # 0x3abb0
movq %rdi, %rsi
addq $0x40, %rsi
movl $0x3f, %edx
callq 0x109a0
movl $0x0, -0x20(%rbp)
cmpl $0x3f, -0x20(%rbp)
jae 0x10684
movl -0x20(%rbp), %eax
movl %eax, %ecx
leaq 0x2a54d(%rip), %rax     # 0x3abb0
movzbl (%rax,%rcx), %eax
cmpl $0xe8, %eax
je 0x10677
movb $0x0, -0xb(%rbp)
jmp 0x10989
jmp 0x10679
movl -0x20(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x20(%rbp)
jmp 0x10651
movl $0x0, -0x24(%rbp)
cmpl $0x3f, -0x24(%rbp)
jae 0x106d1
movl -0x24(%rbp), %eax
movl %eax, %ecx
leaq 0x2a513(%rip), %rax     # 0x3abb0
movb $0x1f, (%rax,%rcx)
movl -0x24(%rbp), %eax
movl %eax, %ecx
leaq 0x2a503(%rip), %rax     # 0x3abb0
movb $-0x9, 0x40(%rax,%rcx)
movl -0x24(%rbp), %eax
movl %eax, %ecx
leaq 0x2a4f2(%rip), %rax     # 0x3abb0
movb $0x71, 0x80(%rax,%rcx)
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x1068b
leaq 0x2a4d8(%rip), %rdi     # 0x3abb0
movq %rdi, %rsi
addq $0x40, %rsi
movq %rdi, %rdx
addq $0x80, %rdx
movl $0x3f, %ecx
callq 0x10f30
movl $0x0, -0x28(%rbp)
cmpl $0x3f, -0x28(%rbp)
jae 0x1072d
movl -0x28(%rbp), %eax
movl %eax, %ecx
leaq 0x2a4a4(%rip), %rax     # 0x3abb0
movzbl (%rax,%rcx), %eax
cmpl $0x99, %eax
je 0x10720
movb $0x0, -0xb(%rbp)
jmp 0x10989
jmp 0x10722
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x28(%rbp)
jmp 0x106fa
movl $0x0, -0x2c(%rbp)
cmpl $0x3f, -0x2c(%rbp)
jae 0x1077a
movl -0x2c(%rbp), %eax
movl %eax, %ecx
leaq 0x2a46a(%rip), %rax     # 0x3abb0
movb $0x55, (%rax,%rcx)
movl -0x2c(%rbp), %eax
movl %eax, %ecx
leaq 0x2a45a(%rip), %rax     # 0x3abb0
movb $-0x56, 0x40(%rax,%rcx)
movl -0x2c(%rbp), %eax
movl %eax, %ecx
leaq 0x2a449(%rip), %rax     # 0x3abb0
movb $0x6c, 0x80(%rax,%rcx)
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x10734
leaq 0x2a42f(%rip), %rdi     # 0x3abb0
movq %rdi, %rsi
addq $0x40, %rsi
movq %rdi, %rdx
addq $0x80, %rdx
movl $0x3f, %ecx
callq 0x11290
movl $0x0, -0x30(%rbp)
cmpl $0x3f, -0x30(%rbp)
jae 0x107d6
movl -0x30(%rbp), %eax
movl %eax, %ecx
leaq 0x2a3fb(%rip), %rax     # 0x3abb0
movzbl (%rax,%rcx), %eax
cmpl $0xc6, %eax
je 0x107c9
movb $0x0, -0xb(%rbp)
jmp 0x10989
jmp 0x107cb
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x107a3
movl $0x0, -0x34(%rbp)
cmpl $0x3f, -0x34(%rbp)
jae 0x1080f
movl -0x34(%rbp), %eax
movl %eax, %ecx
leaq 0x2a3c1(%rip), %rax     # 0x3abb0
movb $-0x1, (%rax,%rcx)
movl -0x34(%rbp), %eax
movl %eax, %ecx
leaq 0x2a3b1(%rip), %rax     # 0x3abb0
movb $-0x56, 0x40(%rax,%rcx)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x107dd
movb $-0x56, -0x3(%rbp)
movb $0x6c, -0x4(%rbp)
movzbl -0x4(%rbp), %eax
shll $0x8, %eax
movzbl -0x3(%rbp), %ecx
addl %ecx, %eax
movl %eax, %eax
movl %eax, %ecx
leaq 0x7b61(%rip), %rax      # 0x18390
movb 0x2000(%rax,%rcx), %al
movb %al, -0x35(%rbp)
leaq 0x2a370(%rip), %rdi     # 0x3abb0
movl $0x6c, %esi
movq %rdi, %rdx
addq $0x40, %rdx
movl $0x3f, %ecx
callq 0x11fe0
movl $0x0, -0x3c(%rbp)
cmpl $0x3f, -0x3c(%rbp)
jae 0x10897
movl -0x3c(%rbp), %eax
movl %eax, %ecx
leaq 0x2a341(%rip), %rax     # 0x3abb0
movzbl (%rax,%rcx), %eax
movzbl -0x35(%rbp), %ecx
xorl $0xff, %ecx
cmpl %ecx, %eax
je 0x1088a
movb $0x0, -0xb(%rbp)
jmp 0x10989
jmp 0x1088c
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x1085d
movl $0x0, -0x40(%rbp)
cmpl $0x3f, -0x40(%rbp)
jae 0x108d0
movl -0x40(%rbp), %eax
movl %eax, %ecx
leaq 0x2a300(%rip), %rax     # 0x3abb0
movb $-0x1, (%rax,%rcx)
movl -0x40(%rbp), %eax
movl %eax, %ecx
leaq 0x2a2f0(%rip), %rax     # 0x3abb0
movb $0x55, 0x40(%rax,%rcx)
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x1089e
movb $-0x5e, -0x5(%rbp)
movb $0x55, -0x6(%rbp)
movzbl -0x6(%rbp), %eax
shll $0x8, %eax
movzbl -0x5(%rbp), %ecx
addl %ecx, %eax
movl %eax, %eax
movl %eax, %ecx
leaq 0x7aa0(%rip), %rax      # 0x18390
movb 0x2000(%rax,%rcx), %al
movb %al, -0x41(%rbp)
leaq 0x2a2af(%rip), %rdi     # 0x3abb0
movq %rdi, %rsi
addq $0x40, %rsi
movl $0xa2, %edx
movl $0x3f, %ecx
callq 0x11890
movl $0x0, -0x48(%rbp)
cmpl $0x3f, -0x48(%rbp)
jae 0x1094f
movl -0x48(%rbp), %eax
movl %eax, %ecx
leaq 0x2a280(%rip), %rax     # 0x3abb0
movzbl (%rax,%rcx), %eax
movzbl -0x41(%rbp), %ecx
cmpl %ecx, %eax
je 0x10942
movb $0x0, -0xb(%rbp)
jmp 0x10989
jmp 0x10944
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x1091e
movzbl 0x2a299(%rip), %eax     # 0x3abef
cmpl $0x5a, %eax
je 0x10961
movb $0x0, -0xb(%rbp)
jmp 0x10989
movzbl 0x2a2c7(%rip), %eax     # 0x3ac2f
cmpl $0x5a, %eax
je 0x10973
movb $0x0, -0xb(%rbp)
jmp 0x10989
movzbl 0x2a2f5(%rip), %eax     # 0x3ac6f
cmpl $0x5a, %eax
je 0x10985
movb $0x0, -0xb(%rbp)
jmp 0x10989
movb $0x1, -0xb(%rbp)
movb -0xb(%rbp), %al
andb $0x1, %al
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)