Browse Source

* Added new tests for BZHI optimisations

J. Gareth "Curious Kit" Moreton 2 years ago
parent
commit
0dbf40a24c

+ 38 - 0
tests/test/cg/tbzhi1.pp

@@ -0,0 +1,38 @@
+{ %CPU=i386,x86_64 }
+{ %OPT=-O3 -CpCOREAVX2 -OpCOREAVX2 }
+
+program tbzhi1;
+
+function MaskOut(Input: LongInt; Index: Byte): LongInt; noinline;
+begin
+  MaskOut := Input and ((1 shl Index) - 1);
+end;
+
+const
+  Inputs:  array[0..3] of LongInt = (0, $FFFFFFFF, $12345678, $87654321);
+  Expected: array[0..3] of array[0..31] of LongInt =
+    (
+      ($00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000),
+      ($00000000, $00000001, $00000003, $00000007, $0000000F, $0000001F, $0000003F, $0000007F, $000000FF, $000001FF, $000003FF, $000007FF, $00000FFF, $00001FFF, $00003FFF, $00007FFF, $0000FFFF, $0001FFFF, $0003FFFF, $0007FFFF, $000FFFFF, $001FFFFF, $003FFFFF, $007FFFFF, $00FFFFFF, $01FFFFFF, $03FFFFFF, $07FFFFFF, $0FFFFFFF, $1FFFFFFF, $3FFFFFFF, $7FFFFFFF),
+      ($00000000, $00000000, $00000000, $00000000, $00000008, $00000018, $00000038, $00000078, $00000078, $00000078, $00000278, $00000678, $00000678, $00001678, $00001678, $00005678, $00005678, $00005678, $00005678, $00045678, $00045678, $00145678, $00345678, $00345678, $00345678, $00345678, $02345678, $02345678, $02345678, $12345678, $12345678, $12345678),
+      ($00000000, $00000001, $00000001, $00000001, $00000001, $00000001, $00000021, $00000021, $00000021, $00000121, $00000321, $00000321, $00000321, $00000321, $00000321, $00004321, $00004321, $00014321, $00014321, $00054321, $00054321, $00054321, $00254321, $00654321, $00654321, $01654321, $03654321, $07654321, $07654321, $07654321, $07654321, $07654321)
+    );
+
+var
+  X: Byte;
+  Y: Integer;
+  Output: LongInt;
+begin
+  for Y := Low(Inputs) to High(Inputs) do
+    for X := 0 to 31 do
+      begin
+	    Output := MaskOut(Inputs[Y], X);
+		if Output <> Expected[Y][X] then
+		  begin
+		    WriteLn('FAIL: $', HexStr(Inputs[Y], 8), ' and ((1 shl ', X, ') - 1) returned $', HexStr(Output, 8), '; expected $', HexStr(Expected[Y][X], 8));
+		    Halt(1);
+		  end;
+	  end;
+
+  WriteLn('ok');
+end.

+ 38 - 0
tests/test/cg/tbzhi1a.pp

@@ -0,0 +1,38 @@
+{ %CPU=i386,x86_64 }
+{ %OPT=-O3 -CpCOREAVX2 -OpCOREAVX2 }
+
+program tbzhi1a;
+
+function MaskOut(Input, Index: LongInt): LongInt; noinline;
+begin
+  MaskOut := Input and ((1 shl Index) - 1);
+end;
+
+const
+  Inputs:  array[0..3] of LongInt = (0, $FFFFFFFF, $12345678, $87654321);
+  Expected: array[0..3] of array[0..31] of LongInt =
+    (
+      ($00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000),
+      ($00000000, $00000001, $00000003, $00000007, $0000000F, $0000001F, $0000003F, $0000007F, $000000FF, $000001FF, $000003FF, $000007FF, $00000FFF, $00001FFF, $00003FFF, $00007FFF, $0000FFFF, $0001FFFF, $0003FFFF, $0007FFFF, $000FFFFF, $001FFFFF, $003FFFFF, $007FFFFF, $00FFFFFF, $01FFFFFF, $03FFFFFF, $07FFFFFF, $0FFFFFFF, $1FFFFFFF, $3FFFFFFF, $7FFFFFFF),
+      ($00000000, $00000000, $00000000, $00000000, $00000008, $00000018, $00000038, $00000078, $00000078, $00000078, $00000278, $00000678, $00000678, $00001678, $00001678, $00005678, $00005678, $00005678, $00005678, $00045678, $00045678, $00145678, $00345678, $00345678, $00345678, $00345678, $02345678, $02345678, $02345678, $12345678, $12345678, $12345678),
+      ($00000000, $00000001, $00000001, $00000001, $00000001, $00000001, $00000021, $00000021, $00000021, $00000121, $00000321, $00000321, $00000321, $00000321, $00000321, $00004321, $00004321, $00014321, $00014321, $00054321, $00054321, $00054321, $00254321, $00654321, $00654321, $01654321, $03654321, $07654321, $07654321, $07654321, $07654321, $07654321)
+    );
+
+var
+  X: Byte;
+  Y: Integer;
+  Output: LongInt;
+begin
+  for Y := Low(Inputs) to High(Inputs) do
+    for X := 0 to 31 do
+      begin
+	    Output := MaskOut(Inputs[Y], X);
+		if Output <> Expected[Y][X] then
+		  begin
+		    WriteLn('FAIL: $', HexStr(Inputs[Y], 8), ' and ((1 shl ', X, ') - 1) returned $', HexStr(Output, 8), '; expected $', HexStr(Expected[Y][X], 8));
+		    Halt(1);
+		  end;
+	  end;
+
+  WriteLn('ok');
+end.

+ 38 - 0
tests/test/cg/tbzhi1b.pp

