 8c0b8139c8
			
		
	
	
	8c0b8139c8
	
	
	
		
			
			The LL/SC and IRQ versions were using generic stubs while the GRB version was just reimplementing what it already had for the standard cmpxchg() code. As we have optimized cmpxchg() implementations that are decoupled from the atomic code, simply falling back on the generic wrapper does the right thing. With this in place the GRB case is unaffected while the LL/SC case gets to use its optimized cmpxchg(). Signed-off-by: Paul Mundt <lethal@linux-sh.org>
		
			
				
	
	
		
			123 lines
		
	
	
	
		
			3.5 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
	
		
			3.5 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| #ifndef __ASM_SH_ATOMIC_GRB_H
 | |
| #define __ASM_SH_ATOMIC_GRB_H
 | |
| 
 | |
| static inline void atomic_add(int i, atomic_t *v)
 | |
| {
 | |
| 	int tmp;
 | |
| 
 | |
| 	__asm__ __volatile__ (
 | |
| 		"   .align 2              \n\t"
 | |
| 		"   mova    1f,   r0      \n\t" /* r0 = end point */
 | |
| 		"   mov    r15,   r1      \n\t" /* r1 = saved sp */
 | |
| 		"   mov    #-6,   r15     \n\t" /* LOGIN: r15 = size */
 | |
| 		"   mov.l  @%1,   %0      \n\t" /* load  old value */
 | |
| 		"   add     %2,   %0      \n\t" /* add */
 | |
| 		"   mov.l   %0,   @%1     \n\t" /* store new value */
 | |
| 		"1: mov     r1,   r15     \n\t" /* LOGOUT */
 | |
| 		: "=&r" (tmp),
 | |
| 		  "+r"  (v)
 | |
| 		: "r"   (i)
 | |
| 		: "memory" , "r0", "r1");
 | |
| }
 | |
| 
 | |
| static inline void atomic_sub(int i, atomic_t *v)
 | |
| {
 | |
| 	int tmp;
 | |
| 
 | |
| 	__asm__ __volatile__ (
 | |
| 		"   .align 2              \n\t"
 | |
| 		"   mova    1f,   r0      \n\t" /* r0 = end point */
 | |
| 		"   mov     r15,  r1      \n\t" /* r1 = saved sp */
 | |
| 		"   mov    #-6,   r15     \n\t" /* LOGIN: r15 = size */
 | |
| 		"   mov.l  @%1,   %0      \n\t" /* load  old value */
 | |
| 		"   sub     %2,   %0      \n\t" /* sub */
 | |
| 		"   mov.l   %0,   @%1     \n\t" /* store new value */
 | |
| 		"1: mov     r1,   r15     \n\t" /* LOGOUT */
 | |
| 		: "=&r" (tmp),
 | |
| 		  "+r"  (v)
 | |
| 		: "r"   (i)
 | |
| 		: "memory" , "r0", "r1");
 | |
| }
 | |
| 
 | |
| static inline int atomic_add_return(int i, atomic_t *v)
 | |
| {
 | |
| 	int tmp;
 | |
| 
 | |
| 	__asm__ __volatile__ (
 | |
| 		"   .align 2              \n\t"
 | |
| 		"   mova    1f,   r0      \n\t" /* r0 = end point */
 | |
| 		"   mov    r15,   r1      \n\t" /* r1 = saved sp */
 | |
| 		"   mov    #-6,   r15     \n\t" /* LOGIN: r15 = size */
 | |
| 		"   mov.l  @%1,   %0      \n\t" /* load  old value */
 | |
| 		"   add     %2,   %0      \n\t" /* add */
 | |
| 		"   mov.l   %0,   @%1     \n\t" /* store new value */
 | |
| 		"1: mov     r1,   r15     \n\t" /* LOGOUT */
 | |
| 		: "=&r" (tmp),
 | |
| 		  "+r"  (v)
 | |
| 		: "r"   (i)
 | |
| 		: "memory" , "r0", "r1");
 | |
| 
 | |
| 	return tmp;
 | |
| }
 | |
| 
 | |
| static inline int atomic_sub_return(int i, atomic_t *v)
 | |
| {
 | |
| 	int tmp;
 | |
| 
 | |
| 	__asm__ __volatile__ (
 | |
| 		"   .align 2              \n\t"
 | |
| 		"   mova    1f,   r0      \n\t" /* r0 = end point */
 | |
| 		"   mov    r15,   r1      \n\t" /* r1 = saved sp */
 | |
| 		"   mov    #-6,   r15     \n\t" /* LOGIN: r15 = size */
 | |
| 		"   mov.l  @%1,   %0      \n\t" /* load  old value */
 | |
| 		"   sub     %2,   %0      \n\t" /* sub */
 | |
| 		"   mov.l   %0,   @%1     \n\t" /* store new value */
 | |
| 		"1: mov     r1,   r15     \n\t" /* LOGOUT */
 | |
| 		: "=&r" (tmp),
 | |
| 		  "+r"  (v)
 | |
| 		: "r"   (i)
 | |
| 		: "memory", "r0", "r1");
 | |
| 
 | |
| 	return tmp;
 | |
| }
 | |
| 
 | |
| static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
 | |
| {
 | |
| 	int tmp;
 | |
| 	unsigned int _mask = ~mask;
 | |
| 
 | |
| 	__asm__ __volatile__ (
 | |
| 		"   .align 2              \n\t"
 | |
| 		"   mova    1f,   r0      \n\t" /* r0 = end point */
 | |
| 		"   mov    r15,   r1      \n\t" /* r1 = saved sp */
 | |
| 		"   mov    #-6,   r15     \n\t" /* LOGIN: r15 = size */
 | |
| 		"   mov.l  @%1,   %0      \n\t" /* load  old value */
 | |
| 		"   and     %2,   %0      \n\t" /* add */
 | |
| 		"   mov.l   %0,   @%1     \n\t" /* store new value */
 | |
| 		"1: mov     r1,   r15     \n\t" /* LOGOUT */
 | |
| 		: "=&r" (tmp),
 | |
| 		  "+r"  (v)
 | |
| 		: "r"   (_mask)
 | |
| 		: "memory" , "r0", "r1");
 | |
| }
 | |
| 
 | |
| static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
 | |
| {
 | |
| 	int tmp;
 | |
| 
 | |
| 	__asm__ __volatile__ (
 | |
| 		"   .align 2              \n\t"
 | |
| 		"   mova    1f,   r0      \n\t" /* r0 = end point */
 | |
| 		"   mov    r15,   r1      \n\t" /* r1 = saved sp */
 | |
| 		"   mov    #-6,   r15     \n\t" /* LOGIN: r15 = size */
 | |
| 		"   mov.l  @%1,   %0      \n\t" /* load  old value */
 | |
| 		"   or      %2,   %0      \n\t" /* or */
 | |
| 		"   mov.l   %0,   @%1     \n\t" /* store new value */
 | |
| 		"1: mov     r1,   r15     \n\t" /* LOGOUT */
 | |
| 		: "=&r" (tmp),
 | |
| 		  "+r"  (v)
 | |
| 		: "r"   (mask)
 | |
| 		: "memory" , "r0", "r1");
 | |
| }
 | |
| 
 | |
| #endif /* __ASM_SH_ATOMIC_GRB_H */
 |