+ support for bitpacking types with a negative lower bound

git-svn-id: trunk@6683 -
This commit is contained in:
Jonas Maebe 2007-02-28 17:42:41 +00:00
parent 7925bed48d
commit 615c450062
7 changed files with 411 additions and 90 deletions

1
.gitattributes vendored
View File

@ -6775,6 +6775,7 @@ tests/test/tparray15.pp svneol=native#text/plain
tests/test/tparray16.pp svneol=native#text/plain
tests/test/tparray17.pp svneol=native#text/plain
tests/test/tparray18.pp svneol=native#text/plain
tests/test/tparray19.pp svneol=native#text/plain
tests/test/tparray2.pp svneol=native#text/plain
tests/test/tparray3.pp svneol=native#text/plain
tests/test/tparray4.pp svneol=native#text/plain

View File

@ -917,10 +917,12 @@ implementation
{$ifopt r+}
{$define rangeon}
{$r-}
{$endif}
{$ifopt q+}
{$define overflowon}
{$q-}
{$endif}
procedure tcg.a_load_subsetreg_reg(list : TAsmList; subsetsize, tosize: tcgsize; const sreg: tsubsetregister; destreg: tregister);
@ -930,15 +932,25 @@ implementation
stopbit: byte;
begin
tmpreg:=getintregister(list,sreg.subsetregsize);
a_op_const_reg_reg(list,OP_SHR,sreg.subsetregsize,sreg.startbit,sreg.subsetreg,tmpreg);
stopbit := sreg.startbit + sreg.bitlen;
// on x86(64), 1 shl 32(64) = 1 instead of 0
// use aword to prevent overflow with 1 shl 31
if (stopbit - sreg.startbit <> AIntBits) then
bitmask := (aword(1) shl (stopbit - sreg.startbit)) - 1
if (subsetsize in [OS_S8..OS_S128]) then
begin
{ sign extend in case the value has a bitsize mod 8 <> 0 }
{ both instructions will be optimized away if not }
a_op_const_reg_reg(list,OP_SHL,sreg.subsetregsize,(tcgsize2size[sreg.subsetregsize]*8)-sreg.startbit-sreg.bitlen,sreg.subsetreg,tmpreg);
a_op_const_reg(list,OP_SAR,sreg.subsetregsize,(tcgsize2size[sreg.subsetregsize]*8)-sreg.bitlen,tmpreg);
end
else
bitmask := high(aword);
a_op_const_reg(list,OP_AND,sreg.subsetregsize,aint(bitmask),tmpreg);
begin
a_op_const_reg_reg(list,OP_SHR,sreg.subsetregsize,sreg.startbit,sreg.subsetreg,tmpreg);
stopbit := sreg.startbit + sreg.bitlen;
// on x86(64), 1 shl 32(64) = 1 instead of 0
// use aword to prevent overflow with 1 shl 31
if (stopbit - sreg.startbit <> AIntBits) then
bitmask := (aword(1) shl (stopbit - sreg.startbit)) - 1
else
bitmask := high(aword);
a_op_const_reg(list,OP_AND,sreg.subsetregsize,aint(bitmask),tmpreg);
end;
tmpreg := makeregsize(list,tmpreg,subsetsize);
a_load_reg_reg(list,tcgsize2unsigned[subsetsize],subsetsize,tmpreg,tmpreg);
a_load_reg_reg(list,subsetsize,tosize,tmpreg,destreg);
@ -1081,7 +1093,7 @@ implementation
(*
Subsetrefs are used for (bit)packed arrays and (bit)packed records stored
in memory. They are like a regular reference, but contain an extra bit
offset (either constant -startbit- or variable -bitindexreg, always OS_INT)
offset (either constant -startbit- or variable -bitindexreg-, always OS_INT)
and a bit length (always constant).
Bit packed values are stored differently in memory depending on whether we
@ -1101,7 +1113,7 @@ implementation
the right, but the bits in the next byte are all more significant than
those in the previous byte (e.g., the 222 in the first byte are the low
three bits of that value, while the 22 in the second byte are the upper
three bits.
two bits.
Big endian, 9 bit values:
11111111 12222222 22333333 33344444 ...
@ -1171,20 +1183,37 @@ implementation
begin
{ valuereg contains the upper bits, extra_value_reg the lower }
restbits := (sref.bitlen - (loadbitsize - sref.startbit));
a_op_const_reg(list,OP_SHL,OS_INT,restbits,valuereg);
{ mask other bits }
if (sref.bitlen <> AIntBits) then
a_op_const_reg(list,OP_AND,OS_INT,aint((aword(1) shl sref.bitlen)-1),valuereg);
if (subsetsize in [OS_S8..OS_S128]) then
begin
{ sign extend }
a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-loadbitsize+sref.startbit,valuereg);
a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,valuereg);
end
else
begin
a_op_const_reg(list,OP_SHL,OS_INT,restbits,valuereg);
{ mask other bits }
if (sref.bitlen <> AIntBits) then
a_op_const_reg(list,OP_AND,OS_INT,aint((aword(1) shl sref.bitlen)-1),valuereg);
end;
a_op_const_reg(list,OP_SHR,OS_INT,loadbitsize-restbits,extra_value_reg)
end
else
begin
{ valuereg contains the lower bits, extra_value_reg the upper }
a_op_const_reg(list,OP_SHR,OS_INT,sref.startbit,valuereg);
a_op_const_reg(list,OP_SHL,OS_INT,loadbitsize-sref.startbit,extra_value_reg);
{ mask other bits }
if (sref.bitlen <> AIntBits) then
a_op_const_reg(list,OP_AND,OS_INT,aint((aword(1) shl sref.bitlen)-1),extra_value_reg);
if (subsetsize in [OS_S8..OS_S128]) then
begin
a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-sref.bitlen+loadbitsize-sref.startbit,extra_value_reg);
a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,extra_value_reg);
end
else
begin
a_op_const_reg(list,OP_SHL,OS_INT,loadbitsize-sref.startbit,extra_value_reg);
{ mask other bits }
if (sref.bitlen <> AIntBits) then
a_op_const_reg(list,OP_AND,OS_INT,aint((aword(1) shl sref.bitlen)-1),extra_value_reg);
end;
end;
{ merge }
a_op_reg_reg(list,OP_OR,OS_INT,extra_value_reg,valuereg);
@ -1203,10 +1232,18 @@ implementation
{ get the data in valuereg in the right place }
a_op_reg_reg(list,OP_SHL,OS_INT,sref.bitindexreg,valuereg);
a_op_const_reg(list,OP_SHR,OS_INT,loadbitsize-sref.bitlen,valuereg);
if (loadbitsize <> AIntBits) then
{ mask left over bits }
a_op_const_reg(list,OP_AND,OS_INT,aint((aword(1) shl sref.bitlen)-1),valuereg);
if (subsetsize in [OS_S8..OS_S128]) then
begin
a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-loadbitsize,valuereg);
a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,valuereg)
end
else
begin
a_op_const_reg(list,OP_SHR,OS_INT,loadbitsize-sref.bitlen,valuereg);
if (loadbitsize <> AIntBits) then
{ mask left over bits }
a_op_const_reg(list,OP_AND,OS_INT,aint((aword(1) shl sref.bitlen)-1),valuereg);
end;
tmpreg := getintregister(list,OS_INT);
{ the bits in extra_value_reg (if any) start at the most significant bit => }
{ extra_value_reg must be shr by (loadbitsize-sref.bitlen)+(loadsize-sref.bitindex) }
@ -1245,8 +1282,14 @@ implementation
{$endif x86}
{ merge }
a_op_reg_reg(list,OP_OR,OS_INT,extra_value_reg,valuereg);
{ mask other bits }
a_op_const_reg(list,OP_AND,OS_INT,aint((aword(1) shl sref.bitlen)-1),valuereg);
{ sign extend or mask other bits }
if (subsetsize in [OS_S8..OS_S128]) then
begin
a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-sref.bitlen,valuereg);
a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,valuereg);
end
else
a_op_const_reg(list,OP_AND,OS_INT,aint((aword(1) shl sref.bitlen)-1),valuereg);
end;
end;
@ -1292,12 +1335,27 @@ implementation
if (target_info.endian = endian_big) then
begin
a_op_reg_reg(list,OP_SHL,OS_INT,sref.bitindexreg,valuereg);
a_op_const_reg(list,OP_SHR,OS_INT,loadbitsize-sref.bitlen,valuereg);
if (subsetsize in [OS_S8..OS_S128]) then
begin
{ sign extend to entire register }
a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-loadbitsize,valuereg);
a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,valuereg);
end
else
a_op_const_reg(list,OP_SHR,OS_INT,loadbitsize-sref.bitlen,valuereg);
end
else
a_op_reg_reg(list,OP_SHR,OS_INT,sref.bitindexreg,valuereg);
{ mask other bits }
a_op_const_reg(list,OP_AND,OS_INT,aint((aword(1) shl sref.bitlen)-1),valuereg);
begin
a_op_reg_reg(list,OP_SHR,OS_INT,sref.bitindexreg,valuereg);
if (subsetsize in [OS_S8..OS_S128]) then
begin
a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-sref.bitlen,valuereg);
a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,valuereg);
end
end;
{ mask other bits/sign extend }
if not(subsetsize in [OS_S8..OS_S128]) then
a_op_const_reg(list,OP_AND,OS_INT,aint((aword(1) shl sref.bitlen)-1),valuereg);
end
end
else
@ -1320,22 +1378,11 @@ implementation
end;
{ store in destination }
{ (types with a negative lower bound are always a base type (8, 16, 32, 64 bits) }
if ((sref.bitlen mod 8) = 0) then
begin
{ since we know all necessary bits are already masked, avoid unnecessary }
{ zero-extensions }
valuereg := makeregsize(list,valuereg,tosize);
a_load_reg_reg(list,tcgsize2unsigned[tosize],tosize,valuereg,destreg)
end
else
begin
{ avoid unnecessary sign extension and zeroing }
valuereg := makeregsize(list,valuereg,OS_INT);
destreg := makeregsize(list,destreg,OS_INT);
a_load_reg_reg(list,OS_INT,OS_INT,valuereg,destreg);
destreg := makeregsize(list,destreg,tosize);
end
{ avoid unnecessary sign extension and zeroing }
valuereg := makeregsize(list,valuereg,OS_INT);
destreg := makeregsize(list,destreg,OS_INT);
a_load_reg_reg(list,OS_INT,OS_INT,valuereg,destreg);
destreg := makeregsize(list,destreg,tosize);
end;
@ -1541,16 +1588,14 @@ implementation
if (target_info.endian = endian_big) then
begin
a_op_const_reg(list,OP_SHL,OS_INT,loadbitsize-sref.bitlen,tmpreg);
if not(slopt in [SL_REGNOSRCMASK,SL_SETMAX]) and
(loadbitsize <> AIntBits) then
if not(slopt in [SL_REGNOSRCMASK,SL_SETMAX]) then
{ mask left over bits }
a_op_const_reg(list,OP_AND,OS_INT,aint(((aword(1) shl sref.bitlen)-1) shl (loadbitsize-sref.bitlen)),tmpreg);
a_op_reg_reg(list,OP_SHR,OS_INT,sref.bitindexreg,tmpreg);
end
else
begin
if not(slopt in [SL_REGNOSRCMASK,SL_SETMAX]) and
(loadbitsize <> AIntBits) then
if not(slopt in [SL_REGNOSRCMASK,SL_SETMAX]) then
{ mask left over bits }
a_op_const_reg(list,OP_AND,OS_INT,aint((aword(1) shl sref.bitlen)-1),tmpreg);
a_op_reg_reg(list,OP_SHL,OS_INT,sref.bitindexreg,tmpreg);
@ -1669,11 +1714,14 @@ implementation
tmpreg: tregister;
slopt: tsubsetloadopt;
begin
{ perform masking of the source value in advance }
slopt := SL_REGNOSRCMASK;
if (sref.bitlen <> AIntBits) then
aword(a) := aword(a) and ((aword(1) shl sref.bitlen) -1);
if (
{ broken x86 "x shl regbitsize = x" }
((sref.bitlen <> AIntBits) and
(aword(a) = (aword(1) shl sref.bitlen) -1)) or
((aword(a) and ((aword(1) shl sref.bitlen) -1)) = (aword(1) shl sref.bitlen) -1)) or
((sref.bitlen = AIntBits) and
(a = -1))
) then