@@ -0,0 +1,38 @@
+{ %CPU=i386,x86_64 }
+{ %OPT=-O3 -CpCOREAVX2 -OpCOREAVX2 }
+
+program tbzhi1b;
+
+function MaskOut(var Input: LongInt; Index: Byte): LongInt; noinline;
+begin
+  MaskOut := Input and ((1 shl Index) - 1);
+end;
+
+const
+  Inputs:  array[0..3] of LongInt = (0, $FFFFFFFF, $12345678, $87654321);
+  Expected: array[0..3] of array[0..31] of LongInt =
+    (
+      ($00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000),
+      ($00000000, $00000001, $00000003, $00000007, $0000000F, $0000001F, $0000003F, $0000007F, $000000FF, $000001FF, $000003FF, $000007FF, $00000FFF, $00001FFF, $00003FFF, $00007FFF, $0000FFFF, $0001FFFF, $0003FFFF, $0007FFFF, $000FFFFF, $001FFFFF, $003FFFFF, $007FFFFF, $00FFFFFF, $01FFFFFF, $03FFFFFF, $07FFFFFF, $0FFFFFFF, $1FFFFFFF, $3FFFFFFF, $7FFFFFFF),
+      ($00000000, $00000000, $00000000, $00000000, $00000008, $00000018, $00000038, $00000078, $00000078, $00000078, $00000278, $00000678, $00000678, $00001678, $00001678, $00005678, $00005678, $00005678, $00005678, $00045678, $00045678, $00145678, $00345678, $00345678, $00345678, $00345678, $02345678, $02345678, $02345678, $12345678, $12345678, $12345678),
+      ($00000000, $00000001, $00000001, $00000001, $00000001, $00000001, $00000021, $00000021, $00000021, $00000121, $00000321, $00000321, $00000321, $00000321, $00000321, $00004321, $00004321, $00014321, $00014321, $00054321, $00054321, $00054321, $00254321, $00654321, $00654321, $01654321, $03654321, $07654321, $07654321, $07654321, $07654321, $07654321)
+    );
+
+var
+  X: Byte;
+  Y: Integer;
+  Output: LongInt;
+begin
+  for Y := Low(Inputs) to High(Inputs) do
+    for X := 0 to 31 do
+      begin
+	    Output := MaskOut(Inputs[Y], X);
+		if Output <> Expected[Y][X] then
+		  begin
+		    WriteLn('FAIL: $', HexStr(Inputs[Y], 8), ' and ((1 shl ', X, ') - 1) returned $', HexStr(Output, 8), '; expected $', HexStr(Expected[Y][X], 8));
+		    Halt(1);
+		  end;
+	  end;
+
+  WriteLn('ok');
+end.

+ 39 - 0
tests/test/cg/tbzhi1c.pp

@@ -0,0 +1,39 @@
+{ %CPU=i386,x86_64 }
+{ %OPT=-O3 -CpCOREAVX2 -OpCOREAVX2 }
+
+program tbzhi1c;
+
+procedure MaskOut(var InOut: LongInt; Index: Byte); noinline;
+begin
+  InOut := InOut and ((1 shl Index) - 1);
+end;
+
+const
+  Inputs:  array[0..3] of LongInt = (0, $FFFFFFFF, $12345678, $87654321);
+  Expected: array[0..3] of array[0..31] of LongInt =
+    (
+      ($00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000),
+      ($00000000, $00000001, $00000003, $00000007, $0000000F, $0000001F, $0000003F, $0000007F, $000000FF, $000001FF, $000003FF, $000007FF, $00000FFF, $00001FFF, $00003FFF, $00007FFF, $0000FFFF, $0001FFFF, $0003FFFF, $0007FFFF, $000FFFFF, $001FFFFF, $003FFFFF, $007FFFFF, $00FFFFFF, $01FFFFFF, $03FFFFFF, $07FFFFFF, $0FFFFFFF, $1FFFFFFF, $3FFFFFFF, $7FFFFFFF),
+      ($00000000, $00000000, $00000000, $00000000, $00000008, $00000018, $00000038, $00000078, $00000078, $00000078, $00000278, $00000678, $00000678, $00001678, $00001678, $00005678, $00005678, $00005678, $00005678, $00045678, $00045678, $00145678, $00345678, $00345678, $00345678, $00345678, $02345678, $02345678, $02345678, $12345678, $12345678, $12345678),
+      ($00000000, $00000001, $00000001, $00000001, $00000001, $00000001, $00000021, $00000021, $00000021, $00000121, $00000321, $00000321, $00000321, $00000321, $00000321, $00004321, $00004321, $00014321, $00014321, $00054321, $00054321, $00054321, $00254321, $00654321, $00654321, $01654321, $03654321, $07654321, $07654321, $07654321, $07654321, $07654321)
+    );
+
+var
+  X: Byte;
+  Y: Integer;
+  Output: LongInt;
+begin
+  for Y := Low(Inputs) to High(Inputs) do
+    for X := 0 to 31 do
+      begin
+	    Output := Inputs[Y];
+		MaskOut(Output, X);
+		if Output <> Expected[Y][X] then
+		  begin
+		    WriteLn('FAIL: $', HexStr(Inputs[Y], 8), ' and ((1 shl ', X, ') - 1) returned $', HexStr(Output, 8), '; expected $', HexStr(Expected[Y][X], 8));
+		    Halt(1);
+		  end;
+	  end;
+
+  WriteLn('ok');
+end.

+ 39 - 0
tests/test/cg/tbzhi1d.pp

