@@ -1015,10 +1015,18 @@ atomic_uint64_t::compare_swap(volatile uint64_t &x, uint64_t expected, uint64_t
10151015 return __atomic_compare_exchange (&x,&expected,&desired,0 ,CLICK_ATOMIC_MEMORDER, CLICK_ATOMIC_MEMORDER)
10161016 ? expected : x;
10171017#elif CLICK_ATOMIC_X86
1018- asm volatile (CLICK_ATOMIC_LOCK " cmpxchgq %2,%1"
1019- : " =a" (expected), " =m" (x)
1020- : " r" (desired), " 0" (expected), " m" (x)
1021- : " cc" , " memory" );
1018+ #if defined(__x86_64__)
1019+ asm volatile (CLICK_ATOMIC_LOCK " cmpxchgq %2,%1"
1020+ : " =a" (expected), " =m" (x)
1021+ : " r" (desired), " 0" (expected), " m" (x)
1022+ : " cc" , " memory" );
1023+ #else
1024+ asm volatile (CLICK_ATOMIC_LOCK " cmpxchg8b %1\n\t " // Compare EDX:EAX with [mem], replace with ECX:EBX if equal
1025+ : " +A" (expected) // load expected into EAX:EDX
1026+ : " m" (x), // preload memory value to compare.
1027+ " b" ((uint32_t )desired), " c" ((uint32_t ) (desired>>32 ))
1028+ : " memory" );
1029+ #endif
10221030 return expected;
10231031#elif CLICK_LINUXMODULE && defined(cmpxchg)
10241032 return cmpxchg (&x, expected, desired);
@@ -1063,11 +1071,31 @@ atomic_uint64_t::fetch_and_add(uint64_t delta)
10631071#if CLICK_ATOMIC_BUILTINS
10641072 return __atomic_fetch_add (&_val, delta, CLICK_ATOMIC_MEMORDER);
10651073#elif CLICK_ATOMIC_X86
1066- asm volatile (CLICK_ATOMIC_LOCK " xaddq %0,%1"
1067- : " =r" (delta), " =m" (CLICK_ATOMIC_VAL)
1068- : " 0" (delta), " m" (CLICK_ATOMIC_VAL)
1069- : " cc" );
1070- return delta;
1074+ #if defined(__x86_64__)
1075+ asm volatile (CLICK_ATOMIC_LOCK " xaddq %0,%1"
1076+ : " =r" (delta), " =m" (CLICK_ATOMIC_VAL)
1077+ : " 0" (delta), " m" (CLICK_ATOMIC_VAL)
1078+ : " cc" );
1079+ return delta;
1080+ #else
1081+ uint32_t old_lo, old_hi;
1082+ asm volatile (
1083+ " 1:\n\t "
1084+ " movl (%2), %%eax\n\t " // Load old low 32 bits
1085+ " movl 4(%2), %%edx\n\t " // Load old high 32 bits
1086+ " movl %%eax, %%ebx\n\t " // Copy low to ebx (new low)
1087+ " movl %%edx, %%ecx\n\t " // Copy high to ecx (new high)
1088+ " addl %3, %%ebx\n\t " // new low += delta low
1089+ " adcl %4, %%ecx\n\t " // new high += delta high + carry
1090+ CLICK_ATOMIC_LOCK " cmpxchg8b (%2)\n\t " // atomic cmpxchg8b
1091+ " jnz 1b\n\t " // if fail, retry
1092+ " movl %%eax, %0\n\t " // store old low
1093+ " movl %%edx, %1\n\t " // store old high
1094+ : " +a" (old_lo), " +d" (old_hi)
1095+ : " r" (&_val), " r" ((uint32_t )delta), " r" ((uint32_t )(delta >> 3 ))
1096+ : " ebx" , " memory" );
1097+ return (static_cast <uint64_t >(old_hi) << 32 ) | old_lo;
1098+ #endif
10711099#elif CLICK_LINUXMODULE && HAVE_LINUX_ATOMIC_ADD_RETURN
10721100 return atomic64_add_return (&_val, delta) - delta;
10731101#elif CLICK_LINUXMODULE
0 commit comments