Browse Source

* Bsf/Bsr on x86 handle now correctly 0 as argument, resolves #22783
* generic Bsf implementations handle now correctly 0 as argument
* test extended

git-svn-id: trunk@22327 -

florian 13 years ago
parent
commit
8818b58e5d
4 changed files with 74 additions and 7 deletions
  1. 5 0
      compiler/x86/cgx86.pas
  2. 10 3
      rtl/i386/i386.inc
  3. 7 4
      rtl/inc/generic.inc
  4. 52 0
      tests/test/tbsx1.pp

+ 5 - 0
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);
      procedure tcgx86.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister);
      var
      var
        opsize: topsize;
        opsize: topsize;
+       l : TAsmLabel;
      begin
      begin
        opsize:=tcgsize2opsize[size];
        opsize:=tcgsize2opsize[size];
        if not reverse then
        if not reverse then
          list.concat(taicpu.op_reg_reg(A_BSF,opsize,src,dst))
          list.concat(taicpu.op_reg_reg(A_BSF,opsize,src,dst))
        else
        else
          list.concat(taicpu.op_reg_reg(A_BSR,opsize,src,dst));
          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;
      end;
 
 
 {*************** compare instructructions ****************}
 {*************** compare instructructions ****************}

+ 10 - 3
rtl/i386/i386.inc

@@ -1564,8 +1564,12 @@ function BsfQWord(Const AValue : QWord): cardinal; assembler; nostackframe;
 asm
 asm
      bsfl    4(%esp),%eax
      bsfl    4(%esp),%eax
      jnz     .L2
      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:
 .L2:
 end;
 end;
 {$endif FPC_SYSTEM_HAS_BSF_QWORD}
 {$endif FPC_SYSTEM_HAS_BSF_QWORD}
@@ -1579,7 +1583,10 @@ asm
      jz     .L1
      jz     .L1
      add     $32,%eax
      add     $32,%eax
      jmp     .L2
      jmp     .L2
-.L1: bsrl    4(%esp),%eax
+.L1:
+     bsrl    4(%esp),%eax
+     jnz     .L2
+     movl    $255,%eax
 .L2:
 .L2:
 end;
 end;
 {$endif FPC_SYSTEM_HAS_BSR_QWORD}
 {$endif FPC_SYSTEM_HAS_BSR_QWORD}

+ 7 - 4
rtl/inc/generic.inc

@@ -2381,9 +2381,10 @@ function BsrByte(Const AValue: Byte): Byte;
 {$ifndef FPC_HAS_INTERNAL_BSF_WORD}
 {$ifndef FPC_HAS_INTERNAL_BSF_WORD}
 function BsfWord(Const AValue: Word): cardinal;
 function BsfWord(Const AValue: Word): cardinal;
   begin
   begin
+    result:=$ff;
     if lo(AValue)<>0 then
     if lo(AValue)<>0 then
       result:=BsfByte(lo(AValue))
       result:=BsfByte(lo(AValue))
-    else
+    else if hi(AValue) <> 0 then
       result:=BsfByte(hi(AValue))+8
       result:=BsfByte(hi(AValue))+8
   end;
   end;
 {$endif}
 {$endif}
@@ -2405,9 +2406,10 @@ function BsrWord(Const AValue: Word): cardinal;
 {$ifndef FPC_SYSTEM_HAS_BSF_DWORD}
 {$ifndef FPC_SYSTEM_HAS_BSF_DWORD}
 function BsfDWord(Const AValue : DWord): cardinal;
 function BsfDWord(Const AValue : DWord): cardinal;
 begin
 begin
+  result:=$ff;
   if lo(AValue)<>0 then
   if lo(AValue)<>0 then
     result:=BsfWord(lo(AValue))
     result:=BsfWord(lo(AValue))
-  else
+  else if hi(AValue) <> 0 then
     result:=BsfWord(hi(AValue))+16
     result:=BsfWord(hi(AValue))+16
 end;
 end;
 {$endif}
 {$endif}
@@ -2429,10 +2431,11 @@ end;
 {$ifndef FPC_SYSTEM_HAS_BSF_QWORD}
 {$ifndef FPC_SYSTEM_HAS_BSF_QWORD}
 function BsfQWord(Const AValue : QWord): cardinal;
 function BsfQWord(Const AValue : QWord): cardinal;
   begin
   begin
+    result:=$ff;
     if lo(AValue) <> 0 then
     if lo(AValue) <> 0 then
       result:=BsfDWord(lo(AValue))
       result:=BsfDWord(lo(AValue))
-    else
-      result:=BsfDWord(hi(AValue)) + 32
+    else hi(AValue) <> 0 then
+      result:=BsfDWord(hi(AValue)) + 32;
   end;
   end;
 {$endif}
 {$endif}
 {$endif}
 {$endif}

+ 52 - 0
tests/test/tbsx1.pp

@@ -23,6 +23,19 @@ begin
       exit(false);
       exit(false);
     end;
     end;
   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;
   result:=true;
 end;
 end;
 
 
@@ -47,6 +60,19 @@ begin
       exit(false);
       exit(false);
     end;
     end;
   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;
   result:=true;
 end;
 end;
 
 
@@ -71,6 +97,19 @@ begin
       exit(false);
       exit(false);
     end;
     end;
   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;
   result:=true;
 end;
 end;
 
 
@@ -93,6 +132,19 @@ begin
       exit(false);
       exit(false);
     end;
     end;
   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;
   result:=true;
 end;
 end;