@@ -0,0 +1,39 @@
+{ %CPU=i386,x86_64 }
+{ %OPT=-O3 -CpCOREAVX2 -OpCOREAVX2 }
+
+program tbzhi1c;
+
+procedure MaskOut(var InOut: LongInt; Index: LongInt); noinline;
+begin
+  InOut := InOut and ((1 shl Index) - 1);
+end;
+
+const
+  Inputs:  array[0..3] of LongInt = (0, $FFFFFFFF, $12345678, $87654321);
+  Expected: array[0..3] of array[0..31] of LongInt =
+    (
+      ($00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000),
+      ($00000000, $00000001, $00000003, $00000007, $0000000F, $0000001F, $0000003F, $0000007F, $000000FF, $000001FF, $000003FF, $000007FF, $00000FFF, $00001FFF, $00003FFF, $00007FFF, $0000FFFF, $0001FFFF, $0003FFFF, $0007FFFF, $000FFFFF, $001FFFFF, $003FFFFF, $007FFFFF, $00FFFFFF, $01FFFFFF, $03FFFFFF, $07FFFFFF, $0FFFFFFF, $1FFFFFFF, $3FFFFFFF, $7FFFFFFF),
+      ($00000000, $00000000, $00000000, $00000000, $00000008, $00000018, $00000038, $00000078, $00000078, $00000078, $00000278, $00000678, $00000678, $00001678, $00001678, $00005678, $00005678, $00005678, $00005678, $00045678, $00045678, $00145678, $00345678, $00345678, $00345678, $00345678, $02345678, $02345678, $02345678, $12345678, $12345678, $12345678),
+      ($00000000, $00000001, $00000001, $00000001, $00000001, $00000001, $00000021, $00000021, $00000021, $00000121, $00000321, $00000321, $00000321, $00000321, $00000321, $00004321, $00004321, $00014321, $00014321, $00054321, $00054321, $00054321, $00254321, $00654321, $00654321, $01654321, $03654321, $07654321, $07654321, $07654321, $07654321, $07654321)
+    );
+
+var
+  X: Byte;
+  Y: Integer;
+  Output: LongInt;
+begin
+  for Y := Low(Inputs) to High(Inputs) do
+    for X := 0 to 31 do
+      begin
+	    Output := Inputs[Y];
+		MaskOut(Output, X);
+		if Output <> Expected[Y][X] then
+		  begin
+		    WriteLn('FAIL: $', HexStr(Inputs[Y], 8), ' and ((1 shl ', X, ') - 1) returned $', HexStr(Output, 8), '; expected $', HexStr(Expected[Y][X], 8));
+		    Halt(1);
+		  end;
+	  end;
+
+  WriteLn('ok');
+end.

+ 38 - 0
tests/test/cg/tbzhi1e.pp

@@ -0,0 +1,38 @@
+{ %CPU=i386,x86_64 }
+{ %OPT=-O3 -CpCOREAVX2 -OpCOREAVX2 }
+
+program tbzhi1e;
+
+function MaskOut(Input: LongInt; Index: Int64): LongInt; noinline;
+begin
+  MaskOut := Input and ((1 shl Index) - 1);
+end;
+
+const
+  Inputs:  array[0..3] of LongInt = (0, $FFFFFFFF, $12345678, $87654321);
+  Expected: array[0..3] of array[0..31] of LongInt =
+    (
+      ($00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000),
+      ($00000000, $00000001, $00000003, $00000007, $0000000F, $0000001F, $0000003F, $0000007F, $000000FF, $000001FF, $000003FF, $000007FF, $00000FFF, $00001FFF, $00003FFF, $00007FFF, $0000FFFF, $0001FFFF, $0003FFFF, $0007FFFF, $000FFFFF, $001FFFFF, $003FFFFF, $007FFFFF, $00FFFFFF, $01FFFFFF, $03FFFFFF, $07FFFFFF, $0FFFFFFF, $1FFFFFFF, $3FFFFFFF, $7FFFFFFF),
+      ($00000000, $00000000, $00000000, $00000000, $00000008, $00000018, $00000038, $00000078, $00000078, $00000078, $00000278, $00000678, $00000678, $00001678, $00001678, $00005678, $00005678, $00005678, $00005678, $00045678, $00045678, $00145678, $00345678, $00345678, $00345678, $00345678, $02345678, $02345678, $02345678, $12345678, $12345678, $12345678),
+      ($00000000, $00000001, $00000001, $00000001, $00000001, $00000001, $00000021, $00000021, $00000021, $00000121, $00000321, $00000321, $00000321, $00000321, $00000321, $00004321, $00004321, $00014321, $00014321, $00054321, $00054321, $00054321, $00254321, $00654321, $00654321, $01654321, $03654321, $07654321, $07654321, $07654321, $07654321, $07654321)
+    );
+
+var
+  X: Byte;
+  Y: Integer;
+  Output: LongInt;
+begin
+  for Y := Low(Inputs) to High(Inputs) do
+    for X := 0 to 31 do
+      begin
+	    Output := MaskOut(Inputs[Y], X);
+		if Output <> Expected[Y][X] then
+		  begin
+		    WriteLn('FAIL: $', HexStr(Inputs[Y], 8), ' and ((1 shl ', X, ') - 1) returned $', HexStr(Output, 8), '; expected $', HexStr(Expected[Y][X], 8));
+		    Halt(1);
+		  end;
+	  end;
+
+  WriteLn('ok');
+end.

+ 38 - 0
tests/test/cg/tbzhi1f.pp

@@ -0,0 +1,38 @@
+{ %CPU=i386,x86_64 }
+{ %OPT=-O3 -CpCOREAVX2 -OpCOREAVX2 }
+
+program tbzhi1f;
+
+function MaskOut(var Input: LongInt; Index: Int64): LongInt; noinline;
+begin
+  MaskOut := Input and ((1 shl Index) - 1);
+end;
+
+const
+  Inputs:  array[0..3] of LongInt = (0, $FFFFFFFF, $12345678, $87654321);
+  Expected: array[0..3] of array[0..31] of LongInt =
+    (
+      ($00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000),
+      ($00000000, $00000001, $00000003, $00000007, $0000000F, $0000001F, $0000003F, $0000007F, $000000FF, $000001FF, $000003FF, $000007FF, $00000FFF, $00001FFF, $00003FFF, $00007FFF, $0000FFFF, $0001FFFF, $0003FFFF, $0007FFFF, $000FFFFF, $001FFFFF, $003FFFFF, $007FFFFF, $00FFFFFF, $01FFFFFF, $03FFFFFF, $07FFFFFF, $0FFFFFFF, $1FFFFFFF, $3FFFFFFF, $7FFFFFFF),
+      ($00000000, $00000000, $00000000, $00000000, $00000008, $00000018, $00000038, $00000078, $00000078, $00000078, $00000278, $00000678, $00000678, $00001678, $00001678, $00005678, $00005678, $00005678, $00005678, $00045678, $00045678, $00145678, $00345678, $00345678, $00345678, $00345678, $02345678, $02345678, $02345678, $12345678, $12345678, $12345678),
+      ($00000000, $00000001, $00000001, $00000001, $00000001, $00000001, $00000021, $00000021, $00000021, $00000121, $00000321, $00000321, $00000321, $00000321, $00000321, $00004321, $00004321, $00014321, $00014321, $00054321, $00054321, $00054321, $00254321, $00654321, $00654321, $01654321, $03654321, $07654321, $07654321, $07654321, $07654321, $07654321)
+    );
+
+var
+  X: Byte;
+  Y: Integer;
+  Output: LongInt;
+begin
+  for Y := Low(Inputs) to High(Inputs) do
+    for X := 0 to 31 do
+      begin
+	    Output := MaskOut(Inputs[Y], X);
+		if Output <> Expected[Y][X] then
+		  begin
+		    WriteLn('FAIL: $', HexStr(Inputs[Y], 8), ' and ((1 shl ', X, ') - 1) returned $', HexStr(Output, 8), '; expected $', HexStr(Expected[Y][X], 8));
+		    Halt(1);
+		  end;
+	  end;
+
+  WriteLn('ok');
+end.

