summaryrefslogblamecommitdiffstats
path: root/arch/blackfin/kernel/fixed_code.S
blob: d8b1ebc7099684d1dd46fea05cf4d94186fcd7df (plain) (tree)
1
2
3
4
5
6
7
8
9
10









                                                                       
                         
                      























































































































                                                                              
/*
 * This file contains sequences of code that will be copied to a
 * fixed location, defined in <asm/atomic_seq.h>.  The interrupt
 * handlers ensure that these sequences appear to be atomic when
 * executed from userspace.
 * These are aligned to 16 bytes, so that we have some space to replace
 * these sequences with something else (e.g. kernel traps if we ever do
 * BF561 SMP).
 */
#include <linux/linkage.h>
#include <linux/unistd.h>
#include <asm/entry.h>

.text
ENTRY(_fixed_code_start)

.align 16
ENTRY(_sigreturn_stub)
	P0 = __NR_rt_sigreturn;
	EXCPT 0;
	/* Speculative execution paranoia.  */
0:	JUMP.S 0b;
ENDPROC (_sigreturn_stub)

.align 16
	/*
	 * Atomic swap, 8 bit.
	 * Inputs:	P0: memory address to use
	 *		R1: value to store
	 * Output:	R0: old contents of the memory address, zero extended.
	 */
ENTRY(_atomic_xchg32)
	R0 = [P0];
	[P0] = R1;
	rts;
ENDPROC (_atomic_xchg32)

.align 16
	/*
	 * Compare and swap, 32 bit.
	 * Inputs:	P0: memory address to use
	 *		R1: compare value
	 *		R2: new value to store
	 * The new value is stored if the contents of the memory
	 * address is equal to the compare value.
	 * Output:	R0: old contents of the memory address.
	 */
ENTRY(_atomic_cas32)
	R0 = [P0];
	CC = R0 == R1;
	IF !CC JUMP 1f;
	[P0] = R2;
1:
	rts;
ENDPROC (_atomic_cas32)

.align 16
	/*
	 * Atomic add, 32 bit.
	 * Inputs:	P0: memory address to use
	 *		R0: value to add
	 * Outputs:	R0: new contents of the memory address.
	 *		R1: previous contents of the memory address.
	 */
ENTRY(_atomic_add32)
	R1 = [P0];
	R0 = R1 + R0;
	[P0] = R0;
	rts;
ENDPROC (_atomic_add32)

.align 16
	/*
	 * Atomic sub, 32 bit.
	 * Inputs:	P0: memory address to use
	 *		R0: value to subtract
	 * Outputs:	R0: new contents of the memory address.
	 *		R1: previous contents of the memory address.
	 */
ENTRY(_atomic_sub32)
	R1 = [P0];
	R0 = R1 - R0;
	[P0] = R0;
	rts;
ENDPROC (_atomic_sub32)

.align 16
	/*
	 * Atomic ior, 32 bit.
	 * Inputs:	P0: memory address to use
	 *		R0: value to ior
	 * Outputs:	R0: new contents of the memory address.
	 *		R1: previous contents of the memory address.
	 */
ENTRY(_atomic_ior32)
	R1 = [P0];
	R0 = R1 | R0;
	[P0] = R0;
	rts;
ENDPROC (_atomic_ior32)

.align 16
	/*
	 * Atomic ior, 32 bit.
	 * Inputs:	P0: memory address to use
	 *		R0: value to ior
	 * Outputs:	R0: new contents of the memory address.
	 *		R1: previous contents of the memory address.
	 */
ENTRY(_atomic_and32)
	R1 = [P0];
	R0 = R1 & R0;
	[P0] = R0;
	rts;
ENDPROC (_atomic_ior32)

.align 16
	/*
	 * Atomic ior, 32 bit.
	 * Inputs:	P0: memory address to use
	 *		R0: value to ior
	 * Outputs:	R0: new contents of the memory address.
	 *		R1: previous contents of the memory address.
	 */
ENTRY(_atomic_xor32)
	R1 = [P0];
	R0 = R1 ^ R0;
	[P0] = R0;
	rts;
ENDPROC (_atomic_ior32)

ENTRY(_fixed_code_end)