215 lines
		
	
	
	
		
			4.6 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
		
		
			
		
	
	
			215 lines
		
	
	
	
		
			4.6 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
|   | /* | ||
|  |  * linux/arch/unicore32/lib/copy_template.S | ||
|  |  * | ||
|  |  * Code specific to PKUnity SoC and UniCore ISA | ||
|  |  * | ||
|  |  * Copyright (C) 2001-2010 GUAN Xue-tao | ||
|  |  * | ||
|  |  * This program is free software; you can redistribute it and/or modify
 | ||
|  |  * it under the terms of the GNU General Public License version 2 as | ||
|  |  * published by the Free Software Foundation. | ||
|  |  */ | ||
|  | 
 | ||
|  | /* | ||
|  |  * 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 | ||
|  | 
 |