+ 39 - 0
tests/test/cg/tbzhi1g.pp

@@ -0,0 +1,39 @@
+{ %CPU=i386,x86_64 }
+{ %OPT=-O3 -CpCOREAVX2 -OpCOREAVX2 }
+
+program tbzhi1g;
+
+procedure MaskOut(var InOut: LongInt; Index: Int64); noinline;
+begin
+  InOut := InOut and ((1 shl Index) - 1);
+end;
+
+const
+  Inputs:  array[0..3] of LongInt = (0, $FFFFFFFF, $12345678, $87654321);
+  Expected: array[0..3] of array[0..31] of LongInt =
+    (
+      ($00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000, $00000000),
+      ($00000000, $00000001, $00000003, $00000007, $0000000F, $0000001F, $0000003F, $0000007F, $000000FF, $000001FF, $000003FF, $000007FF, $00000FFF, $00001FFF, $00003FFF, $00007FFF, $0000FFFF, $0001FFFF, $0003FFFF, $0007FFFF, $000FFFFF, $001FFFFF, $003FFFFF, $007FFFFF, $00FFFFFF, $01FFFFFF, $03FFFFFF, $07FFFFFF, $0FFFFFFF, $1FFFFFFF, $3FFFFFFF, $7FFFFFFF),
+      ($00000000, $00000000, $00000000, $00000000, $00000008, $00000018, $00000038, $00000078, $00000078, $00000078, $00000278, $00000678, $00000678, $00001678, $00001678, $00005678, $00005678, $00005678, $00005678, $00045678, $00045678, $00145678, $00345678, $00345678, $00345678, $00345678, $02345678, $02345678, $02345678, $12345678, $12345678, $12345678),
+      ($00000000, $00000001, $00000001, $00000001, $00000001, $00000001, $00000021, $00000021, $00000021, $00000121, $00000321, $00000321, $00000321, $00000321, $00000321, $00004321, $00004321, $00014321, $00014321, $00054321, $00054321, $00054321, $00254321, $00654321, $00654321, $01654321, $03654321, $07654321, $07654321, $07654321, $07654321, $07654321)
+    );
+
+var
+  X: Byte;
+  Y: Integer;
+  Output: LongInt;
+begin
+  for Y := Low(Inputs) to High(Inputs) do
+    for X := 0 to 31 do
+      begin
+	    Output := Inputs[Y];
+		MaskOut(Output, X);
+		if Output <> Expected[Y][X] then
+		  begin
+		    WriteLn('FAIL: $', HexStr(Inputs[Y], 8), ' and ((1 shl ', X, ') - 1) returned $', HexStr(Output, 8), '; expected $', HexStr(Expected[Y][X], 8));
+		    Halt(1);
+		  end;
+	  end;
+
+  WriteLn('ok');
+end.

+ 38 - 0
tests/test/cg/tbzhi2.pp

@@ -0,0 +1,38 @@
+{ %CPU=i386,x86_64 }
+{ %OPT=-O3 -CpCOREAVX2 -OpCOREAVX2 }
+
+program tbzhi2;
+
+function MaskOut(Input: Int64; Index: Byte): Int64; noinline;
+begin
+  MaskOut := Input and ((Int64(1) shl Index) - 1);
+end;
+
+const
+  Inputs:  array[0..3] of Int64 = (0, $FFFFFFFFFFFFFFFF, $0123456789ABCDEF, $FEDCBA9876543210);
+  Expected: array[0..3] of array[0..63] of Int64 =
+    (
+      ($0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000),
+      ($0000000000000000, $0000000000000001, $0000000000000003, $0000000000000007, $000000000000000F, $000000000000001F, $000000000000003F, $000000000000007F, $00000000000000FF, $00000000000001FF, $00000000000003FF, $00000000000007FF, $0000000000000FFF, $0000000000001FFF, $0000000000003FFF, $0000000000007FFF, $000000000000FFFF, $000000000001FFFF, $000000000003FFFF, $000000000007FFFF, $00000000000FFFFF, $00000000001FFFFF, $00000000003FFFFF, $00000000007FFFFF, $0000000000FFFFFF, $0000000001FFFFFF, $0000000003FFFFFF, $0000000007FFFFFF, $000000000FFFFFFF, $000000001FFFFFFF, $000000003FFFFFFF, $000000007FFFFFFF, $00000000FFFFFFFF, $00000001FFFFFFFF, $00000003FFFFFFFF, $00000007FFFFFFFF, $0000000FFFFFFFFF, $0000001FFFFFFFFF, $0000003FFFFFFFFF, $0000007FFFFFFFFF, $000000FFFFFFFFFF, $000001FFFFFFFFFF, $000003FFFFFFFFFF, $000007FFFFFFFFFF, $00000FFFFFFFFFFF, $00001FFFFFFFFFFF, $00003FFFFFFFFFFF, $00007FFFFFFFFFFF, $0000FFFFFFFFFFFF, $0001FFFFFFFFFFFF, $0003FFFFFFFFFFFF, $0007FFFFFFFFFFFF, $000FFFFFFFFFFFFF, $001FFFFFFFFFFFFF, $003FFFFFFFFFFFFF, $007FFFFFFFFFFFFF, $00FFFFFFFFFFFFFF, $01FFFFFFFFFFFFFF, $03FFFFFFFFFFFFFF, $07FFFFFFFFFFFFFF, $0FFFFFFFFFFFFFFF, $1FFFFFFFFFFFFFFF, $3FFFFFFFFFFFFFFF, $7FFFFFFFFFFFFFFF),
+      ($0000000000000000, $0000000000000001, $0000000000000003, $0000000000000007, $000000000000000F, $000000000000000F, $000000000000002F, $000000000000006F, $00000000000000EF, $00000000000001EF, $00000000000001EF, $00000000000005EF, $0000000000000DEF, $0000000000000DEF, $0000000000000DEF, $0000000000004DEF, $000000000000CDEF, $000000000001CDEF, $000000000003CDEF, $000000000003CDEF, $00000000000BCDEF, $00000000000BCDEF, $00000000002BCDEF, $00000000002BCDEF, $0000000000ABCDEF, $0000000001ABCDEF, $0000000001ABCDEF, $0000000001ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000089ABCDEF, $0000000189ABCDEF, $0000000389ABCDEF, $0000000789ABCDEF, $0000000789ABCDEF, $0000000789ABCDEF, $0000002789ABCDEF, $0000006789ABCDEF, $0000006789ABCDEF, $0000016789ABCDEF, $0000016789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000456789ABCDEF, $0000456789ABCDEF, $0001456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0023456789ABCDEF, $0023456789ABCDEF, $0023456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF),
+      ($0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000210, $0000000000000210, $0000000000000210, $0000000000001210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000043210, $0000000000043210, $0000000000143210, $0000000000143210, $0000000000543210, $0000000000543210, $0000000000543210, $0000000002543210, $0000000006543210, $0000000006543210, $0000000016543210, $0000000036543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000876543210, $0000001876543210, $0000001876543210, $0000001876543210, $0000009876543210, $0000009876543210, $0000029876543210, $0000029876543210, $00000A9876543210, $00001A9876543210, $00003A9876543210, $00003A9876543210, $0000BA9876543210, $0000BA9876543210, $0000BA9876543210, $0004BA9876543210, $000CBA9876543210, $001CBA9876543210, $001CBA9876543210, $005CBA9876543210, $00DCBA9876543210, $00DCBA9876543210, $02DCBA9876543210, $06DCBA9876543210, $0EDCBA9876543210, $1EDCBA9876543210, $3EDCBA9876543210, $7EDCBA9876543210)
+    );
+
+var
+  X: Byte;
+  Y: Integer;
+  Output: Int64;
+begin
+  for Y := Low(Inputs) to High(Inputs) do
+    for X := 0 to 63 do
+      begin
+	    Output := MaskOut(Inputs[Y], X);
+		if Output <> Expected[Y][X] then
+		  begin
+		    WriteLn('FAIL: $', HexStr(Inputs[Y], 16), ' and ((1 shl ', X, ') - 1) returned $', HexStr(Output, 16), '; expected $', HexStr(Expected[Y][X], 16));
+		    Halt(1);
+		  end;
+	  end;
+
+  WriteLn('ok');
+end.

