Linux 6.7-rc7
[linux-modified.git] / arch / loongarch / lib / unaligned.S
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/regdef.h>
13
14 .L_fixup_handle_unaligned:
15         li.w    a0, -EFAULT
16         jr      ra
17
18 /*
19  * unsigned long unaligned_read(void *addr, void *value, unsigned long n, bool sign)
20  *
21  * a0: addr
22  * a1: value
23  * a2: n
24  * a3: sign
25  */
26 SYM_FUNC_START(unaligned_read)
27         beqz    a2, 5f
28
29         li.w    t2, 0
30         addi.d  t0, a2, -1
31         slli.d  t1, t0, 3
32         add.d   a0, a0, t0
33
34         beqz    a3, 2f
35 1:      ld.b    t3, a0, 0
36         b       3f
37
38 2:      ld.bu   t3, a0, 0
39 3:      sll.d   t3, t3, t1
40         or      t2, t2, t3
41         addi.d  t1, t1, -8
42         addi.d  a0, a0, -1
43         addi.d  a2, a2, -1
44         bgtz    a2, 2b
45 4:      st.d    t2, a1, 0
46
47         move    a0, a2
48         jr      ra
49
50 5:      li.w    a0, -EFAULT
51         jr      ra
52
53         _asm_extable 1b, .L_fixup_handle_unaligned
54         _asm_extable 2b, .L_fixup_handle_unaligned
55         _asm_extable 4b, .L_fixup_handle_unaligned
56 SYM_FUNC_END(unaligned_read)
57
58 /*
59  * unsigned long unaligned_write(void *addr, unsigned long value, unsigned long n)
60  *
61  * a0: addr
62  * a1: value
63  * a2: n
64  */
65 SYM_FUNC_START(unaligned_write)
66         beqz    a2, 3f
67
68         li.w    t0, 0
69 1:      srl.d   t1, a1, t0
70 2:      st.b    t1, a0, 0
71         addi.d  t0, t0, 8
72         addi.d  a2, a2, -1
73         addi.d  a0, a0, 1
74         bgtz    a2, 1b
75
76         move    a0, a2
77         jr      ra
78
79 3:      li.w    a0, -EFAULT
80         jr      ra
81
82         _asm_extable 2b, .L_fixup_handle_unaligned
83 SYM_FUNC_END(unaligned_write)