View File

@ -417,11 +417,17 @@ const
list.concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,destreg,
sreg.subsetreg,(32-sreg.startbit) and 31,32-sreg.bitlen,31));
{ types with a negative lower bound are always a base type (8, 16, 32 bits) }
if ((sreg.bitlen mod 8) = 0) then
begin
a_load_reg_reg(list,tcgsize2unsigned[subsetsize],subsetsize,destreg,destreg);
a_load_reg_reg(list,subsetsize,tosize,destreg,destreg);
end;
if (subsetsize in [OS_S8..OS_S128]) then
if ((sreg.bitlen mod 8) = 0) then
begin
a_load_reg_reg(list,tcgsize2unsigned[subsetsize],subsetsize,destreg,destreg);
a_load_reg_reg(list,subsetsize,tosize,destreg,destreg);
end
else
begin
a_op_const_reg(list,OP_SHL,OS_INT,32-sreg.bitlen,destreg);
a_op_const_reg(list,OP_SAR,OS_INT,32-sreg.bitlen,destreg);
end;
end
else
a_load_reg_reg(list,subsetsize,tosize,sreg.subsetreg,destreg);

View File

@ -814,12 +814,20 @@ begin
extend the sign correctly. (The latter is actually required only for signed subsets and if that
subset is not >= the tosize). }
extrdi_startbit := 64 - (sreg.bitlen + sreg.startbit);
if (sreg.startbit <> 0) then begin
if (sreg.startbit <> 0) or
(sreg.bitlen <> tcgsize2size[subsetsize]*8) then begin
list.concat(taicpu.op_reg_reg_const_const(A_EXTRDI, destreg, sreg.subsetreg, sreg.bitlen, extrdi_startbit));
a_load_reg_reg(list, tcgsize2unsigned[subsetsize], subsetsize, destreg, destreg);
a_load_reg_reg(list, subsetsize, tosize, destreg, destreg);
if (subsetsize in [OS_S8..OS_S128]) then
if ((sreg.bitlen mod 8) = 0) then begin
a_load_reg_reg(list, tcgsize2unsigned[subsetsize], subsetsize, destreg, destreg);
a_load_reg_reg(list, subsetsize, tosize, destreg, destreg);
end else begin
a_op_const_reg(list,OP_SHL,OS_INT,64-sreg.bitlen,destreg);
a_op_const_reg(list,OP_SAR,OS_INT,64-sreg.bitlen,destreg);
end;
end else begin
a_load_reg_reg(list, tcgsize2unsigned[sreg.subsetregsize], subsetsize, sreg.subsetreg, destreg);
a_load_reg_reg(list, subsetsize, tosize, destreg, destreg);
end;
end;

