// File: /workspace/github_c_makefile_star2_O0/pahihu[P]mixal/cell.c
// Function: multiply
void multiply(Cell x, Cell y, Cell *high_word, Cell *low_word)
{
    unsigned long sign = sign_bit(x) ^ sign_bit(y);

    /*
       x = x0 + x1 * 2 ^ 10 + x2 * 2 ^ 20
       y = y0 + y1 * 2 ^ 10 + y2 * 2 ^ 20
       x0, x1, x2, y0, y1, y2 are < 2 ^ 10
    */
    unsigned long x0 = (x & 0x000003FF);
    unsigned long x1 = (x & 0x000FFC00) >> 10;
    unsigned long x2 = (x & 0x3FF00000) >> 20;
    unsigned long y0 = (y & 0x000003FF);
    unsigned long y1 = (y & 0x000FFC00) >> 10;
    unsigned long y2 = (y & 0x3FF00000) >> 20;

    /*
       x * y = partial0 +
               partial1 * 2 ^ 10 +
               partial2 * 2 ^ 20 +
               partial3 * 2 ^ 30 +
               partial4 * 2 ^ 40
       partial0 and partial4 are <     2 ^ 20
       partial1 and partial3 are <     2 ^ 21
       partial2 is               < 3 * 2 ^ 20
    */
    unsigned long partial0 = x0 * y0;
    unsigned long partial1 = x0 * y1 + x1 * y0;
    unsigned long partial2 = x0 * y2 + x1 * y1 + x2 * y0;
    unsigned long partial3 = x1 * y2 + x2 * y1;
    unsigned long partial4 = x2 * y2;

    /*  sum1 has a place value of 1 and is < 2 ^ 32 */
    unsigned long sum1   = partial0 + (partial1 << 10);
    unsigned long carry1 = (sum1 & 0xFFF00000) >> 20;

    /* sum2 has a place value of 2 ^ 20 and is < 2 ^ 32 */
    unsigned long sum2   = partial2 + (partial3 << 10) + carry1;
    unsigned long carry2 = (sum2 & 0xFFF00000) >> 20;

    /* sum3 has a place value of 2 ^ 40 and is < 2 ^ 20 */
    unsigned long sum3   = partial4 + carry2;

    sum1 &= ~0xFFF00000;
    sum2 &= ~0xFFF00000;

    /*
       Now paste the three values back into two.
    */
    *low_word   = sum1 | ((sum2 & 0x000003FF) << 20);
    *low_word  |= sign;
    *high_word  = ((sum2 & 0x000FFC00) >> 10) | (sum3 << 10);
    *high_word |= sign;

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x28, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq -0x8(%rbp), %rax
andq $0x40000000, %rax       # imm = 0x40000000
movq -0x10(%rbp), %rcx
andq $0x40000000, %rcx       # imm = 0x40000000
xorq %rcx, %rax
movq %rax, -0x28(%rbp)
movq -0x8(%rbp), %rax
andq $0x3ff, %rax            # imm = 0x3FF
movq %rax, -0x30(%rbp)
movq -0x8(%rbp), %rax
andq $0xffc00, %rax          # imm = 0xFFC00
sarq $0xa, %rax
movq %rax, -0x38(%rbp)
movq -0x8(%rbp), %rax
andq $0x3ff00000, %rax       # imm = 0x3FF00000
sarq $0x14, %rax
movq %rax, -0x40(%rbp)
movq -0x10(%rbp), %rax
andq $0x3ff, %rax            # imm = 0x3FF
movq %rax, -0x48(%rbp)
movq -0x10(%rbp), %rax
andq $0xffc00, %rax          # imm = 0xFFC00
sarq $0xa, %rax
movq %rax, -0x50(%rbp)
movq -0x10(%rbp), %rax
andq $0x3ff00000, %rax       # imm = 0x3FF00000
sarq $0x14, %rax
movq %rax, -0x58(%rbp)
movq -0x30(%rbp), %rax
imulq -0x48(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x30(%rbp), %rax
imulq -0x50(%rbp), %rax
movq -0x38(%rbp), %rcx
imulq -0x48(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x68(%rbp)
movq -0x30(%rbp), %rax
imulq -0x58(%rbp), %rax
movq -0x38(%rbp), %rcx
imulq -0x50(%rbp), %rcx
addq %rcx, %rax
movq -0x40(%rbp), %rcx
imulq -0x48(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x70(%rbp)
movq -0x38(%rbp), %rax
imulq -0x58(%rbp), %rax
movq -0x40(%rbp), %rcx
imulq -0x50(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x78(%rbp)
movq -0x40(%rbp), %rax
imulq -0x58(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x60(%rbp), %rax
movq -0x68(%rbp), %rcx
shlq $0xa, %rcx
addq %rcx, %rax
movq %rax, -0x88(%rbp)
movabsq $0xfff00000, %rax       # imm = 0xFFF00000
andq -0x88(%rbp), %rax
shrq $0x14, %rax
movq %rax, -0x90(%rbp)
movq -0x70(%rbp), %rax
movq -0x78(%rbp), %rcx
shlq $0xa, %rcx
addq %rcx, %rax
addq -0x90(%rbp), %rax
movq %rax, -0x98(%rbp)
movabsq $0xfff00000, %rax       # imm = 0xFFF00000
andq -0x98(%rbp), %rax
shrq $0x14, %rax
movq %rax, -0xa0(%rbp)
movq -0x80(%rbp), %rax
addq -0xa0(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0x88(%rbp), %rax
andq $0xfffff, %rax          # imm = 0xFFFFF
movq %rax, -0x88(%rbp)
movq -0x98(%rbp), %rax
andq $0xfffff, %rax          # imm = 0xFFFFF
movq %rax, -0x98(%rbp)
movq -0x88(%rbp), %rcx
movq -0x98(%rbp), %rax
andq $0x3ff, %rax            # imm = 0x3FF
shlq $0x14, %rax
orq %rax, %rcx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
movq -0x28(%rbp), %rcx
movq -0x20(%rbp), %rax
orq (%rax), %rcx
movq %rcx, (%rax)
movq -0x98(%rbp), %rcx
andq $0xffc00, %rcx          # imm = 0xFFC00
shrq $0xa, %rcx
movq -0xa8(%rbp), %rax
shlq $0xa, %rax
orq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x28(%rbp), %rcx
movq -0x18(%rbp), %rax
orq (%rax), %rcx
movq %rcx, (%rax)
addq $0x28, %rsp
popq %rbp
retq
nopl (%rax)