PDA

View Full Version : Use of SHR with signed integers



Ñuño Martínez
01-02-2007, 12:54 PM
I'm using SHR and SHL to convert fixed point <-> integers but I've find a problem.



program project2;

FUNCTION integer_to_fixed &#40;v&#58; LONGINT&#41;&#58; LONGINT;
BEGIN
integer_to_fixed &#58;= v SHL 16;
END;

FUNCTION fixed_to_integer &#40;v&#58; LONGINT&#41;&#58; LONGINT;
BEGIN
fixed_to_integer &#58;= v SHR 16;
END;

VAR
v&#58; LONGINT;
begin
v &#58;= integer_to_fixed &#40;-1&#41;; &#123; Gets -1 in 16.16 fixed point. &#125;
WriteLn &#40;v&#41;; &#123; Writes the value as stored in memory. &#125;
WriteLn &#40;fixed_to_integer &#40;v&#41;&#41;; &#123; Should write '-1' but writes '65535'. &#125;
ReadLn;
end.


As you see, SHR doesn't add the '1' bit. What can I use in the "fixed_to_integer" function?

[edit] Found a solution:


FUNCTION fixed_to_integer &#40;v&#58; LONGINT&#41;&#58; LONGINT;
BEGIN
IF v < 0 THEN
fixed_to_integer &#58;= &#40;v SHR 16&#41; OR $FFFF0000
ELSE
fixed_to_integer &#58;= v SHR 16;
END;


Is this the bets one?

Mirage
01-02-2007, 01:17 PM
You can use DIV 65536 of course, but it's slow.

Another way is to use assembler:



FUNCTION fixed_to_integer &#40;v&#58; LONGINT&#41;&#58; LONGINT;
asm
sar eax, 16
END;

LP
01-02-2007, 04:38 PM
You can use DIV 65536 of course, but it's slow.
Actually when optimizations are enabled, this division will be translated into "sar" (at least in Delphi; is it the same in FPC?)

dmantione
01-02-2007, 06:53 PM
Yes, FPC uses sar, optimized or unoptimized. However, -3 div 2=-1, while -3 sar 1=-2. To compensate FPC generates this code (register variables off):



; &#91;12&#93; fixed_to_integer &#58;= v div 65536;
mov edx,dword &#91;ebp-4&#93;
mov eax,edx
sar eax,31
and eax,65535
add edx,eax
sar edx,16
mov dword &#91;ebp-8&#93;,edx

BeRo
03-02-2007, 09:06 PM
function sar&#40;Value,Shift&#58;integer&#41;&#58;integer; &#123;$IFDEF CPU386&#125;assembler; register;&#123;$ELSE&#125;&#123;$IFDEF FPC&#125;inline;&#123;$ELSE&#125;register;&#123;$ENDIF&#125;&#123;$ENDIF&#125;
&#123;$IFDEF CPU386&#125;
asm
mov ecx,edx
sar eax,cl
end;
&#123;$ELSE&#125;
begin
result&#58;=&#40;Value shr Shift&#41; or &#40;&#40;$ffffffff+&#40;1-&#40;&#40;Value and &#40;1 shl 31&#41;&#41; shr 31&#41; and ord&#40;Shift<>0&#41;&#41;&#41; shl &#40;32-Shift&#41;&#41;;
end;
&#123;$ENDIF&#125;


But Delphi does also optimize DIV (2^n) terms to signed shift SAR opcodes.