View File

@ -312,26 +312,29 @@ unit cgppc;
restbits: byte;
begin
restbits := (sref.bitlen - (loadbitsize - sref.startbit));
a_op_const_reg(list,OP_SHL,OS_INT,restbits,valuereg);
{ mask other bits }
if (sref.bitlen <> AIntBits) then
a_op_const_reg(list,OP_AND,OS_INT,(aword(1) shl sref.bitlen)-1,valuereg);
if (subsetsize in [OS_S8..OS_S128]) then
begin
{ sign extend }
a_op_const_reg(list,OP_SHL,OS_INT,AIntBits-loadbitsize+sref.startbit,valuereg);
a_op_const_reg(list,OP_SAR,OS_INT,AIntBits-sref.bitlen,valuereg);
end
else
begin
a_op_const_reg(list,OP_SHL,OS_INT,restbits,valuereg);
{ mask other bits }
if (sref.bitlen <> AIntBits) then
a_op_const_reg(list,OP_AND,OS_INT,(aword(1) shl sref.bitlen)-1,valuereg);
end;
{ use subsetreg routine, it may have been overridden with an optimized version }
fromsreg.subsetreg := extra_value_reg;
fromsreg.subsetregsize := OS_INT;
{ subsetregs always count bits from right to left }
if (target_info.endian = endian_big) then
fromsreg.startbit := loadbitsize-restbits
else
fromsreg.startbit := 0;
fromsreg.startbit := loadbitsize-restbits;
fromsreg.bitlen := restbits;
tosreg.subsetreg := valuereg;
tosreg.subsetregsize := OS_INT;
if (target_info.endian = endian_big) then
tosreg.startbit := 0
else
tosreg.startbit := loadbitsize-sref.startbit;
tosreg.startbit := 0;
tosreg.bitlen := restbits;
a_load_subsetreg_subsetreg(list,subsetsize,subsetsize,fromsreg,tosreg);