+ 38 - 0
tests/test/cg/tbzhi2a.pp

@@ -0,0 +1,38 @@
+{ %CPU=i386,x86_64 }
+{ %OPT=-O3 -CpCOREAVX2 -OpCOREAVX2 }
+
+program tbzhi2a;
+
+function MaskOut(Input, Index: Int64): Int64; noinline;
+begin
+  MaskOut := Input and ((Int64(1) shl Index) - 1);
+end;
+
+const
+  Inputs:  array[0..3] of Int64 = (0, $FFFFFFFFFFFFFFFF, $0123456789ABCDEF, $FEDCBA9876543210);
+  Expected: array[0..3] of array[0..63] of Int64 =
+    (
+      ($0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000),
+      ($0000000000000000, $0000000000000001, $0000000000000003, $0000000000000007, $000000000000000F, $000000000000001F, $000000000000003F, $000000000000007F, $00000000000000FF, $00000000000001FF, $00000000000003FF, $00000000000007FF, $0000000000000FFF, $0000000000001FFF, $0000000000003FFF, $0000000000007FFF, $000000000000FFFF, $000000000001FFFF, $000000000003FFFF, $000000000007FFFF, $00000000000FFFFF, $00000000001FFFFF, $00000000003FFFFF, $00000000007FFFFF, $0000000000FFFFFF, $0000000001FFFFFF, $0000000003FFFFFF, $0000000007FFFFFF, $000000000FFFFFFF, $000000001FFFFFFF, $000000003FFFFFFF, $000000007FFFFFFF, $00000000FFFFFFFF, $00000001FFFFFFFF, $00000003FFFFFFFF, $00000007FFFFFFFF, $0000000FFFFFFFFF, $0000001FFFFFFFFF, $0000003FFFFFFFFF, $0000007FFFFFFFFF, $000000FFFFFFFFFF, $000001FFFFFFFFFF, $000003FFFFFFFFFF, $000007FFFFFFFFFF, $00000FFFFFFFFFFF, $00001FFFFFFFFFFF, $00003FFFFFFFFFFF, $00007FFFFFFFFFFF, $0000FFFFFFFFFFFF, $0001FFFFFFFFFFFF, $0003FFFFFFFFFFFF, $0007FFFFFFFFFFFF, $000FFFFFFFFFFFFF, $001FFFFFFFFFFFFF, $003FFFFFFFFFFFFF, $007FFFFFFFFFFFFF, $00FFFFFFFFFFFFFF, $01FFFFFFFFFFFFFF, $03FFFFFFFFFFFFFF, $07FFFFFFFFFFFFFF, $0FFFFFFFFFFFFFFF, $1FFFFFFFFFFFFFFF, $3FFFFFFFFFFFFFFF, $7FFFFFFFFFFFFFFF),
+      ($0000000000000000, $0000000000000001, $0000000000000003, $0000000000000007, $000000000000000F, $000000000000000F, $000000000000002F, $000000000000006F, $00000000000000EF, $00000000000001EF, $00000000000001EF, $00000000000005EF, $0000000000000DEF, $0000000000000DEF, $0000000000000DEF, $0000000000004DEF, $000000000000CDEF, $000000000001CDEF, $000000000003CDEF, $000000000003CDEF, $00000000000BCDEF, $00000000000BCDEF, $00000000002BCDEF, $00000000002BCDEF, $0000000000ABCDEF, $0000000001ABCDEF, $0000000001ABCDEF, $0000000001ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000089ABCDEF, $0000000189ABCDEF, $0000000389ABCDEF, $0000000789ABCDEF, $0000000789ABCDEF, $0000000789ABCDEF, $0000002789ABCDEF, $0000006789ABCDEF, $0000006789ABCDEF, $0000016789ABCDEF, $0000016789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000456789ABCDEF, $0000456789ABCDEF, $0001456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0023456789ABCDEF, $0023456789ABCDEF, $0023456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF),
+      ($0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000210, $0000000000000210, $0000000000000210, $0000000000001210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000043210, $0000000000043210, $0000000000143210, $0000000000143210, $0000000000543210, $0000000000543210, $0000000000543210, $0000000002543210, $0000000006543210, $0000000006543210, $0000000016543210, $0000000036543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000876543210, $0000001876543210, $0000001876543210, $0000001876543210, $0000009876543210, $0000009876543210, $0000029876543210, $0000029876543210, $00000A9876543210, $00001A9876543210, $00003A9876543210, $00003A9876543210, $0000BA9876543210, $0000BA9876543210, $0000BA9876543210, $0004BA9876543210, $000CBA9876543210, $001CBA9876543210, $001CBA9876543210, $005CBA9876543210, $00DCBA9876543210, $00DCBA9876543210, $02DCBA9876543210, $06DCBA9876543210, $0EDCBA9876543210, $1EDCBA9876543210, $3EDCBA9876543210, $7EDCBA9876543210)
+    );
+
+var
+  X: Byte;
+  Y: Integer;
+  Output: Int64;
+begin
+  for Y := Low(Inputs) to High(Inputs) do
+    for X := 0 to 63 do
+      begin
+	    Output := MaskOut(Inputs[Y], X);
+		if Output <> Expected[Y][X] then
+		  begin
+		    WriteLn('FAIL: $', HexStr(Inputs[Y], 16), ' and ((1 shl ', X, ') - 1) returned $', HexStr(Output, 16), '; expected $', HexStr(Expected[Y][X], 16));
+		    Halt(1);
+		  end;
+	  end;
+
+  WriteLn('ok');
+end.

