diff --git a/compiler/x86/cgx86.pas b/compiler/x86/cgx86.pas index fcba4a13b6..bfc10b51ed 100644 --- a/compiler/x86/cgx86.pas +++ b/compiler/x86/cgx86.pas @@ -1628,12 +1628,17 @@ unit cgx86; procedure tcgx86.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); var opsize: topsize; + l : TAsmLabel; begin opsize:=tcgsize2opsize[size]; if not reverse then list.concat(taicpu.op_reg_reg(A_BSF,opsize,src,dst)) else list.concat(taicpu.op_reg_reg(A_BSR,opsize,src,dst)); + current_asmdata.getjumplabel(l); + a_jmp_cond(list,OC_NE,l); + list.concat(taicpu.op_const_reg(A_MOV,opsize,$ff,dst)); + a_label(list,l); end; {*************** compare instructructions ****************} diff --git a/rtl/i386/i386.inc b/rtl/i386/i386.inc index 73b3d04fe2..121b81ed6d 100644 --- a/rtl/i386/i386.inc +++ b/rtl/i386/i386.inc @@ -1564,8 +1564,12 @@ function BsfQWord(Const AValue : QWord): cardinal; assembler; nostackframe; asm bsfl 4(%esp),%eax jnz .L2 -.L1: bsfl 8(%esp),%eax - add $32,%eax +.L1: + bsfl 8(%esp),%eax + jnz .L3 + movl $223,%eax +.L3: + addl $32,%eax .L2: end; {$endif FPC_SYSTEM_HAS_BSF_QWORD} @@ -1579,7 +1583,10 @@ asm jz .L1 add $32,%eax jmp .L2 -.L1: bsrl 4(%esp),%eax +.L1: + bsrl 4(%esp),%eax + jnz .L2 + movl $255,%eax .L2: end; {$endif FPC_SYSTEM_HAS_BSR_QWORD} diff --git a/rtl/inc/generic.inc b/rtl/inc/generic.inc index cf00997c6b..be0feeae1c 100644 --- a/rtl/inc/generic.inc +++ b/rtl/inc/generic.inc @@ -2381,9 +2381,10 @@ function BsrByte(Const AValue: Byte): Byte; {$ifndef FPC_HAS_INTERNAL_BSF_WORD} function BsfWord(Const AValue: Word): cardinal; begin + result:=$ff; if lo(AValue)<>0 then result:=BsfByte(lo(AValue)) - else + else if hi(AValue) <> 0 then result:=BsfByte(hi(AValue))+8 end; {$endif} @@ -2405,9 +2406,10 @@ function BsrWord(Const AValue: Word): cardinal; {$ifndef FPC_SYSTEM_HAS_BSF_DWORD} function BsfDWord(Const AValue : DWord): cardinal; begin + result:=$ff; if lo(AValue)<>0 then result:=BsfWord(lo(AValue)) - else + else if hi(AValue) <> 0 then result:=BsfWord(hi(AValue))+16 end; {$endif} @@ -2429,10 +2431,11 @@ end; {$ifndef FPC_SYSTEM_HAS_BSF_QWORD} function BsfQWord(Const AValue : QWord): cardinal; begin + result:=$ff; if lo(AValue) <> 0 then result:=BsfDWord(lo(AValue)) - else - result:=BsfDWord(hi(AValue)) + 32 + else hi(AValue) <> 0 then + result:=BsfDWord(hi(AValue)) + 32; end; {$endif} {$endif} diff --git a/tests/test/tbsx1.pp b/tests/test/tbsx1.pp index 98aaf3c7e4..d15c28cd0b 100644 --- a/tests/test/tbsx1.pp +++ b/tests/test/tbsx1.pp @@ -23,6 +23,19 @@ begin exit(false); end; end; + x8:=0; + f:=BsfByte(x8); + if (f<>$ff) then + begin + writeln('BsfByte(',x8,') returned ',f,', should be ',$ff); + exit(false); + end; + r:=BsrByte(x8); + if r<>$ff then + begin + writeln('BsrByte(',x8,') returned ',f,', should be ',$ff); + exit(false); + end; result:=true; end; @@ -47,6 +60,19 @@ begin exit(false); end; end; + x16:=0; + f:=BsfDWord(x16); + if (f<>$ff) then + begin + writeln('BsfWord(',x16,') returned ',f,', should be ',$ff); + exit(false); + end; + r:=BsrWord(x16); + if r<>$ff then + begin + writeln('BsrWord(',x16,') returned ',f,', should be ',$ff); + exit(false); + end; result:=true; end; @@ -71,6 +97,19 @@ begin exit(false); end; end; + x32:=0; + f:=BsfDWord(x32); + if (f<>$ff) then + begin + writeln('BsfDWord(',x32,') returned ',f,', should be ',$ff); + exit(false); + end; + r:=BsrDWord(x32); + if r<>$ff then + begin + writeln('BsrDWord(',x32,') returned ',f,', should be ',$ff); + exit(false); + end; result:=true; end; @@ -93,6 +132,19 @@ begin exit(false); end; end; + x64:=0; + f:=BsfQWord(x64); + if (f<>$ff) then + begin + writeln('BsfQWord(',x64,') returned ',f,', should be ',$ff); + exit(false); + end; + r:=BsrQWord(x64); + if r<>$ff then + begin + writeln('BsrQWord(',x64,') returned ',f,', should be ',$ff); + exit(false); + end; result:=true; end;