#include "crypto_asm_hidden.h"
// linker define fe25519_mul
// linker use mask63

/* Assembly for field multiplication. */

#define mask63 CRYPTO_SHARED_NAMESPACE(mask63)

	.p2align 5
	ASM_HIDDEN _CRYPTO_SHARED_NAMESPACE(fe25519_mul)
	.globl _CRYPTO_SHARED_NAMESPACE(fe25519_mul)
	ASM_HIDDEN CRYPTO_SHARED_NAMESPACE(fe25519_mul)
	.globl CRYPTO_SHARED_NAMESPACE(fe25519_mul)

_CRYPTO_SHARED_NAMESPACE(fe25519_mul):
CRYPTO_SHARED_NAMESPACE(fe25519_mul):

	movq    %rsp,%r11
	andq 	$-32,%rsp
	subq    $56,%rsp

	movq    %r11,0(%rsp)
	movq    %r12,8(%rsp)
	movq    %r13,16(%rsp)
	movq    %r14,24(%rsp)
	movq    %r15,32(%rsp)
	movq    %rbx,40(%rsp)
	movq    %rbp,48(%rsp)

	movq    %rdx,%rbx
	    
	xorq    %r13,%r13
	movq    0(%rbx),%rdx    

	mulx    0(%rsi),%r8,%r9
	mulx    8(%rsi),%rcx,%r10
	adcx    %rcx,%r9     

	mulx    16(%rsi),%rcx,%r11
	adcx    %rcx,%r10    

	mulx    24(%rsi),%rcx,%r12
	adcx    %rcx,%r11
	adcx    %r13,%r12

	xorq    %r14,%r14
	movq    8(%rbx),%rdx
	   
	mulx    0(%rsi),%rcx,%rbp
	adcx    %rcx,%r9
	adox    %rbp,%r10
	    
	mulx    8(%rsi),%rcx,%rbp
	adcx    %rcx,%r10
	adox    %rbp,%r11
	    
	mulx    16(%rsi),%rcx,%rbp
	adcx    %rcx,%r11
	adox    %rbp,%r12
	    
	mulx    24(%rsi),%rcx,%rbp
	adcx    %rcx,%r12
	adox    %rbp,%r13
	adcx    %r14,%r13

	xorq    %r15,%r15

	movq    16(%rbx),%rdx
	    
	mulx    0(%rsi),%rcx,%rbp
	adcx    %rcx,%r10
	adox    %rbp,%r11
	    
	mulx    8(%rsi),%rcx,%rbp
	adcx    %rcx,%r11
	adox    %rbp,%r12
	    
	mulx    16(%rsi),%rcx,%rbp
	adcx    %rcx,%r12
	adox    %rbp,%r13
	    
	mulx    24(%rsi),%rcx,%rbp
	adcx    %rcx,%r13
	adox    %rbp,%r14
	adcx    %r15,%r14

	xorq    %rax,%rax

	movq    24(%rbx),%rdx
	    
	mulx    0(%rsi),%rcx,%rbp
	adcx    %rcx,%r11
	adox    %rbp,%r12
	    
	mulx    8(%rsi),%rcx,%rbp
	adcx    %rcx,%r12
	adox    %rbp,%r13
	    
	mulx    16(%rsi),%rcx,%rbp
	adcx    %rcx,%r13
	adox    %rbp,%r14
	    
	mulx    24(%rsi),%rcx,%rbp
	adcx    %rcx,%r14
	adox    %rbp,%r15			
	adcx    %rax,%r15

	xorq    %rbp,%rbp
	movq    $38,%rdx

	mulx    %r12,%rax,%r12 
	adcx    %rax,%r8
	adox    %r12,%r9

	mulx    %r13,%rcx,%r13
	adcx    %rcx,%r9
	adox    %r13,%r10

	mulx    %r14,%rcx,%r14
	adcx    %rcx,%r10
	adox    %r14,%r11

	mulx    %r15,%rcx,%r15
	adcx    %rcx,%r11
	adox    %rbp,%r15
	adcx    %rbp,%r15

	shld    $1,%r11,%r15
	andq	mask63(%rip),%r11

	imul    $19,%r15,%r15
	addq    %r15,%r8
	adcq    $0,%r9
	adcq    $0,%r10
	adcq    $0,%r11

	movq    %r8,0(%rdi)
	movq    %r9,8(%rdi)
	movq    %r10,16(%rdi)
	movq    %r11,24(%rdi)

	movq    0(%rsp),%r11
	movq    8(%rsp),%r12
	movq    16(%rsp),%r13
	movq    24(%rsp),%r14
	movq    32(%rsp),%r15
	movq    40(%rsp),%rbx
	movq    48(%rsp),%rbp

	movq    %r11,%rsp

	ret
.section	.note.GNU-stack,"",@progbits