+ 38 - 0
tests/test/cg/tbzhi2b.pp

@@ -0,0 +1,38 @@
+{ %CPU=i386,x86_64 }
+{ %OPT=-O3 -CpCOREAVX2 -OpCOREAVX2 }
+
+program tbzhi2b;
+
+function MaskOut(var InOut: Int64; Index: Byte): Int64; noinline;
+begin
+  MaskOut := InOut and ((Int64(1) shl Index) - 1);
+end;
+
+const
+  Inputs:  array[0..3] of Int64 = (0, $FFFFFFFFFFFFFFFF, $0123456789ABCDEF, $FEDCBA9876543210);
+  Expected: array[0..3] of array[0..63] of Int64 =
+    (
+      ($0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000),
+      ($0000000000000000, $0000000000000001, $0000000000000003, $0000000000000007, $000000000000000F, $000000000000001F, $000000000000003F, $000000000000007F, $00000000000000FF, $00000000000001FF, $00000000000003FF, $00000000000007FF, $0000000000000FFF, $0000000000001FFF, $0000000000003FFF, $0000000000007FFF, $000000000000FFFF, $000000000001FFFF, $000000000003FFFF, $000000000007FFFF, $00000000000FFFFF, $00000000001FFFFF, $00000000003FFFFF, $00000000007FFFFF, $0000000000FFFFFF, $0000000001FFFFFF, $0000000003FFFFFF, $0000000007FFFFFF, $000000000FFFFFFF, $000000001FFFFFFF, $000000003FFFFFFF, $000000007FFFFFFF, $00000000FFFFFFFF, $00000001FFFFFFFF, $00000003FFFFFFFF, $00000007FFFFFFFF, $0000000FFFFFFFFF, $0000001FFFFFFFFF, $0000003FFFFFFFFF, $0000007FFFFFFFFF, $000000FFFFFFFFFF, $000001FFFFFFFFFF, $000003FFFFFFFFFF, $000007FFFFFFFFFF, $00000FFFFFFFFFFF, $00001FFFFFFFFFFF, $00003FFFFFFFFFFF, $00007FFFFFFFFFFF, $0000FFFFFFFFFFFF, $0001FFFFFFFFFFFF, $0003FFFFFFFFFFFF, $0007FFFFFFFFFFFF, $000FFFFFFFFFFFFF, $001FFFFFFFFFFFFF, $003FFFFFFFFFFFFF, $007FFFFFFFFFFFFF, $00FFFFFFFFFFFFFF, $01FFFFFFFFFFFFFF, $03FFFFFFFFFFFFFF, $07FFFFFFFFFFFFFF, $0FFFFFFFFFFFFFFF, $1FFFFFFFFFFFFFFF, $3FFFFFFFFFFFFFFF, $7FFFFFFFFFFFFFFF),
+      ($0000000000000000, $0000000000000001, $0000000000000003, $0000000000000007, $000000000000000F, $000000000000000F, $000000000000002F, $000000000000006F, $00000000000000EF, $00000000000001EF, $00000000000001EF, $00000000000005EF, $0000000000000DEF, $0000000000000DEF, $0000000000000DEF, $0000000000004DEF, $000000000000CDEF, $000000000001CDEF, $000000000003CDEF, $000000000003CDEF, $00000000000BCDEF, $00000000000BCDEF, $00000000002BCDEF, $00000000002BCDEF, $0000000000ABCDEF, $0000000001ABCDEF, $0000000001ABCDEF, $0000000001ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000089ABCDEF, $0000000189ABCDEF, $0000000389ABCDEF, $0000000789ABCDEF, $0000000789ABCDEF, $0000000789ABCDEF, $0000002789ABCDEF, $0000006789ABCDEF, $0000006789ABCDEF, $0000016789ABCDEF, $0000016789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000456789ABCDEF, $0000456789ABCDEF, $0001456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0023456789ABCDEF, $0023456789ABCDEF, $0023456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF),
+      ($0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000210, $0000000000000210, $0000000000000210, $0000000000001210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000043210, $0000000000043210, $0000000000143210, $0000000000143210, $0000000000543210, $0000000000543210, $0000000000543210, $0000000002543210, $0000000006543210, $0000000006543210, $0000000016543210, $0000000036543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000876543210, $0000001876543210, $0000001876543210, $0000001876543210, $0000009876543210, $0000009876543210, $0000029876543210, $0000029876543210, $00000A9876543210, $00001A9876543210, $00003A9876543210, $00003A9876543210, $0000BA9876543210, $0000BA9876543210, $0000BA9876543210, $0004BA9876543210, $000CBA9876543210, $001CBA9876543210, $001CBA9876543210, $005CBA9876543210, $00DCBA9876543210, $00DCBA9876543210, $02DCBA9876543210, $06DCBA9876543210, $0EDCBA9876543210, $1EDCBA9876543210, $3EDCBA9876543210, $7EDCBA9876543210)
+    );
+
+var
+  X: Byte;
+  Y: Integer;
+  Output: Int64;
+begin
+  for Y := Low(Inputs) to High(Inputs) do
+    for X := 0 to 63 do
+      begin
+	    Output := MaskOut(Inputs[Y], X);
+		if Output <> Expected[Y][X] then
+		  begin
+		    WriteLn('FAIL: $', HexStr(Inputs[Y], 16), ' and ((1 shl ', X, ') - 1) returned $', HexStr(Output, 16), '; expected $', HexStr(Expected[Y][X], 16));
+		    Halt(1);
+		  end;
+	  end;
+
+  WriteLn('ok');
+end.

