From fdb8cf8c1b80da286f448f5e748b65f9115d7043 Mon Sep 17 00:00:00 2001 From: Josef 'Jeff' Sipek Date: Wed, 19 Nov 2014 16:10:27 -0500 Subject: [PATCH] 5291 x86 {high,low}bit rely on undefined behavior Reviewed by: Keith Wesolowski Approved by: Dan McDonald --- usr/src/uts/intel/amd64/ml/amd64.il | 9 ------ usr/src/uts/intel/asm/bitmap.h | 24 ++++++++------- usr/src/uts/intel/ia32/ml/i86_subr.s | 57 +++++++++++++----------------------- usr/src/uts/intel/ia32/ml/ia32.il | 18 ------------ 4 files changed, 35 insertions(+), 73 deletions(-) diff --git a/usr/src/uts/intel/amd64/ml/amd64.il b/usr/src/uts/intel/amd64/ml/amd64.il index 2afcf93bed..fc78c95a95 100644 --- a/usr/src/uts/intel/amd64/ml/amd64.il +++ b/usr/src/uts/intel/amd64/ml/amd64.il @@ -64,15 +64,6 @@ .end / -/ find the low order bit in a word -/ - .inline lowbit,4 - movq $-1, %rax - bsfq %rdi, %rax - incq %rax - .end - -/ / Networking byte order functions (too bad, Intel has the wrong byte order) / diff --git a/usr/src/uts/intel/asm/bitmap.h b/usr/src/uts/intel/asm/bitmap.h index 6148277085..92020e39e3 100644 --- a/usr/src/uts/intel/asm/bitmap.h +++ b/usr/src/uts/intel/asm/bitmap.h @@ -48,29 +48,33 @@ extern "C" { extern __GNU_INLINE int highbit(ulong_t i) { - long value = -1l; + long value; + uint8_t zf; __asm__( - "bsr" __SUF " %1,%0" - : "+r" (value) - : "r" (i) + "bsr" __SUF " %2,%0;" + "setz %1" + : "=r" (value), "=q" (zf) + : "mr" (i) : "cc"); - return ((int)(value + 1)); + return (zf ? 0 : (value + 1)); } extern __GNU_INLINE int lowbit(ulong_t i) { - long value = -1l; + long value; + uint8_t zf; __asm__( - "bsf" __SUF " %1,%0" - : "+r" (value) - : "r" (i) + "bsf" __SUF " %2,%0;" + "setz %1" + : "=r" (value), "=q" (zf) + : "mr" (i) : "cc"); - return ((int)(value + 1)); + return (zf ? 0 : (value + 1)); } extern __GNU_INLINE uint_t diff --git a/usr/src/uts/intel/ia32/ml/i86_subr.s b/usr/src/uts/intel/ia32/ml/i86_subr.s index 9baabcee49..23b20ebbde 100644 --- a/usr/src/uts/intel/ia32/ml/i86_subr.s +++ b/usr/src/uts/intel/ia32/ml/i86_subr.s @@ -2801,7 +2801,8 @@ lowbit(ulong_t i) ENTRY(lowbit) movl $-1, %eax - bsfq %rdi, %rax + bsfq %rdi, %rdi + cmovnz %edi, %eax incl %eax ret SET_SIZE(lowbit) @@ -2809,10 +2810,13 @@ lowbit(ulong_t i) #elif defined(__i386) ENTRY(lowbit) - movl $-1, %eax bsfl 4(%esp), %eax + jz 0f incl %eax ret +0: + xorl %eax, %eax + ret SET_SIZE(lowbit) #endif /* __i386 */ @@ -2825,60 +2829,41 @@ int highbit(ulong_t i) { return (0); } +/*ARGSUSED*/ +int +highbit64(uint64_t i) +{ return (0); } + #else /* __lint */ #if defined(__amd64) ENTRY(highbit) + ALTENTRY(highbit64) movl $-1, %eax - bsrq %rdi, %rax + bsrq %rdi, %rdi + cmovnz %edi, %eax incl %eax ret + SET_SIZE(highbit64) SET_SIZE(highbit) #elif defined(__i386) ENTRY(highbit) - movl $-1, %eax bsrl 4(%esp), %eax + jz 0f incl %eax ret +0: + xorl %eax, %eax + ret SET_SIZE(highbit) -#endif /* __i386 */ -#endif /* __lint */ - -#if defined(__lint) - -/*ARGSUSED*/ -int -highbit64(uint64_t i) -{ return (0); } - -#else /* __lint */ - -#if defined(__amd64) - - ENTRY(highbit64) - movl $-1, %eax - bsrq %rdi, %rax - incl %eax - ret - SET_SIZE(highbit64) - -#elif defined(__i386) - ENTRY(highbit64) bsrl 8(%esp), %eax - jz .lowbit - addl $32, %eax - jmp .done - -.lowbit: - movl $-1, %eax - bsrl 4(%esp), %eax -.done: - incl %eax + jz highbit + addl $33, %eax ret SET_SIZE(highbit64) diff --git a/usr/src/uts/intel/ia32/ml/ia32.il b/usr/src/uts/intel/ia32/ml/ia32.il index 78a2b6c647..8ced7d69a6 100644 --- a/usr/src/uts/intel/ia32/ml/ia32.il +++ b/usr/src/uts/intel/ia32/ml/ia32.il @@ -66,24 +66,6 @@ .end / -/ find the low order bit in a word -/ - .inline lowbit,4 - movl $-1, %eax - bsfl (%esp), %eax - incl %eax - .end - -/ -/ find the high order bit in a word -/ - .inline highbit,4 - movl $-1, %eax - bsrl (%esp), %eax - incl %eax - .end - -/ / Networking byte order functions (too bad, Intel has the wrong byte order) / .inline htonll,4 -- 2.11.4.GIT