asm volatile("# beginning down_write\n\t"
                     LOCK_PREFIX "  xadd      %1,(%2)\n\t"
                     /* adds 0xffff0001, returns the old value */
-                    "  test      %1,%1\n\t"
-                    /* was the count 0 before? */
+                    "  test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t"
+                    /* was the active mask 0 before? */
                     "  jz        1f\n"
                     "  call call_rwsem_down_write_failed\n"
                     "1:\n"
  */
 static inline int __down_write_trylock(struct rw_semaphore *sem)
 {
-       long ret = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
-                          RWSEM_ACTIVE_WRITE_BIAS);
-       if (ret == RWSEM_UNLOCKED_VALUE)
-               return 1;
-       return 0;
+       long result, tmp;
+       asm volatile("# beginning __down_write_trylock\n\t"
+                    "  mov          %0,%1\n\t"
+                    "1:\n\t"
+                    "  test " __ASM_SEL(%w1,%k1) "," __ASM_SEL(%w1,%k1) "\n\t"
+                    /* was the active mask 0 before? */
+                    "  jnz          2f\n\t"
+                    "  mov          %1,%2\n\t"
+                    "  add          %3,%2\n\t"
+                    LOCK_PREFIX "  cmpxchg  %2,%0\n\t"
+                    "  jnz          1b\n\t"
+                    "2:\n\t"
+                    "  sete         %b1\n\t"
+                    "  movzbl       %b1, %k1\n\t"
+                    "# ending __down_write_trylock\n\t"
+                    : "+m" (sem->count), "=&a" (result), "=&r" (tmp)
+                    : "er" (RWSEM_ACTIVE_WRITE_BIAS)
+                    : "memory", "cc");
+       return result;
 }
 
 /*