+ 39 - 0
tests/test/cg/tbzhi2c.pp

@@ -0,0 +1,39 @@
+{ %CPU=i386,x86_64 }
+{ %OPT=-O3 -CpCOREAVX2 -OpCOREAVX2 }
+
+program tbzhi2d;
+
+procedure MaskOut(var InOut: Int64; Index: Byte); noinline;
+begin
+  InOut := InOut and ((Int64(1) shl Index) - 1);
+end;
+
+const
+  Inputs:  array[0..3] of Int64 = (0, $FFFFFFFFFFFFFFFF, $0123456789ABCDEF, $FEDCBA9876543210);
+  Expected: array[0..3] of array[0..63] of Int64 =
+    (
+      ($0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000),
+      ($0000000000000000, $0000000000000001, $0000000000000003, $0000000000000007, $000000000000000F, $000000000000001F, $000000000000003F, $000000000000007F, $00000000000000FF, $00000000000001FF, $00000000000003FF, $00000000000007FF, $0000000000000FFF, $0000000000001FFF, $0000000000003FFF, $0000000000007FFF, $000000000000FFFF, $000000000001FFFF, $000000000003FFFF, $000000000007FFFF, $00000000000FFFFF, $00000000001FFFFF, $00000000003FFFFF, $00000000007FFFFF, $0000000000FFFFFF, $0000000001FFFFFF, $0000000003FFFFFF, $0000000007FFFFFF, $000000000FFFFFFF, $000000001FFFFFFF, $000000003FFFFFFF, $000000007FFFFFFF, $00000000FFFFFFFF, $00000001FFFFFFFF, $00000003FFFFFFFF, $00000007FFFFFFFF, $0000000FFFFFFFFF, $0000001FFFFFFFFF, $0000003FFFFFFFFF, $0000007FFFFFFFFF, $000000FFFFFFFFFF, $000001FFFFFFFFFF, $000003FFFFFFFFFF, $000007FFFFFFFFFF, $00000FFFFFFFFFFF, $00001FFFFFFFFFFF, $00003FFFFFFFFFFF, $00007FFFFFFFFFFF, $0000FFFFFFFFFFFF, $0001FFFFFFFFFFFF, $0003FFFFFFFFFFFF, $0007FFFFFFFFFFFF, $000FFFFFFFFFFFFF, $001FFFFFFFFFFFFF, $003FFFFFFFFFFFFF, $007FFFFFFFFFFFFF, $00FFFFFFFFFFFFFF, $01FFFFFFFFFFFFFF, $03FFFFFFFFFFFFFF, $07FFFFFFFFFFFFFF, $0FFFFFFFFFFFFFFF, $1FFFFFFFFFFFFFFF, $3FFFFFFFFFFFFFFF, $7FFFFFFFFFFFFFFF),
+      ($0000000000000000, $0000000000000001, $0000000000000003, $0000000000000007, $000000000000000F, $000000000000000F, $000000000000002F, $000000000000006F, $00000000000000EF, $00000000000001EF, $00000000000001EF, $00000000000005EF, $0000000000000DEF, $0000000000000DEF, $0000000000000DEF, $0000000000004DEF, $000000000000CDEF, $000000000001CDEF, $000000000003CDEF, $000000000003CDEF, $00000000000BCDEF, $00000000000BCDEF, $00000000002BCDEF, $00000000002BCDEF, $0000000000ABCDEF, $0000000001ABCDEF, $0000000001ABCDEF, $0000000001ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000089ABCDEF, $0000000189ABCDEF, $0000000389ABCDEF, $0000000789ABCDEF, $0000000789ABCDEF, $0000000789ABCDEF, $0000002789ABCDEF, $0000006789ABCDEF, $0000006789ABCDEF, $0000016789ABCDEF, $0000016789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000456789ABCDEF, $0000456789ABCDEF, $0001456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0023456789ABCDEF, $0023456789ABCDEF, $0023456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF),
+      ($0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000210, $0000000000000210, $0000000000000210, $0000000000001210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000043210, $0000000000043210, $0000000000143210, $0000000000143210, $0000000000543210, $0000000000543210, $0000000000543210, $0000000002543210, $0000000006543210, $0000000006543210, $0000000016543210, $0000000036543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000876543210, $0000001876543210, $0000001876543210, $0000001876543210, $0000009876543210, $0000009876543210, $0000029876543210, $0000029876543210, $00000A9876543210, $00001A9876543210, $00003A9876543210, $00003A9876543210, $0000BA9876543210, $0000BA9876543210, $0000BA9876543210, $0004BA9876543210, $000CBA9876543210, $001CBA9876543210, $001CBA9876543210, $005CBA9876543210, $00DCBA9876543210, $00DCBA9876543210, $02DCBA9876543210, $06DCBA9876543210, $0EDCBA9876543210, $1EDCBA9876543210, $3EDCBA9876543210, $7EDCBA9876543210)
+    );
+
+var
+  X: Byte;
+  Y: Integer;
+  Output: Int64;
+begin
+  for Y := Low(Inputs) to High(Inputs) do
+    for X := 0 to 63 do
+      begin
+	    Output := Inputs[Y];
+		MaskOut(Output, X);
+		if Output <> Expected[Y][X] then
+		  begin
+		    WriteLn('FAIL: $', HexStr(Inputs[Y], 16), ' and ((1 shl ', X, ') - 1) returned $', HexStr(Output, 16), '; expected $', HexStr(Expected[Y][X], 16));
+		    Halt(1);
+		  end;
+	  end;
+
+  WriteLn('ok');
+end.

