#include "arm_arch.h"

.text


.align	5
.globl	__armv7_neon_probe

__armv7_neon_probe:
	AARCH64_VALID_CALL_TARGET
	orr	v15.16b, v15.16b, v15.16b
	ret


.globl	__armv7_tick

__armv7_tick:
	AARCH64_VALID_CALL_TARGET
#ifdef	__APPLE__
	mrs	x0, CNTPCT_EL0
#else
	mrs	x0, CNTVCT_EL0
#endif
	ret


.globl	__armv8_aes_probe

__armv8_aes_probe:
	AARCH64_VALID_CALL_TARGET
	aese	v0.16b, v0.16b
	ret


.globl	__armv8_sha1_probe

__armv8_sha1_probe:
	AARCH64_VALID_CALL_TARGET
	sha1h	s0, s0
	ret


.globl	__armv8_sha256_probe

__armv8_sha256_probe:
	AARCH64_VALID_CALL_TARGET
	sha256su0	v0.4s, v0.4s
	ret


.globl	__armv8_pmull_probe

__armv8_pmull_probe:
	AARCH64_VALID_CALL_TARGET
	pmull	v0.1q, v0.1d, v0.1d
	ret


.globl	__armv8_sm4_probe

__armv8_sm4_probe:
	AARCH64_VALID_CALL_TARGET
.long	0xcec08400	// sm4e	v0.4s, v0.4s
	ret


.globl	__armv8_sha512_probe

__armv8_sha512_probe:
	AARCH64_VALID_CALL_TARGET
.long	0xcec08000	// sha512su0	v0.2d,v0.2d
	ret


.globl	__armv8_eor3_probe

__armv8_eor3_probe:
	AARCH64_VALID_CALL_TARGET
.long	0xce010800	// eor3	v0.16b, v0.16b, v1.16b, v2.16b
	ret


.globl	__armv8_sve_probe

__armv8_sve_probe:
	AARCH64_VALID_CALL_TARGET
.long	0x04a03000	// eor z0.d,z0.d,z0.d
	ret


.globl	__armv8_sve2_probe

__armv8_sve2_probe:
	AARCH64_VALID_CALL_TARGET
.long	0x04e03400	// xar z0.d,z0.d,z0.d
	ret


.globl	__armv8_cpuid_probe

__armv8_cpuid_probe:
	AARCH64_VALID_CALL_TARGET
	mrs	x0, midr_el1
	ret


.globl	__armv8_sm3_probe

__armv8_sm3_probe:
	AARCH64_VALID_CALL_TARGET
.long	0xce63c004	// sm3partw1 v4.4s, v0.4s, v3.4s
	ret


.globl	_OPENSSL_cleanse

.align	5
_OPENSSL_cleanse:
	AARCH64_VALID_CALL_TARGET
	cbz	x1,Lret	// len==0?
	cmp	x1,#15
	b.hi	Lot		// len>15
	nop
Little:
	strb	wzr,[x0],#1	// store byte-by-byte
	subs	x1,x1,#1
	b.ne	Little
Lret:	ret

.align	4
Lot:	tst	x0,#7
	b.eq	Laligned	// inp is aligned
	strb	wzr,[x0],#1	// store byte-by-byte
	sub	x1,x1,#1
	b	Lot

.align	4
Laligned:
	str	xzr,[x0],#8	// store word-by-word
	sub	x1,x1,#8
	tst	x1,#-8
	b.ne	Laligned	// len>=8
	cbnz	x1,Little	// len!=0?
	ret


.globl	_CRYPTO_memcmp

.align	4
_CRYPTO_memcmp:
	AARCH64_VALID_CALL_TARGET
	eor	w3,w3,w3
	cbz	x2,Lno_data	// len==0?
	cmp	x2,#16
	b.ne	Loop_cmp
	ldp	x8,x9,[x0]
	ldp	x10,x11,[x1]
	eor	x8,x8,x10
	eor	x9,x9,x11
	orr	x8,x8,x9
	mov	x0,#1
	cmp	x8,#0
	csel	x0,xzr,x0,eq
	ret

.align	4
Loop_cmp:
	ldrb	w4,[x0],#1
	ldrb	w5,[x1],#1
	eor	w4,w4,w5
	orr	w3,w3,w4
	subs	x2,x2,#1
	b.ne	Loop_cmp

Lno_data:
	neg	w0,w3
	lsr	w0,w0,#31
	ret


.globl	__armv8_rng_probe

__armv8_rng_probe:
	AARCH64_VALID_CALL_TARGET
	mrs	x0, s3_3_c2_c4_0	// rndr
	mrs	x0, s3_3_c2_c4_1	// rndrrs
	ret

// Fill buffer with Randomly Generated Bytes
// inputs:  char * in x0 - Pointer to buffer
//          size_t in x1 - Number of bytes to write to buffer
// outputs: size_t in x0 - Number of bytes successfully written to buffer
.globl	_OPENSSL_rndr_asm

.align	4
_OPENSSL_rndr_asm:
	AARCH64_VALID_CALL_TARGET
	mov	x2,xzr
	mov	x3,xzr

.align	4
Loop_rndr:
	cmp	x1,#0
	b.eq	.rndr_done
	mov	x3,xzr
	mrs	x3,s3_3_c2_c4_0
	b.eq	.rndr_done

	cmp	x1,#8
	b.lt	Loop_single_byte_rndr

	str	x3,[x0]
	add	x0,x0,#8
	add	x2,x2,#8
	subs	x1,x1,#8
	b.ge	Loop_rndr

.align	4
Loop_single_byte_rndr:
	strb	w3,[x0]
	lsr	x3,x3,#8
	add	x2,x2,#1
	add	x0,x0,#1
	subs	x1,x1,#1
	b.gt	Loop_single_byte_rndr

.align	4
.rndr_done:
	mov	x0,x2
	ret

// Fill buffer with Randomly Generated Bytes
// inputs:  char * in x0 - Pointer to buffer
//          size_t in x1 - Number of bytes to write to buffer
// outputs: size_t in x0 - Number of bytes successfully written to buffer
.globl	_OPENSSL_rndrrs_asm

.align	4
_OPENSSL_rndrrs_asm:
	AARCH64_VALID_CALL_TARGET
	mov	x2,xzr
	mov	x3,xzr

.align	4
Loop_rndrrs:
	cmp	x1,#0
	b.eq	.rndrrs_done
	mov	x3,xzr
	mrs	x3,s3_3_c2_c4_1
	b.eq	.rndrrs_done

	cmp	x1,#8
	b.lt	Loop_single_byte_rndrrs

	str	x3,[x0]
	add	x0,x0,#8
	add	x2,x2,#8
	subs	x1,x1,#8
	b.ge	Loop_rndrrs

.align	4
Loop_single_byte_rndrrs:
	strb	w3,[x0]
	lsr	x3,x3,#8
	add	x2,x2,#1
	add	x0,x0,#1
	subs	x1,x1,#1
	b.gt	Loop_single_byte_rndrrs

.align	4
.rndrrs_done:
	mov	x0,x2
	ret

