#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
int /*<<< orphan*/ freeze(unsigned int *);
int /*<<< orphan*/ mainloop(unsigned int *, unsigned char const *);
int /*<<< orphan*/ mult(unsigned int *, unsigned int *, unsigned int *);
int /*<<< orphan*/ recip(unsigned int *, unsigned int *);
int curve25519(unsigned char *q, const unsigned char *n,
               const unsigned char *p) {
  unsigned int work[96];
  unsigned int i;
  for (i = 0; i < 32; ++i)
    work[i] = p[i];
  work[31] &= 127;
  mainloop(work, n);
  recip(work + 32, work + 32);
  mult(work + 64, work, work + 32);
  freeze(work + 64);
  for (i = 0; i < 32; ++i)
    q[i] = work[64 + i];
  return 0;
}


x86 assembly (clang, -O0):
<curve25519>:
push   %rbp
mov    %rsp,%rbp
sub    $0x1b0,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
movl   $0x0,-0x1a4(%rbp)
cmpl   $0x20,-0x1a4(%rbp)
jae    119d <curve25519+0x5d>
mov    -0x18(%rbp),%rax
mov    -0x1a4(%rbp),%ecx
movzbl (%rax,%rcx,1),%ecx
mov    -0x1a4(%rbp),%eax
mov    %ecx,-0x1a0(%rbp,%rax,4)
mov    -0x1a4(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1a4(%rbp)
jmp    1161 <curve25519+0x21>
mov    -0x124(%rbp),%eax
and    $0x7f,%eax
mov    %eax,-0x124(%rbp)
lea    -0x1a0(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1060 <mainloop@plt>
lea    -0x1a0(%rbp),%rdi
add    $0x80,%rdi
lea    -0x1a0(%rbp),%rsi
add    $0x80,%rsi
call   1050 <recip@plt>
lea    -0x1a0(%rbp),%rdi
add    $0x100,%rdi
lea    -0x1a0(%rbp),%rsi
lea    -0x1a0(%rbp),%rdx
add    $0x80,%rdx
call   1030 <mult@plt>
lea    -0x1a0(%rbp),%rdi
add    $0x100,%rdi
call   1040 <freeze@plt>
movl   $0x0,-0x1a4(%rbp)
cmpl   $0x20,-0x1a4(%rbp)
jae    1264 <curve25519+0x124>
mov    -0x1a4(%rbp),%eax
add    $0x40,%eax
mov    %eax,%eax
mov    -0x1a0(%rbp,%rax,4),%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x1a4(%rbp),%ecx
mov    %dl,(%rax,%rcx,1)
mov    -0x1a4(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x1a4(%rbp)
jmp    1222 <curve25519+0xe2>
xor    %eax,%eax
add    $0x1b0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<curve25519>:
push   %r15
push   %r14
push   %r12
push   %rbx
sub    $0x188,%rsp
mov    %rdi,%r15
movd   (%rdx),%xmm1
pxor   %xmm0,%xmm0
punpcklbw %xmm0,%xmm1
punpcklwd %xmm0,%xmm1
movdqa %xmm1,(%rsp)
movd   0x4(%rdx),%xmm1
punpcklbw %xmm0,%xmm1
punpcklwd %xmm0,%xmm1
movdqa %xmm1,0x10(%rsp)
movd   0x8(%rdx),%xmm1
punpcklbw %xmm0,%xmm1
punpcklwd %xmm0,%xmm1
movdqa %xmm1,0x20(%rsp)
movd   0xc(%rdx),%xmm1
punpcklbw %xmm0,%xmm1
punpcklwd %xmm0,%xmm1
movdqa %xmm1,0x30(%rsp)
movd   0x10(%rdx),%xmm1
punpcklbw %xmm0,%xmm1
punpcklwd %xmm0,%xmm1
movdqa %xmm1,0x40(%rsp)
movd   0x14(%rdx),%xmm1
punpcklbw %xmm0,%xmm1
punpcklwd %xmm0,%xmm1
movdqa %xmm1,0x50(%rsp)
movd   0x18(%rdx),%xmm1
punpcklbw %xmm0,%xmm1
punpcklwd %xmm0,%xmm1
movdqa %xmm1,0x60(%rsp)
movzbl 0x1c(%rdx),%eax
mov    %eax,0x70(%rsp)
movzbl 0x1d(%rdx),%eax
mov    %eax,0x74(%rsp)
movzbl 0x1e(%rdx),%eax
mov    %eax,0x78(%rsp)
movzbl 0x1f(%rdx),%eax
and    $0x7f,%eax
mov    %eax,0x7c(%rsp)
mov    %rsp,%r14
mov    %r14,%rdi
call   1060 <mainloop@plt>
lea    0x80(%rsp),%rbx
mov    %rbx,%rdi
mov    %rbx,%rsi
call   1050 <recip@plt>
lea    0x100(%rsp),%r12
mov    %r12,%rdi
mov    %r14,%rsi
mov    %rbx,%rdx
call   1030 <mult@plt>
mov    %r12,%rdi
call   1040 <freeze@plt>
movdqa 0xdc1(%rip),%xmm0
movdqa 0x100(%rsp),%xmm1
pand   %xmm0,%xmm1
packuswb %xmm1,%xmm1
packuswb %xmm1,%xmm1
movd   %xmm1,(%r15)
movdqa 0x110(%rsp),%xmm1
pand   %xmm0,%xmm1
packuswb %xmm1,%xmm1
packuswb %xmm1,%xmm1
movd   %xmm1,0x4(%r15)
movdqa 0x120(%rsp),%xmm1
pand   %xmm0,%xmm1
packuswb %xmm1,%xmm1
packuswb %xmm1,%xmm1
movd   %xmm1,0x8(%r15)
movdqa 0x130(%rsp),%xmm1
pand   %xmm0,%xmm1
packuswb %xmm1,%xmm1
packuswb %xmm1,%xmm1
movd   %xmm1,0xc(%r15)
movdqa 0x140(%rsp),%xmm1
pand   %xmm0,%xmm1
packuswb %xmm1,%xmm1
packuswb %xmm1,%xmm1
movd   %xmm1,0x10(%r15)
movdqa 0x150(%rsp),%xmm1
pand   %xmm0,%xmm1
packuswb %xmm1,%xmm1
packuswb %xmm1,%xmm1
movd   %xmm1,0x14(%r15)
movdqa 0x160(%rsp),%xmm1
pand   %xmm0,%xmm1
packuswb %xmm1,%xmm1
packuswb %xmm1,%xmm1
movd   %xmm1,0x18(%r15)
pand   0x170(%rsp),%xmm0
packuswb %xmm0,%xmm0
packuswb %xmm0,%xmm0
movd   %xmm0,0x1c(%r15)
xor    %eax,%eax
add    $0x188,%rsp
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
define i32 @curve25519(i8* %0, i8* %1, i8* %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i8*
%7 = alloca [96 x i32]
%8 = alloca i32
store i8* %0, i8** %4
store i8* %1, i8** %5
store i8* %2, i8** %6
store i32 0, i32* %8
br label %9
9: ; preds = %22, %3
%10 = load i32, i32* %8
%11 = icmp ult i32 %10, 32
br i1 %11, label %12, label %25
12: ; preds = %9
%13 = load i8*, i8** %6
%14 = load i32, i32* %8
%15 = zext i32 %14 to i64
%16 = getelementptr inbounds i8, i8* %13, i64 %15
%17 = load i8, i8* %16
%18 = zext i8 %17 to i32
%19 = load i32, i32* %8
%20 = zext i32 %19 to i64
%21 = getelementptr inbounds [96 x i32], [96 x i32]* %7, i64 0, i64 %20
store i32 %18, i32* %21
br label %22
22: ; preds = %12
%23 = load i32, i32* %8
%24 = add i32 %23, 1
store i32 %24, i32* %8
br label %9
25: ; preds = %9
%26 = getelementptr inbounds [96 x i32], [96 x i32]* %7, i64 0, i64 31
%27 = load i32, i32* %26
%28 = and i32 %27, 127
store i32 %28, i32* %26
%29 = getelementptr inbounds [96 x i32], [96 x i32]* %7, i64 0, i64 0
%30 = load i8*, i8** %5
%31 = call i32 @mainloop(i32* %29, i8* %30)
%32 = getelementptr inbounds [96 x i32], [96 x i32]* %7, i64 0, i64 0
%33 = getelementptr inbounds i32, i32* %32, i64 32
%34 = getelementptr inbounds [96 x i32], [96 x i32]* %7, i64 0, i64 0
%35 = getelementptr inbounds i32, i32* %34, i64 32
%36 = call i32 @recip(i32* %33, i32* %35)
%37 = getelementptr inbounds [96 x i32], [96 x i32]* %7, i64 0, i64 0
%38 = getelementptr inbounds i32, i32* %37, i64 64
%39 = getelementptr inbounds [96 x i32], [96 x i32]* %7, i64 0, i64 0
%40 = getelementptr inbounds [96 x i32], [96 x i32]* %7, i64 0, i64 0
%41 = getelementptr inbounds i32, i32* %40, i64 32
%42 = call i32 @mult(i32* %38, i32* %39, i32* %41)
%43 = getelementptr inbounds [96 x i32], [96 x i32]* %7, i64 0, i64 0
%44 = getelementptr inbounds i32, i32* %43, i64 64
%45 = call i32 @freeze(i32* %44)
store i32 0, i32* %8
br label %46
46: ; preds = %60, %25
%47 = load i32, i32* %8
%48 = icmp ult i32 %47, 32
br i1 %48, label %49, label %63
49: ; preds = %46
%50 = load i32, i32* %8
%51 = add i32 64, %50
%52 = zext i32 %51 to i64
%53 = getelementptr inbounds [96 x i32], [96 x i32]* %7, i64 0, i64 %52
%54 = load i32, i32* %53
%55 = trunc i32 %54 to i8
%56 = load i8*, i8** %4
%57 = load i32, i32* %8
%58 = zext i32 %57 to i64
%59 = getelementptr inbounds i8, i8* %56, i64 %58
store i8 %55, i8* %59
br label %60
60: ; preds = %49
%61 = load i32, i32* %8
%62 = add i32 %61, 1
store i32 %62, i32* %8
br label %46
63: ; preds = %46
ret i32 0
}

LLVM IR (-O2):
define i32 @curve25519(i8* nocapture writeonly %0, i8* %1, i8* nocapture %2) {
%4 = alloca [96 x i32]
%5 = bitcast [96 x i32]* %4 to i8*
%6 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 0
%7 = bitcast i8* %2 to <4 x i8>*
%8 = load <4 x i8>, <4 x i8>* %7
%9 = zext <4 x i8> %8 to <4 x i32>
%10 = bitcast [96 x i32]* %4 to <4 x i32>*
store <4 x i32> %9, <4 x i32>* %10
%11 = getelementptr inbounds i8, i8* %2, i64 4
%12 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 4
%13 = bitcast i8* %11 to <4 x i8>*
%14 = load <4 x i8>, <4 x i8>* %13
%15 = zext <4 x i8> %14 to <4 x i32>
%16 = bitcast i32* %12 to <4 x i32>*
store <4 x i32> %15, <4 x i32>* %16
%17 = getelementptr inbounds i8, i8* %2, i64 8
%18 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 8
%19 = bitcast i8* %17 to <4 x i8>*
%20 = load <4 x i8>, <4 x i8>* %19
%21 = zext <4 x i8> %20 to <4 x i32>
%22 = bitcast i32* %18 to <4 x i32>*
store <4 x i32> %21, <4 x i32>* %22
%23 = getelementptr inbounds i8, i8* %2, i64 12
%24 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 12
%25 = bitcast i8* %23 to <4 x i8>*
%26 = load <4 x i8>, <4 x i8>* %25
%27 = zext <4 x i8> %26 to <4 x i32>
%28 = bitcast i32* %24 to <4 x i32>*
store <4 x i32> %27, <4 x i32>* %28
%29 = getelementptr inbounds i8, i8* %2, i64 16
%30 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 16
%31 = bitcast i8* %29 to <4 x i8>*
%32 = load <4 x i8>, <4 x i8>* %31
%33 = zext <4 x i8> %32 to <4 x i32>
%34 = bitcast i32* %30 to <4 x i32>*
store <4 x i32> %33, <4 x i32>* %34
%35 = getelementptr inbounds i8, i8* %2, i64 20
%36 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 20
%37 = bitcast i8* %35 to <4 x i8>*
%38 = load <4 x i8>, <4 x i8>* %37
%39 = zext <4 x i8> %38 to <4 x i32>
%40 = bitcast i32* %36 to <4 x i32>*
store <4 x i32> %39, <4 x i32>* %40
%41 = getelementptr inbounds i8, i8* %2, i64 24
%42 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 24
%43 = bitcast i8* %41 to <4 x i8>*
%44 = load <4 x i8>, <4 x i8>* %43
%45 = zext <4 x i8> %44 to <4 x i32>
%46 = bitcast i32* %42 to <4 x i32>*
store <4 x i32> %45, <4 x i32>* %46
%47 = getelementptr inbounds i8, i8* %2, i64 28
%48 = load i8, i8* %47
%49 = zext i8 %48 to i32
%50 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 28
store i32 %49, i32* %50
%51 = getelementptr inbounds i8, i8* %2, i64 29
%52 = load i8, i8* %51
%53 = zext i8 %52 to i32
%54 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 29
store i32 %53, i32* %54
%55 = getelementptr inbounds i8, i8* %2, i64 30
%56 = load i8, i8* %55
%57 = zext i8 %56 to i32
%58 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 30
store i32 %57, i32* %58
%59 = getelementptr inbounds i8, i8* %2, i64 31
%60 = load i8, i8* %59
%61 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 31
%62 = and i8 %60, 127
%63 = zext i8 %62 to i32
store i32 %63, i32* %61
%64 = call i32 @mainloop(i32* %6, i8* %1)
%65 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 32
%66 = call i32 @recip(i32* %65, i32* %65)
%67 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 64
%68 = call i32 @mult(i32* %67, i32* %6, i32* %65)
%69 = call i32 @freeze(i32* %67)
%70 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 64
%71 = bitcast i32* %70 to <4 x i32>*
%72 = load <4 x i32>, <4 x i32>* %71
%73 = trunc <4 x i32> %72 to <4 x i8>
%74 = bitcast i8* %0 to <4 x i8>*
store <4 x i8> %73, <4 x i8>* %74
%75 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 68
%76 = bitcast i32* %75 to <4 x i32>*
%77 = load <4 x i32>, <4 x i32>* %76
%78 = trunc <4 x i32> %77 to <4 x i8>
%79 = getelementptr inbounds i8, i8* %0, i64 4
%80 = bitcast i8* %79 to <4 x i8>*
store <4 x i8> %78, <4 x i8>* %80
%81 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 72
%82 = bitcast i32* %81 to <4 x i32>*
%83 = load <4 x i32>, <4 x i32>* %82
%84 = trunc <4 x i32> %83 to <4 x i8>
%85 = getelementptr inbounds i8, i8* %0, i64 8
%86 = bitcast i8* %85 to <4 x i8>*
store <4 x i8> %84, <4 x i8>* %86
%87 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 76
%88 = bitcast i32* %87 to <4 x i32>*
%89 = load <4 x i32>, <4 x i32>* %88
%90 = trunc <4 x i32> %89 to <4 x i8>
%91 = getelementptr inbounds i8, i8* %0, i64 12
%92 = bitcast i8* %91 to <4 x i8>*
store <4 x i8> %90, <4 x i8>* %92
%93 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 80
%94 = bitcast i32* %93 to <4 x i32>*
%95 = load <4 x i32>, <4 x i32>* %94
%96 = trunc <4 x i32> %95 to <4 x i8>
%97 = getelementptr inbounds i8, i8* %0, i64 16
%98 = bitcast i8* %97 to <4 x i8>*
store <4 x i8> %96, <4 x i8>* %98
%99 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 84
%100 = bitcast i32* %99 to <4 x i32>*
%101 = load <4 x i32>, <4 x i32>* %100
%102 = trunc <4 x i32> %101 to <4 x i8>
%103 = getelementptr inbounds i8, i8* %0, i64 20
%104 = bitcast i8* %103 to <4 x i8>*
store <4 x i8> %102, <4 x i8>* %104
%105 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 88
%106 = bitcast i32* %105 to <4 x i32>*
%107 = load <4 x i32>, <4 x i32>* %106
%108 = trunc <4 x i32> %107 to <4 x i8>
%109 = getelementptr inbounds i8, i8* %0, i64 24
%110 = bitcast i8* %109 to <4 x i8>*
store <4 x i8> %108, <4 x i8>* %110
%111 = getelementptr inbounds [96 x i32], [96 x i32]* %4, i64 0, i64 92
%112 = bitcast i32* %111 to <4 x i32>*
%113 = load <4 x i32>, <4 x i32>* %112
%114 = trunc <4 x i32> %113 to <4 x i8>
%115 = getelementptr inbounds i8, i8* %0, i64 28
%116 = bitcast i8* %115 to <4 x i8>*
store <4 x i8> %114, <4 x i8>* %116
ret i32 0
}