1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4 */
5
6#include <asm/alternative-asm.h>
7#include <asm/asm.h>
8#include <asm/asmmacro.h>
9#include <asm/cpu.h>
10#include <asm/export.h>
11#include <asm/regdef.h>
12
13.macro fill_to_64 r0
14	bstrins.d \r0, \r0, 15, 8
15	bstrins.d \r0, \r0, 31, 16
16	bstrins.d \r0, \r0, 63, 32
17.endm
18
19SYM_FUNC_START(memset)
20	/*
21	 * Some CPUs support hardware unaligned access
22	 */
23	ALTERNATIVE	"b __memset_generic", \
24			"b __memset_fast", CPU_FEATURE_UAL
25SYM_FUNC_END(memset)
26_ASM_NOKPROBE(memset)
27
28EXPORT_SYMBOL(memset)
29
30/*
31 * void *__memset_generic(void *s, int c, size_t n)
32 *
33 * a0: s
34 * a1: c
35 * a2: n
36 */
37SYM_FUNC_START(__memset_generic)
38	move	a3, a0
39	beqz	a2, 2f
40
411:	st.b	a1, a0, 0
42	addi.d	a0, a0, 1
43	addi.d	a2, a2, -1
44	bgt	a2, zero, 1b
45
462:	move	a0, a3
47	jr	ra
48SYM_FUNC_END(__memset_generic)
49_ASM_NOKPROBE(__memset_generic)
50
51/*
52 * void *__memset_fast(void *s, int c, size_t n)
53 *
54 * a0: s
55 * a1: c
56 * a2: n
57 */
58SYM_FUNC_START(__memset_fast)
59	move	a3, a0
60	beqz	a2, 3f
61
62	ori	a4, zero, 64
63	blt	a2, a4, 2f
64
65	/* fill a1 to 64 bits */
66	fill_to_64 a1
67
68	/* set 64 bytes at a time */
691:	st.d	a1, a0, 0
70	st.d	a1, a0, 8
71	st.d	a1, a0, 16
72	st.d	a1, a0, 24
73	st.d	a1, a0, 32
74	st.d	a1, a0, 40
75	st.d	a1, a0, 48
76	st.d	a1, a0, 56
77
78	addi.d	a0, a0, 64
79	addi.d	a2, a2, -64
80	bge	a2, a4, 1b
81
82	beqz	a2, 3f
83
84	/* set the remaining bytes */
852:	st.b	a1, a0, 0
86	addi.d	a0, a0, 1
87	addi.d	a2, a2, -1
88	bgt	a2, zero, 2b
89
90	/* return */
913:	move	a0, a3
92	jr	ra
93SYM_FUNC_END(__memset_fast)
94_ASM_NOKPROBE(__memset_fast)
95