+ 39 - 0
tests/test/cg/tbzhi2d.pp

@@ -0,0 +1,39 @@
+{ %CPU=i386,x86_64 }
+{ %OPT=-O3 -CpCOREAVX2 -OpCOREAVX2 }
+
+program tbzhi2d;
+
+procedure MaskOut(var InOut: Int64; Index: Int64); noinline;
+begin
+  InOut := InOut and ((Int64(1) shl Index) - 1);
+end;
+
+const
+  Inputs:  array[0..3] of Int64 = (0, $FFFFFFFFFFFFFFFF, $0123456789ABCDEF, $FEDCBA9876543210);
+  Expected: array[0..3] of array[0..63] of Int64 =
+    (
+      ($0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000),
+      ($0000000000000000, $0000000000000001, $0000000000000003, $0000000000000007, $000000000000000F, $000000000000001F, $000000000000003F, $000000000000007F, $00000000000000FF, $00000000000001FF, $00000000000003FF, $00000000000007FF, $0000000000000FFF, $0000000000001FFF, $0000000000003FFF, $0000000000007FFF, $000000000000FFFF, $000000000001FFFF, $000000000003FFFF, $000000000007FFFF, $00000000000FFFFF, $00000000001FFFFF, $00000000003FFFFF, $00000000007FFFFF, $0000000000FFFFFF, $0000000001FFFFFF, $0000000003FFFFFF, $0000000007FFFFFF, $000000000FFFFFFF, $000000001FFFFFFF, $000000003FFFFFFF, $000000007FFFFFFF, $00000000FFFFFFFF, $00000001FFFFFFFF, $00000003FFFFFFFF, $00000007FFFFFFFF, $0000000FFFFFFFFF, $0000001FFFFFFFFF, $0000003FFFFFFFFF, $0000007FFFFFFFFF, $000000FFFFFFFFFF, $000001FFFFFFFFFF, $000003FFFFFFFFFF, $000007FFFFFFFFFF, $00000FFFFFFFFFFF, $00001FFFFFFFFFFF, $00003FFFFFFFFFFF, $00007FFFFFFFFFFF, $0000FFFFFFFFFFFF, $0001FFFFFFFFFFFF, $0003FFFFFFFFFFFF, $0007FFFFFFFFFFFF, $000FFFFFFFFFFFFF, $001FFFFFFFFFFFFF, $003FFFFFFFFFFFFF, $007FFFFFFFFFFFFF, $00FFFFFFFFFFFFFF, $01FFFFFFFFFFFFFF, $03FFFFFFFFFFFFFF, $07FFFFFFFFFFFFFF, $0FFFFFFFFFFFFFFF, $1FFFFFFFFFFFFFFF, $3FFFFFFFFFFFFFFF, $7FFFFFFFFFFFFFFF),
+      ($0000000000000000, $0000000000000001, $0000000000000003, $0000000000000007, $000000000000000F, $000000000000000F, $000000000000002F, $000000000000006F, $00000000000000EF, $00000000000001EF, $00000000000001EF, $00000000000005EF, $0000000000000DEF, $0000000000000DEF, $0000000000000DEF, $0000000000004DEF, $000000000000CDEF, $000000000001CDEF, $000000000003CDEF, $000000000003CDEF, $00000000000BCDEF, $00000000000BCDEF, $00000000002BCDEF, $00000000002BCDEF, $0000000000ABCDEF, $0000000001ABCDEF, $0000000001ABCDEF, $0000000001ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000009ABCDEF, $0000000089ABCDEF, $0000000189ABCDEF, $0000000389ABCDEF, $0000000789ABCDEF, $0000000789ABCDEF, $0000000789ABCDEF, $0000002789ABCDEF, $0000006789ABCDEF, $0000006789ABCDEF, $0000016789ABCDEF, $0000016789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000056789ABCDEF, $0000456789ABCDEF, $0000456789ABCDEF, $0001456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0003456789ABCDEF, $0023456789ABCDEF, $0023456789ABCDEF, $0023456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF, $0123456789ABCDEF),
+      ($0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000000, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000010, $0000000000000210, $0000000000000210, $0000000000000210, $0000000000001210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000003210, $0000000000043210, $0000000000043210, $0000000000143210, $0000000000143210, $0000000000543210, $0000000000543210, $0000000000543210, $0000000002543210, $0000000006543210, $0000000006543210, $0000000016543210, $0000000036543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000076543210, $0000000876543210, $0000001876543210, $0000001876543210, $0000001876543210, $0000009876543210, $0000009876543210, $0000029876543210, $0000029876543210, $00000A9876543210, $00001A9876543210, $00003A9876543210, $00003A9876543210, $0000BA9876543210, $0000BA9876543210, $0000BA9876543210, $0004BA9876543210, $000CBA9876543210, $001CBA9876543210, $001CBA9876543210, $005CBA9876543210, $00DCBA9876543210, $00DCBA9876543210, $02DCBA9876543210, $06DCBA9876543210, $0EDCBA9876543210, $1EDCBA9876543210, $3EDCBA9876543210, $7EDCBA9876543210)
+    );
+
+var
+  X: Byte;
+  Y: Integer;
+  Output: Int64;
+begin
+  for Y := Low(Inputs) to High(Inputs) do
+    for X := 0 to 63 do
+      begin
+	    Output := Inputs[Y];
+		MaskOut(Output, X);
+		if Output <> Expected[Y][X] then
+		  begin
+		    WriteLn('FAIL: $', HexStr(Inputs[Y], 16), ' and ((1 shl ', X, ') - 1) returned $', HexStr(Output, 16), '; expected $', HexStr(Expected[Y][X], 16));
+		    Halt(1);
+		  end;
+	  end;
+
+  WriteLn('ok');
+end.