// File: /workspace/github_c_makefile_star2_O2/wjmelements[P]evm/src/uint256.c
// Function: mul512
void mul512(const uint512_t *number1, const uint512_t *number2, uint512_t *target) {
    uint256_t top[4];
    uint256_t bottom[4];
    clear128(&UPPER(top[0]));
    copy128(&LOWER(top[0]), &UPPER(UPPER_P(number1)));
    clear128(&UPPER(top[1]));
    copy128(&LOWER(top[1]), &LOWER(UPPER_P(number1)));
    clear128(&UPPER(top[2]));
    copy128(&LOWER(top[2]), &UPPER(LOWER_P(number1)));
    clear128(&UPPER(top[3]));
    copy128(&LOWER(top[3]), &LOWER(LOWER_P(number1)));
    clear128(&UPPER(bottom[0]));
    copy128(&LOWER(bottom[0]), &UPPER(UPPER_P(number2)));
    clear128(&UPPER(bottom[1]));
    copy128(&LOWER(bottom[1]), &LOWER(UPPER_P(number2)));
    clear128(&UPPER(bottom[2]));
    copy128(&LOWER(bottom[2]), &UPPER(LOWER_P(number2)));
    clear128(&UPPER(bottom[3]));
    copy128(&LOWER(bottom[3]), &LOWER(LOWER_P(number2)));

    uint256_t products[4][4];
    for (uint8_t y = 4; y --> 0;) {
        for (uint8_t x = 4; x --> 0;) {
            mul256(&top[x], &bottom[y], &products[x][y]);
        }
    }

    uint256_t tmp, tmp2, fourth64, third64, second64, first64;
    clear128(&UPPER(fourth64));
    copy128(&LOWER(fourth64), &LOWER(products[3][3]));
    clear128(&UPPER(tmp));
    copy128(&LOWER(tmp), &LOWER(products[3][2]));
    clear128(&UPPER(tmp2));
    copy128(&LOWER(tmp2), &UPPER(products[3][3]));
    add256(&tmp, &tmp2, &third64);
    clear128(&UPPER(tmp));
    copy128(&LOWER(tmp), &LOWER(products[3][1]));
    clear128(&UPPER(tmp2));
    copy128(&LOWER(tmp2), &UPPER(products[3][2]));
    add256(&tmp, &tmp2, &second64);
    clear128(&UPPER(tmp));
    copy128(&LOWER(tmp), &LOWER(products[3][0]));
    clear128(&UPPER(tmp2));
    copy128(&LOWER(tmp2), &UPPER(products[3][1]));
    add256(&tmp, &tmp2, &first64);

    clear128(&UPPER(tmp));
    copy128(&LOWER(tmp), &LOWER(products[2][3]));
    add256(&tmp, &third64, &third64);
    clear128(&UPPER(tmp));
    copy128(&LOWER(tmp), &LOWER(products[2][2]));
    add256(&tmp, &second64, &tmp2);
    clear128(&UPPER(tmp));
    copy128(&LOWER(tmp), &UPPER(products[2][3]));
    add256(&tmp, &tmp2, &second64);
    clear128(&UPPER(tmp));
    copy128(&LOWER(tmp), &LOWER(products[2][1]));
    add256(&tmp, &first64, &tmp2);
    clear128(&UPPER(tmp));
    copy128(&LOWER(tmp), &UPPER(products[2][2]));
    add256(&tmp, &tmp2, &first64);

    clear128(&UPPER(tmp));
    copy128(&LOWER(tmp), &LOWER(products[1][3]));
    add256(&tmp, &second64, &second64);
    clear128(&UPPER(tmp));
    copy128(&LOWER(tmp), &LOWER(products[1][2]));
    add256(&tmp, &first64, &tmp2);
    clear128(&UPPER(tmp));
    copy128(&LOWER(tmp), &UPPER(products[1][3]));
    add256(&tmp, &tmp2, &first64);

    clear128(&UPPER(tmp));
    copy128(&LOWER(tmp), &LOWER(products[0][3]));
    add256(&tmp, &first64, &first64);

    uint512_t target1, target2;
    clear512(&target1);
    copy128(&UPPER(UPPER(target1)), &LOWER(first64));
    clear512(&target2);
    copy128(&LOWER(UPPER(target2)), &UPPER(third64));
    copy128(&UPPER(LOWER(target2)), &LOWER(third64));
    add512(&target1, &target2, target);
    clear512(&target1);
    copy256(&UPPER(target1), &second64);
    add512(&target1, target, &target2);
    clear512(&target1);
    copy256(&LOWER(target1), &fourth64);
    add512(&target1, &target2, target);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x428, %rsp            # imm = 0x428
movq %rdx, %rbx
xorps %xmm0, %xmm0
movaps %xmm0, 0x80(%rsp)
movups (%rdi), %xmm1
movaps %xmm1, 0x90(%rsp)
movaps %xmm0, 0xa0(%rsp)
movups 0x10(%rdi), %xmm1
movaps %xmm1, 0xb0(%rsp)
movaps %xmm0, 0xc0(%rsp)
movups 0x20(%rdi), %xmm1
movaps %xmm1, 0xd0(%rsp)
movaps %xmm0, 0xe0(%rsp)
movups 0x30(%rdi), %xmm1
movaps %xmm1, 0xf0(%rsp)
movaps %xmm0, (%rsp)
movups (%rsi), %xmm1
movaps %xmm1, 0x10(%rsp)
movaps %xmm0, 0x20(%rsp)
movups 0x10(%rsi), %xmm1
movaps %xmm1, 0x30(%rsp)
movaps %xmm0, 0x40(%rsp)
movups 0x20(%rsi), %xmm1
movaps %xmm1, 0x50(%rsp)
movaps %xmm0, 0x60(%rsp)
movups 0x30(%rsi), %xmm0
movaps %xmm0, 0x70(%rsp)
pushq $0x4
popq %r15
pushq $0x3
popq %r12
subq $0x1, %r15
jb 0x4240
movzbl %r15b, %r13d
movl %r13d, %eax
shll $0x5, %eax
leaq (%rsp,%rax), %r14
movq %r12, %rbp
cmpq $-0x1, %rbp
je 0x41ed
movzbl %bpl, %eax
movl %eax, %ecx
shll $0x5, %ecx
leaq (%rsp,%rcx), %rdi
addq $0x80, %rdi
movl %r13d, %edx
shll $0x5, %edx
shll $0x7, %eax
addq %rsp, %rax
addq $0x100, %rax            # imm = 0x100
addq %rax, %rdx
movq %r14, %rsi
callq 0x3f32
decq %rbp
jmp 0x4204
xorps %xmm2, %xmm2
leaq 0x360(%rsp), %r12
movaps %xmm2, (%r12)
movaps 0x2d0(%rsp), %xmm0
movaps 0x2e0(%rsp), %xmm1
movaps %xmm0, 0x10(%r12)
leaq 0x340(%rsp), %r13
movaps %xmm2, (%r13)
movaps %xmm1, 0x10(%r13)
leaq 0x320(%rsp), %r14
movq %r12, %rdi
movq %r13, %rsi
movq %r14, %rdx
callq 0x36e3
xorps %xmm2, %xmm2
movaps %xmm2, (%r12)
movaps 0x2b0(%rsp), %xmm0
movaps 0x2c0(%rsp), %xmm1
movaps %xmm0, 0x10(%r12)
movaps %xmm2, (%r13)
movaps %xmm1, 0x10(%r13)
leaq 0x300(%rsp), %r15
movq %r12, %rdi
movq %r13, %rsi
movq %r15, %rdx
callq 0x36e3
xorps %xmm2, %xmm2
movaps %xmm2, (%r12)
movaps 0x290(%rsp), %xmm0
movaps 0x2a0(%rsp), %xmm1
movaps %xmm0, 0x10(%r12)
movaps %xmm2, (%r13)
movaps %xmm1, 0x10(%r13)
leaq 0x380(%rsp), %rbp
movq %r12, %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq 0x36e3
xorps %xmm0, %xmm0
movaps %xmm0, (%r12)
movaps 0x270(%rsp), %xmm0
movaps %xmm0, 0x10(%r12)
movq %r12, %rdi
movq %r14, %rsi
movq %r14, %rdx
callq 0x36e3
xorps %xmm0, %xmm0
movaps %xmm0, (%r12)
movaps 0x250(%rsp), %xmm0
movaps %xmm0, 0x10(%r12)
movq %r12, %rdi
movq %r15, %rsi
movq %r13, %rdx
callq 0x36e3
xorps %xmm0, %xmm0
movaps %xmm0, (%r12)
movaps 0x260(%rsp), %xmm0
movaps %xmm0, 0x10(%r12)
movq %r12, %rdi
movq %r13, %rsi
movq %r15, %rdx
callq 0x36e3
xorps %xmm0, %xmm0
movaps %xmm0, (%r12)
movaps 0x230(%rsp), %xmm0
movaps %xmm0, 0x10(%r12)
movq %r12, %rdi
movq %rbp, %rsi
movq %r13, %rdx
callq 0x36e3
xorps %xmm0, %xmm0
movaps %xmm0, (%r12)
movaps 0x240(%rsp), %xmm0
movaps %xmm0, 0x10(%r12)
movq %r12, %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq 0x36e3
xorps %xmm0, %xmm0
movaps %xmm0, (%r12)
movaps 0x1f0(%rsp), %xmm0
movaps %xmm0, 0x10(%r12)
movq %r12, %rdi
movq %r15, %rsi
movq %r15, %rdx
callq 0x36e3
xorps %xmm0, %xmm0
movaps %xmm0, (%r12)
movaps 0x1d0(%rsp), %xmm0
movaps %xmm0, 0x10(%r12)
movq %r12, %rdi
movq %rbp, %rsi
movq %r13, %rdx
callq 0x36e3
xorps %xmm0, %xmm0
movaps %xmm0, (%r12)
movaps 0x1e0(%rsp), %xmm0
movaps %xmm0, 0x10(%r12)
movq %r12, %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq 0x36e3
xorps %xmm0, %xmm0
movaps %xmm0, (%r12)
movaps 0x170(%rsp), %xmm0
movaps %xmm0, 0x10(%r12)
movq %r12, %rdi
movq %rbp, %rsi
movq %rbp, %rdx
callq 0x36e3
leaq 0x3e0(%rsp), %r12
xorps %xmm1, %xmm1
movaps %xmm1, 0x10(%r12)
movaps %xmm1, 0x20(%r12)
movaps %xmm1, 0x30(%r12)
movups 0x10(%rbp), %xmm0
movaps %xmm0, (%r12)
leaq 0x3a0(%rsp), %r13
movaps %xmm1, (%r13)
movaps %xmm1, 0x30(%r13)
movaps (%r14), %xmm0
movaps 0x10(%r14), %xmm1
movaps %xmm0, 0x10(%r13)
movaps %xmm1, 0x20(%r13)
movq %r12, %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x3b1f
xorps %xmm0, %xmm0
movaps %xmm0, 0x30(%r12)
movaps %xmm0, 0x20(%r12)
movaps (%r15), %xmm0
movaps 0x10(%r15), %xmm1
movaps %xmm0, (%r12)
movaps %xmm1, 0x10(%r12)
movq %r12, %rdi
movq %rbx, %rsi
movq %r13, %rdx
callq 0x3b1f
xorps %xmm0, %xmm0
movaps %xmm0, 0x20(%r12)
movaps %xmm0, 0x10(%r12)
movaps %xmm0, (%r12)
movaps 0x2f0(%rsp), %xmm0
movaps %xmm0, 0x30(%r12)
movq %r12, %rdi
movq %r13, %rsi
movq %rbx, %rdx
callq 0x3b1f
addq $0x428, %rsp            # imm = 0x428
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq