OSDN Git Service

Assembly optimization
[uclinux-h8/linux.git] / arch / h8300 / include / asm / atomic.h
index 40901e3..6a62733 100644 (file)
 
 #include <linux/kernel.h>
 
-static __inline__ int atomic_add_return(int i, atomic_t *v)
+static inline int atomic_add_return(int i, atomic_t *v)
 {
-       unsigned long flags;
+       unsigned short ccr;
        int ret;
-       local_irq_save(flags);
-       ret = v->counter += i;
-       local_irq_restore(flags);
+
+       __asm__ __volatile__ (
+               "stc ccr,%w2\n\t"
+               "orc #0x80,ccr\n\t"
+               "mov.l %1,%0\n\t"
+               "add.l %3,%0\n\t"
+               "mov.l %0,%1\n\t"
+               "ldc %w2,ccr"
+               : "=r"(ret), "+m"(v->counter), "=r"(ccr)
+               : "ri"(i));
        return ret;
 }
 
 #define atomic_add(i, v) atomic_add_return(i, v)
 #define atomic_add_negative(a, v)      (atomic_add_return((a), (v)) < 0)
 
-static __inline__ int atomic_sub_return(int i, atomic_t *v)
+static inline int atomic_sub_return(int i, atomic_t *v)
 {
-       unsigned long flags;
+       unsigned short ccr;
        int ret;
-       local_irq_save(flags);
-       ret = v->counter -= i;
-       local_irq_restore(flags);
+
+       __asm__ __volatile__ (
+               "stc ccr,%w2\n\t"
+               "orc #0x80,ccr\n\t"
+               "mov.l %1,%0\n\t"
+               "sub.l %3,%0\n\t"
+               "mov.l %0,%1\n\t"
+               "ldc %w2,ccr"
+               : "=r"(ret), "+m"(v->counter), "=r"(ccr)
+               : "ri"(i));
        return ret;
 }
 
 #define atomic_sub(i, v) atomic_sub_return(i, v)
-#define atomic_sub_and_test(i,v) (atomic_sub_return(i, v) == 0)
+#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
 
-static __inline__ int atomic_inc_return(atomic_t *v)
+static inline int atomic_inc_return(atomic_t *v)
 {
-       unsigned long flags;
+       unsigned short ccr;
        int ret;
-       local_irq_save(flags);
-       v->counter++;
-       ret = v->counter;
-       local_irq_restore(flags);
+
+       __asm__ __volatile__ (
+               "stc ccr,%w2\n\t"
+               "orc #0x80,ccr\n\t"
+               "mov.l %1,%0\n\t"
+               "inc.l #1,%0\n\t"
+               "mov.l %0,%1\n\t"
+               "ldc %w2,ccr"
+               : "=r"(ret), "+m"(v->counter), "=r"(ccr));
        return ret;
 }
 
@@ -65,76 +84,107 @@ static __inline__ int atomic_inc_return(atomic_t *v)
  */
 #define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
 
-static __inline__ int atomic_dec_return(atomic_t *v)
+static inline int atomic_dec_return(atomic_t *v)
 {
-       unsigned long flags;
+       unsigned short ccr;
        int ret;
-       local_irq_save(flags);
-       --v->counter;
-       ret = v->counter;
-       local_irq_restore(flags);
+
+       __asm__ __volatile__ (
+               "stc ccr,%w2\n\t"
+               "orc #0x80,ccr\n\t"
+               "mov.l %1,%0\n\t"
+               "dec.l #1,%0\n\t"
+               "mov.l %0,%1\n\t"
+               "ldc %w2,ccr"
+               : "=r"(ret), "+m"(v->counter), "=r"(ccr));
        return ret;
 }
 
 #define atomic_dec(v) atomic_dec_return(v)
 
-static __inline__ int atomic_dec_and_test(atomic_t *v)
+static inline int atomic_dec_and_test(atomic_t *v)
 {
-       unsigned long flags;
+       unsigned short ccr;
        int ret;
-       local_irq_save(flags);
-       --v->counter;
-       ret = v->counter;
-       local_irq_restore(flags);
+
+       __asm__ __volatile__ (
+               "stc ccr,%w2\n\t"
+               "orc #0x80,ccr\n\t"
+               "mov.l %1,%0\n\t"
+               "dec.l #1,%0\n\t"
+               "mov.l %0,%1\n\t"
+               "ldc %w2,ccr"
+               : "=r"(ret), "+m"(v->counter), "=r"(ccr));
        return ret == 0;
 }
 
 static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
 {
        int ret;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       ret = v->counter;
-       if (likely(ret == old))
-               v->counter = new;
-       local_irq_restore(flags);
+       unsigned short ccr;
+
+       __asm__ __volatile__ (
+               "stc ccr,%w2\n\t"
+               "orc #0x80,ccr\n\t"
+               "mov.l %1,%0\n\t"
+               "cmp.l %3,%0\n\t"
+               "bne 1f\n\t"
+               "mov.l %4,%1\n"
+               "1:\tldc %w2,ccr"
+               : "=r"(ret), "+m"(v->counter), "=r"(ccr)
+               : "g"(old), "r"(new));
        return ret;
 }
 
 static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
        int ret;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       ret = v->counter;
-       if (ret != u)
-               v->counter += a;
-       local_irq_restore(flags);
+       unsigned char ccr;
+
+       __asm__ __volatile__ (
+               "stc ccr,%w2\n\t"
+               "orc #0x80,ccr\n\t"
+               "mov.l %1,%0\n\t"
+               "cmp.l %4,%0\n\t"
+               "beq 1f\n\t"
+               "add.l %0,%3\n\t"
+               "mov.l %3,%1\n"
+               "1:\tldc %w2,ccr"
+               : "=r"(ret), "+m"(v->counter), "=r"(ccr), "+r"(a)
+               : "ri"(u));
        return ret;
 }
 
-static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v)
+static inline void atomic_clear_mask(unsigned long mask, unsigned long *v)
 {
-       __asm__ __volatile__("stc ccr,r1l\n\t"
-                            "orc #0x80,ccr\n\t"
-                            "mov.l %0,er0\n\t"
-                            "and.l %1,er0\n\t"
-                            "mov.l er0,%0\n\t"
-                            "ldc r1l,ccr" 
-                             : "=m" (*v) : "g" (~(mask)) :"er0","er1");
+       unsigned char ccr;
+       unsigned long tmp;
+
+       __asm__ __volatile__(
+               "stc ccr,%w3\n\t"
+               "orc #0x80,ccr\n\t"
+               "mov.l %0,%1\n\t"
+               "and.l %2,%1\n\t"
+               "mov.l %1,%0\n\t"
+               "ldc %w3,ccr"
+               : "=m"(*v), "=r"(tmp)
+               : "g"(~(mask)), "r"(ccr));
 }
 
-static __inline__ void atomic_set_mask(unsigned long mask, unsigned long *v)
+static inline void atomic_set_mask(unsigned long mask, unsigned long *v)
 {
-       __asm__ __volatile__("stc ccr,r1l\n\t"
-                            "orc #0x80,ccr\n\t"
-                            "mov.l %0,er0\n\t"
-                            "or.l %1,er0\n\t"
-                            "mov.l er0,%0\n\t"
-                            "ldc r1l,ccr" 
-                             : "=m" (*v) : "g" (mask) :"er0","er1");
+       unsigned char ccr;
+       unsigned long tmp;
+
+       __asm__ __volatile__(
+               "stc ccr,%w3\n\t"
+               "orc #0x80,ccr\n\t"
+               "mov.l %0,%1\n\t"
+               "or.l %2,%1\n\t"
+               "mov.l %1,%0\n\t"
+               "ldc %w3,ccr"
+               : "=m"(*v), "=r"(tmp)
+               : "g"(~(mask)), "r"(ccr));
 }
 
 /* Atomic operations are already serializing */