..., rendering affected code more efficient and smaller. Note that in atomic.h this at once does away with the redundant output and input specifications of the memory location touched. Signed-off-by: Jan Beulich --- TBD: Do we want to abstract the pattern asm ( "...; set %" : "=" (var) ... ) matching asm ( "..." : "=@cc" (var) ... ) via some macro? While this would eliminate many (all?) of the conditionals added here, it would result in the : no longer being visible in the actual source, making the asm()s look somewhat odd. Otherwise, to limit code duplication, it may be preferable to put the #ifdef-s inside the asm()s instead of around them. --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -610,7 +610,12 @@ do { */ static bool_t even_parity(uint8_t v) { +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm ( "test %1,%1" : "=@ccp" (v) : "q" (v) ); +#else asm ( "test %1,%1; setp %0" : "=qm" (v) : "q" (v) ); +#endif + return v; } @@ -832,8 +837,14 @@ static int read_ulong( static bool_t mul_dbl(unsigned long m[2]) { bool_t rc; + +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm ( "mul %1" : "+a" (m[0]), "+d" (m[1]), "=@cco" (rc) ); +#else asm ( "mul %1; seto %2" : "+a" (m[0]), "+d" (m[1]), "=qm" (rc) ); +#endif + return rc; } @@ -845,8 +856,14 @@ static bool_t mul_dbl(unsigned long m[2] static bool_t imul_dbl(unsigned long m[2]) { bool_t rc; + +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm ( "imul %1" : "+a" (m[0]), "+d" (m[1]), "=@cco" (rc) ); +#else asm ( "imul %1; seto %2" : "+a" (m[0]), "+d" (m[1]), "=qm" (rc) ); +#endif + return rc; } @@ -4651,9 +4668,15 @@ x86_emulate( case 0xbc: /* bsf or tzcnt */ { bool_t zf; +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm ( "bsf %2,%0" + : "=r" (dst.val), "=@ccz" (zf) + : "rm" (src.val) ); +#else asm ( "bsf %2,%0; setz %1" : "=r" (dst.val), "=qm" (zf) : "rm" (src.val) ); +#endif _regs.eflags &= ~EFLG_ZF; if ( (vex.pfx == vex_f3) && vcpu_has_bmi1() ) { @@ -4677,9 +4700,15 @@ x86_emulate( case 0xbd: /* bsr or lzcnt */ { bool_t zf; +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm ( "bsr %2,%0" + : "=r" (dst.val), "=@ccz" (zf) + : "rm" (src.val) ); +#else asm ( "bsr %2,%0; setz %1" : "=r" (dst.val), "=qm" (zf) : "rm" (src.val) ); +#endif _regs.eflags &= ~EFLG_ZF; if ( (vex.pfx == vex_f3) && vcpu_has_lzcnt() ) { --- a/xen/include/asm-x86/atomic.h +++ b/xen/include/asm-x86/atomic.h @@ -193,12 +193,18 @@ static inline void atomic_sub(int i, ato */ static inline int atomic_sub_and_test(int i, atomic_t *v) { - unsigned char c; + bool_t c; + +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm volatile ( "lock; subl %2,%0" + : "+m" (*(volatile int *)&v->counter), "=@ccz" (c) + : "ir" (i) : "memory" ); +#else + asm volatile ( "lock; subl %2,%0; setz %1" + : "+m" (*(volatile int *)&v->counter), "=qm" (c) + : "ir" (i) : "memory" ); +#endif - asm volatile ( - "lock; subl %2,%0; sete %1" - : "=m" (*(volatile int *)&v->counter), "=qm" (c) - : "ir" (i), "m" (*(volatile int *)&v->counter) : "memory" ); return c; } @@ -240,13 +246,19 @@ static inline void atomic_dec(atomic_t * */ static inline int atomic_dec_and_test(atomic_t *v) { - unsigned char c; + bool_t c; - asm volatile ( - "lock; decl %0; sete %1" - : "=m" (*(volatile int *)&v->counter), "=qm" (c) - : "m" (*(volatile int *)&v->counter) : "memory" ); - return c != 0; +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm volatile ( "lock; decl %0" + : "+m" (*(volatile int *)&v->counter), "=@ccz" (c) + :: "memory" ); +#else + asm volatile ( "lock; decl %0; setz %1" + : "+m" (*(volatile int *)&v->counter), "=qm" (c) + :: "memory" ); +#endif + + return c; } /** @@ -259,13 +271,19 @@ static inline int atomic_dec_and_test(at */ static inline int atomic_inc_and_test(atomic_t *v) { - unsigned char c; + bool_t c; - asm volatile ( - "lock; incl %0; sete %1" - : "=m" (*(volatile int *)&v->counter), "=qm" (c) - : "m" (*(volatile int *)&v->counter) : "memory" ); - return c != 0; +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm volatile ( "lock; incl %0" + : "+m" (*(volatile int *)&v->counter), "=@ccz" (c) + :: "memory" ); +#else + asm volatile ( "lock; incl %0; setz %1" + : "+m" (*(volatile int *)&v->counter), "=qm" (c) + :: "memory" ); +#endif + + return c; } /** @@ -279,12 +297,18 @@ static inline int atomic_inc_and_test(at */ static inline int atomic_add_negative(int i, atomic_t *v) { - unsigned char c; + bool_t c; + +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm volatile ( "lock; addl %2,%0" + : "+m" (*(volatile int *)&v->counter), "=@ccs" (c) + : "ir" (i) : "memory" ); +#else + asm volatile ( "lock; addl %2,%0; sets %1" + : "+m" (*(volatile int *)&v->counter), "=qm" (c) + : "ir" (i) : "memory" ); +#endif - asm volatile ( - "lock; addl %2,%0; sets %1" - : "=m" (*(volatile int *)&v->counter), "=qm" (c) - : "ir" (i), "m" (*(volatile int *)&v->counter) : "memory" ); return c; } --- a/xen/include/asm-x86/bitops.h +++ b/xen/include/asm-x86/bitops.h @@ -145,8 +145,14 @@ static inline int test_and_set_bit(int n { int oldbit; +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm volatile ( "lock; btsl %2,%1" + : "=@ccc" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory" ); +#else asm volatile ( "lock; btsl %2,%1\n\tsbbl %0,%0" - : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory"); + : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory" ); +#endif + return oldbit; } #define test_and_set_bit(nr, addr) ({ \ @@ -167,10 +173,16 @@ static inline int __test_and_set_bit(int { int oldbit; - asm volatile ( - "btsl %2,%1\n\tsbbl %0,%0" - : "=r" (oldbit), "+m" (*(int *)addr) - : "Ir" (nr) : "memory" ); +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm volatile ( "btsl %2,%1" + : "=@ccc" (oldbit), "+m" (*(int *)addr) + : "Ir" (nr) : "memory" ); +#else + asm volatile ( "btsl %2,%1\n\tsbbl %0,%0" + : "=r" (oldbit), "+m" (*(int *)addr) + : "Ir" (nr) : "memory" ); +#endif + return oldbit; } #define __test_and_set_bit(nr, addr) ({ \ @@ -190,8 +202,14 @@ static inline int test_and_clear_bit(int { int oldbit; +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm volatile ( "lock; btrl %2,%1" + : "=@ccc" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory" ); +#else asm volatile ( "lock; btrl %2,%1\n\tsbbl %0,%0" - : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory"); + : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory" ); +#endif + return oldbit; } #define test_and_clear_bit(nr, addr) ({ \ @@ -212,10 +230,16 @@ static inline int __test_and_clear_bit(i { int oldbit; - asm volatile ( - "btrl %2,%1\n\tsbbl %0,%0" - : "=r" (oldbit), "+m" (*(int *)addr) - : "Ir" (nr) : "memory" ); +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm volatile ( "btrl %2,%1" + : "=@ccc" (oldbit), "+m" (*(int *)addr) + : "Ir" (nr) : "memory" ); +#else + asm volatile ( "btrl %2,%1\n\tsbbl %0,%0" + : "=r" (oldbit), "+m" (*(int *)addr) + : "Ir" (nr) : "memory" ); +#endif + return oldbit; } #define __test_and_clear_bit(nr, addr) ({ \ @@ -228,10 +252,16 @@ static inline int __test_and_change_bit( { int oldbit; - asm volatile ( - "btcl %2,%1\n\tsbbl %0,%0" - : "=r" (oldbit), "+m" (*(int *)addr) - : "Ir" (nr) : "memory" ); +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm volatile ( "btcl %2,%1" + : "=@ccc" (oldbit), "+m" (*(int *)addr) + : "Ir" (nr) : "memory" ); +#else + asm volatile ( "btcl %2,%1\n\tsbbl %0,%0" + : "=r" (oldbit), "+m" (*(int *)addr) + : "Ir" (nr) : "memory" ); +#endif + return oldbit; } #define __test_and_change_bit(nr, addr) ({ \ @@ -251,8 +281,14 @@ static inline int test_and_change_bit(in { int oldbit; +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm volatile ( "lock; btcl %2,%1" + : "=@ccc" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory" ); +#else asm volatile ( "lock; btcl %2,%1\n\tsbbl %0,%0" - : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory"); + : "=r" (oldbit), "+m" (ADDR) : "Ir" (nr) : "memory" ); +#endif + return oldbit; } #define test_and_change_bit(nr, addr) ({ \ @@ -270,10 +306,16 @@ static inline int variable_test_bit(int { int oldbit; - asm volatile ( - "btl %2,%1\n\tsbbl %0,%0" - : "=r" (oldbit) - : "m" (CONST_ADDR), "Ir" (nr) : "memory" ); +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + asm volatile ( "btl %2,%1" + : "=@ccc" (oldbit) + : "m" (CONST_ADDR), "Ir" (nr) : "memory" ); +#else + asm volatile ( "btl %2,%1\n\tsbbl %0,%0" + : "=r" (oldbit) + : "m" (CONST_ADDR), "Ir" (nr) : "memory" ); +#endif + return oldbit; } --- a/xen/include/asm-x86/hvm/vmx/vmx.h +++ b/xen/include/asm-x86/hvm/vmx/vmx.h @@ -406,12 +406,17 @@ static inline bool_t __vmread_safe(unsig VMREAD_OPCODE MODRM_EAX_ECX #endif /* CF==1 or ZF==1 --> rc = 0 */ +#ifdef __GCC_ASM_FLAG_OUTPUTS__ + : "=@ccnbe" (okay), +#else "setnbe %0" + : "=qm" (okay), +#endif #ifdef HAVE_GAS_VMX - : "=qm" (okay), "=rm" (*value) + "=rm" (*value) : "r" (field)); #else - : "=qm" (okay), "=c" (*value) + "=c" (*value) : "a" (field)); #endif