162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/* Copyright (C) 2023 Rivos Inc. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/linkage.h>
562306a36Sopenharmony_ci#include <asm/asm.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci	.text
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci/* void __riscv_copy_words_unaligned(void *, const void *, size_t) */
1062306a36Sopenharmony_ci/* Performs a memcpy without aligning buffers, using word loads and stores. */
1162306a36Sopenharmony_ci/* Note: The size is truncated to a multiple of 8 * SZREG */
1262306a36Sopenharmony_ciENTRY(__riscv_copy_words_unaligned)
1362306a36Sopenharmony_ci	andi  a4, a2, ~((8*SZREG)-1)
1462306a36Sopenharmony_ci	beqz  a4, 2f
1562306a36Sopenharmony_ci	add   a3, a1, a4
1662306a36Sopenharmony_ci1:
1762306a36Sopenharmony_ci	REG_L a4,       0(a1)
1862306a36Sopenharmony_ci	REG_L a5,   SZREG(a1)
1962306a36Sopenharmony_ci	REG_L a6, 2*SZREG(a1)
2062306a36Sopenharmony_ci	REG_L a7, 3*SZREG(a1)
2162306a36Sopenharmony_ci	REG_L t0, 4*SZREG(a1)
2262306a36Sopenharmony_ci	REG_L t1, 5*SZREG(a1)
2362306a36Sopenharmony_ci	REG_L t2, 6*SZREG(a1)
2462306a36Sopenharmony_ci	REG_L t3, 7*SZREG(a1)
2562306a36Sopenharmony_ci	REG_S a4,       0(a0)
2662306a36Sopenharmony_ci	REG_S a5,   SZREG(a0)
2762306a36Sopenharmony_ci	REG_S a6, 2*SZREG(a0)
2862306a36Sopenharmony_ci	REG_S a7, 3*SZREG(a0)
2962306a36Sopenharmony_ci	REG_S t0, 4*SZREG(a0)
3062306a36Sopenharmony_ci	REG_S t1, 5*SZREG(a0)
3162306a36Sopenharmony_ci	REG_S t2, 6*SZREG(a0)
3262306a36Sopenharmony_ci	REG_S t3, 7*SZREG(a0)
3362306a36Sopenharmony_ci	addi  a0, a0, 8*SZREG
3462306a36Sopenharmony_ci	addi  a1, a1, 8*SZREG
3562306a36Sopenharmony_ci	bltu  a1, a3, 1b
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci2:
3862306a36Sopenharmony_ci	ret
3962306a36Sopenharmony_ciEND(__riscv_copy_words_unaligned)
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/* void __riscv_copy_bytes_unaligned(void *, const void *, size_t) */
4262306a36Sopenharmony_ci/* Performs a memcpy without aligning buffers, using only byte accesses. */
4362306a36Sopenharmony_ci/* Note: The size is truncated to a multiple of 8 */
4462306a36Sopenharmony_ciENTRY(__riscv_copy_bytes_unaligned)
4562306a36Sopenharmony_ci	andi a4, a2, ~(8-1)
4662306a36Sopenharmony_ci	beqz a4, 2f
4762306a36Sopenharmony_ci	add  a3, a1, a4
4862306a36Sopenharmony_ci1:
4962306a36Sopenharmony_ci	lb   a4, 0(a1)
5062306a36Sopenharmony_ci	lb   a5, 1(a1)
5162306a36Sopenharmony_ci	lb   a6, 2(a1)
5262306a36Sopenharmony_ci	lb   a7, 3(a1)
5362306a36Sopenharmony_ci	lb   t0, 4(a1)
5462306a36Sopenharmony_ci	lb   t1, 5(a1)
5562306a36Sopenharmony_ci	lb   t2, 6(a1)
5662306a36Sopenharmony_ci	lb   t3, 7(a1)
5762306a36Sopenharmony_ci	sb   a4, 0(a0)
5862306a36Sopenharmony_ci	sb   a5, 1(a0)
5962306a36Sopenharmony_ci	sb   a6, 2(a0)
6062306a36Sopenharmony_ci	sb   a7, 3(a0)
6162306a36Sopenharmony_ci	sb   t0, 4(a0)
6262306a36Sopenharmony_ci	sb   t1, 5(a0)
6362306a36Sopenharmony_ci	sb   t2, 6(a0)
6462306a36Sopenharmony_ci	sb   t3, 7(a0)
6562306a36Sopenharmony_ci	addi a0, a0, 8
6662306a36Sopenharmony_ci	addi a1, a1, 8
6762306a36Sopenharmony_ci	bltu a1, a3, 1b
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci2:
7062306a36Sopenharmony_ci	ret
7162306a36Sopenharmony_ciEND(__riscv_copy_bytes_unaligned)
72