blob: 02a7aef83fbf5916d000e6a6f6590395d038c448 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* linux/arch/unicore32/lib/copy_template.S
*
* Code specific to PKUnity SoC and UniCore ISA
*
* Copyright (C) 2001-2010 GUAN Xue-tao
*/
/*
* Theory of operation
* -------------------
*
* This file provides the core code for a forward memory copy used in
* the implementation of memcopy(), copy_to_user() and copy_from_user().
*
* The including file must define the following accessor macros
* according to the need of the given function:
*
* ldr1w ptr reg abort
*
* This loads one word from 'ptr', stores it in 'reg' and increments
* 'ptr' to the next word. The 'abort' argument is used for fixup tables.
*
* ldr4w ptr reg1 reg2 reg3 reg4 abort
* ldr8w ptr, reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
*
* This loads four or eight words starting from 'ptr', stores them
* in provided registers and increments 'ptr' past those words.
* The'abort' argument is used for fixup tables.
*
* ldr1b ptr reg cond abort
*
* Similar to ldr1w, but it loads a byte and increments 'ptr' one byte.
* It also must apply the condition code if provided, otherwise the
* "al" condition is assumed by default.
*
* str1w ptr reg abort
* str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
* str1b ptr reg cond abort
*
* Same as their ldr* counterparts, but data is stored to 'ptr' location
* rather than being loaded.
*
* enter
*
* Preserve the provided registers on the stack plus any additional
* data as needed by the implementation including this code. Called
* upon code entry.
*
* exit
*
* Restore registers with the values previously saved with the
* 'preserv' macro. Called upon code termination.
*/
enter
sub.a r2, r2, #4
bsl 8f
and.a ip, r0, #3
bne 9f
and.a ip, r1, #3
bne 10f
1: sub.a r2, r2, #(28)
stm.w (r5 - r8), [sp-]
bsl 5f
3:
4: ldr8w r1, r3, r4, r5, r6, r7, r8, r10, r11, abort=20f
sub.a r2, r2, #32
str8w r0, r3, r4, r5, r6, r7, r8, r10, r11, abort=20f
beg 3b
5: and.a ip, r2, #28
rsub ip, ip, #32
beq 7f
add pc, pc, ip @ C is always clear here
nop
ldr1w r1, r3, abort=20f
ldr1w r1, r4, abort=20f
ldr1w r1, r5, abort=20f
ldr1w r1, r6, abort=20f
ldr1w r1, r7, abort=20f
ldr1w r1, r8, abort=20f
ldr1w r1, r11, abort=20f
add pc, pc, ip
nop
str1w r0, r3, abort=20f
str1w r0, r4, abort=20f
str1w r0, r5, abort=20f
str1w r0, r6, abort=20f
str1w r0, r7, abort=20f
str1w r0, r8, abort=20f
str1w r0, r11, abort=20f
7: ldm.w (r5 - r8), [sp]+
8: mov.a r2, r2 << #31
ldr1b r1, r3, ne, abort=21f
ldr1b r1, r4, ea, abort=21f
ldr1b r1, r10, ea, abort=21f
str1b r0, r3, ne, abort=21f
str1b r0, r4, ea, abort=21f
str1b r0, r10, ea, abort=21f
exit
9: rsub ip, ip, #4
csub.a ip, #2
ldr1b r1, r3, sg, abort=21f
ldr1b r1, r4, eg, abort=21f
ldr1b r1, r11, abort=21f
str1b r0, r3, sg, abort=21f
str1b r0, r4, eg, abort=21f
sub.a r2, r2, ip
str1b r0, r11, abort=21f
bsl 8b
and.a ip, r1, #3
beq 1b
10: andn r1, r1, #3
csub.a ip, #2
ldr1w r1, r11, abort=21f
beq 17f
bsg 18f
.macro forward_copy_shift a b
sub.a r2, r2, #28
bsl 14f
11: stm.w (r5 - r9), [sp-]
12:
ldr4w r1, r4, r5, r6, r7, abort=19f
mov r3, r11 pull #\a
sub.a r2, r2, #32
ldr4w r1, r8, r9, r10, r11, abort=19f
or r3, r3, r4 push #\b
mov r4, r4 pull #\a
or r4, r4, r5 push #\b
mov r5, r5 pull #\a
or r5, r5, r6 push #\b
mov r6, r6 pull #\a
or r6, r6, r7 push #\b
mov r7, r7 pull #\a
or r7, r7, r8 push #\b
mov r8, r8 pull #\a
or r8, r8, r9 push #\b
mov r9, r9 pull #\a
or r9, r9, r10 push #\b
mov r10, r10 pull #\a
or r10, r10, r11 push #\b
str8w r0, r3, r4, r5, r6, r7, r8, r9, r10, , abort=19f
beg 12b
ldm.w (r5 - r9), [sp]+
14: and.a ip, r2, #28
beq 16f
15: mov r3, r11 pull #\a
ldr1w r1, r11, abort=21f
sub.a ip, ip, #4
or r3, r3, r11 push #\b
str1w r0, r3, abort=21f
bsg 15b
16: sub r1, r1, #(\b / 8)
b 8b
.endm
forward_copy_shift a=8 b=24
17: forward_copy_shift a=16 b=16
18: forward_copy_shift a=24 b=8
/*
* Abort preamble and completion macros.
* If a fixup handler is required then those macros must surround it.
* It is assumed that the fixup code will handle the private part of
* the exit macro.
*/
.macro copy_abort_preamble
19: ldm.w (r5 - r9), [sp]+
b 21f
299: .word 0 @ store lr
@ to avoid function call in fixup
20: ldm.w (r5 - r8), [sp]+
21:
adr r1, 299b
stw lr, [r1]
.endm
.macro copy_abort_end
adr lr, 299b
ldw pc, [lr]
.endm