View File

@ -1331,21 +1331,23 @@ implementation
function tenumdef.packedbitsize: aint;
var
sizeval: tconstexprint;
power: longint;
begin
result := 0;
if (minval < 0) then
result := inherited packedbitsize
if (minval >= 0) and
(maxval <= 1) then
result := 1
else
begin
if (maxval <= 1) then
result := 1
if (minval>=0) then
sizeval:=maxval
else
begin
{ 256 must become 512 etc. }
nextpowerof2(maxval+1,power);
result := power;
end;
{ don't count 0 twice }
sizeval:=(cutils.max(-minval,maxval)*2)-1;
{ 256 must become 512 etc. }
nextpowerof2(sizeval+1,power);
result := power;
end;
end;
@ -1496,26 +1498,32 @@ implementation
function torddef.packedbitsize: aint;
var
sizeval: tconstexprint;
power: longint;
begin
result := 0;
if ordtype = uvoid then
exit;
if (low < 0) then
result := inherited packedbitsize
if (low >= 0) and
(high <= 1) then
result := 1
else if (ordtype = u64bit) or
((ordtype = s64bit) and
((low <= (system.low(int64) div 2)) or
(high > (system.high(int64) div 2)))) then
result := 64
else
begin
if (high <= 1) then
result := 1
else if (ordtype = u64bit) then
result := 64
if (low>=0) then
sizeval:=high
else
begin
{ 256 must become 512 etc. }
nextpowerof2(high+1,power);
result := power;
end;
end;
{ don't count 0 twice }
sizeval:=(cutils.max(-low,high)*2)-1;
{ 256 must become 512 etc. }
nextpowerof2(sizeval+1,power);
result := power;
end;
end;

247
tests/test/tparray19.pp Normal file
View File

@ -0,0 +1,247 @@
{$mode macpas}
{$r-}
procedure error(l: longint);
begin
writeln('error near ',l);
halt(1);
end;
procedure test8bit;
type
ta = -1..0;
tb = packed array[0..999] of ta;
tc = array[0..124] of byte;
const
results: array[0..9] of ta = (-1,0,-1,-1,-1,0,-1,-1,-1,0);
var
a: ta;
b: tb;
i,j: longint;
begin
fillchar(b,sizeof(b),0);
for i := low(results) to high(results) do
begin
b[i] := results[i];
for j := succ(i) to high(results) do
if b[j] <> 0 then
error(201);
if b[i] <> results[i] then
error(202);
end;
if (b[0] <> results[0]) then
error(1);
if (b[1] <> results[1]) then
error(2);
if (b[2] <> results[2]) then
error(3);
if (b[3] <> results[3]) then
error(4);
if (b[4] <> results[4]) then
error(5);
for i := low(results) to high(results) do
if b[i] <> results[i] then
error(7);
end;
procedure test8to16bit;
type
ta = -3..3;
tb = packed array[0..1000] of ta;
const
results: array[0..5] of ta = (2,-2,1,-1,-3,1);
var
a: ta;
b: tb;
i,j: longint;
begin
fillchar(b,sizeof(b),0);
for i := low(results) to high(results) do
begin
b[i] := results[i];
for j := succ(i) to high(results) do
if b[j] <> 0 then
error(211);
if b[i] <> results[i] then
error(212);
end;
if (b[0] <> results[0]) then
error(11);
if (b[1] <> results[1]) then
error(12);
if (b[2] <> results[2]) then
error(13);
if (b[3] <> results[3]) then
error(14);
if (b[4] <> results[4]) then
error(15);
if (b[5] <> results[5]) then
error(155);
for i := low(results) to high(results) do
if b[i] <> results[i] then
error(17);
end;
procedure test16bit;
type
ta = -255..255;
tb = packed array[0..799] of ta;
tc = array[0..899] of byte;
const
results: array[0..4] of ta = (256-356,39,256-485,100,256-500);
var
a: ta;
b: tb;
i,j: longint;
begin
fillchar(b,sizeof(b),$ff);
for i := low(results) to high(results) do
begin
b[i] := results[i];
for j := succ(i) to high(results) do
if b[j] <> -1 then
error(221);
if b[i] <> results[i] then
error(222);
end;
if (b[0] <> results[0]) then
error(21);
if (b[1] <> results[1]) then
error(22);
if (b[2] <> results[2]) then
error(23);
if (b[3] <> results[3]) then
error(24);
if (b[4] <> results[4]) then
error(25);
for i := low(results) to high(results) do
if b[i] <> results[i] then
error(27);
end;
procedure test16to24bit;
type
ta = -1023..1023;
tb = packed array[0..799] of ta;
tc = array[0..1099] of byte;
const
results: array[0..4] of ta = (1000,67-1023,853,512-1023,759);
var
a: ta;
b: tb;
i,j: longint;
begin
fillchar(b,sizeof(b),0);
for i := low(results) to high(results) do
begin
b[i] := results[i];
for j := succ(i) to high(results) do
if b[j] <> 0 then
error(231);
if b[i] <> results[i] then
error(232);
end;
if (b[0] <> results[0]) then
error(31);
if (b[1] <> results[1]) then
error(32);
if (b[2] <> results[2]) then
error(33);
if (b[3] <> results[3]) then
error(34);
if (b[4] <> results[4]) then
error(35);
for i := low(results) to high(results) do
if b[i] <> results[i] then
error(37);
end;
procedure test32bit;
type
ta = -((1 shl 18)-1)..(1 shl 18) - 1;
tb = packed array[0..799] of ta;
tc = array[0..1899] of byte;
const
results: array[0..4] of ta = ($0002F687,$00032222-(1 shl 18),$000178EE,$000057970-(1 shl 18),$0007E1D2-(1 shl 18));
var
a: ta;
b: tb;
i,j: longint;
begin
fillchar(b,sizeof(b),$00);
for i := low(results) to high(results) do
begin
b[i] := results[i];
for j := succ(i) to high(results) do
if b[j] <> 0 then
error(241);
if b[i] <> results[i] then
error(242);
end;
if (b[0] <> results[0]) then
error(41);
if (b[1] <> results[1]) then
error(42);
if (b[2] <> results[2]) then
error(43);
if (b[3] <> results[3]) then
error(44);
if (b[4] <> results[4]) then
error(45);
for i := low(results) to high(results) do
if b[i] <> results[i] then
error(47);
end;
procedure test32to40bit;
type
ta = -$3fffffff..$3fffffff;
tb = packed array[0..799] of ta;
tc = array[0..3099] of byte;
const
results: array[0..4] of ta = ($3fffffff-$71567851,$3fffffff-$56789ABD,$3fffffff-$50F11178,$39D68DDC,$3fffffff-$6C7A5A7);
var
a: ta;
b: tb;
i,j: longint;
begin
fillchar(b,sizeof(b),0);
for i := low(results) to high(results) do
begin
b[i] := results[i];
for j := succ(i) to high(results) do
if b[j] <> 0 then
error(251);
if b[i] <> results[i] then
error(252);
end;
if (b[0] <> results[0]) then
error(51);
if (b[1] <> results[1]) then
error(52);
if (b[2] <> results[2]) then
error(53);
if (b[3] <> results[3]) then
error(54);
if (b[4] <> results[4]) then
error(55);
for i := low(results) to high(results) do
if b[i] <> results[i] then
error(57);
end;
begin
test8bit;
test8to16bit;
test16bit;
test16to24bit;
test32bit;
test32to40bit;
end.