1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
4  */
5 
6 #include <linux/linkage.h>
7 
8 #include <asm/asm.h>
9 #include <asm/asmmacro.h>
10 #include <asm/asm-extable.h>
11 #include <asm/errno.h>
12 #include <asm/export.h>
13 #include <asm/regdef.h>
14 
15 .L_fixup_handle_unaligned:
16 	li.w	a0, -EFAULT
17 	jr	ra
18 
19 /*
20  * unsigned long unaligned_read(void *addr, void *value, unsigned long n, bool sign)
21  *
22  * a0: addr
23  * a1: value
24  * a2: n
25  * a3: sign
26  */
27 SYM_FUNC_START(unaligned_read)
28 	beqz	a2, 5f
29 
30 	li.w	t2, 0
31 	addi.d	t0, a2, -1
32 	slli.d	t1, t0, 3
33 	add.d 	a0, a0, t0
34 
35 	beqz	a3, 2f
36 1:	ld.b	t3, a0, 0
37 	b	3f
38 
39 2:	ld.bu	t3, a0, 0
40 3:	sll.d	t3, t3, t1
41 	or	t2, t2, t3
42 	addi.d	t1, t1, -8
43 	addi.d	a0, a0, -1
44 	addi.d	a2, a2, -1
45 	bgtz	a2, 2b
46 4:	st.d	t2, a1, 0
47 
48 	move	a0, a2
49 	jr	ra
50 
51 5:	li.w    a0, -EFAULT
52 	jr	ra
53 
54 	_asm_extable 1b, .L_fixup_handle_unaligned
55 	_asm_extable 2b, .L_fixup_handle_unaligned
56 	_asm_extable 4b, .L_fixup_handle_unaligned
57 SYM_FUNC_END(unaligned_read)
58 
59 /*
60  * unsigned long unaligned_write(void *addr, unsigned long value, unsigned long n)
61  *
62  * a0: addr
63  * a1: value
64  * a2: n
65  */
66 SYM_FUNC_START(unaligned_write)
67 	beqz	a2, 3f
68 
69 	li.w	t0, 0
70 1:	srl.d	t1, a1, t0
71 2:	st.b	t1, a0, 0
72 	addi.d	t0, t0, 8
73 	addi.d	a2, a2, -1
74 	addi.d	a0, a0, 1
75 	bgtz	a2, 1b
76 
77 	move	a0, a2
78 	jr	ra
79 
80 3:	li.w    a0, -EFAULT
81 	jr	ra
82 
83 	_asm_extable 2b, .L_fixup_handle_unaligned
84 SYM_FUNC_END(unaligned_write)
85