[fpc-pascal] rotating bits

Пётр Косаревский ppkk at mail.ru
Wed May 24 13:59:35 CEST 2006


> On 24 mei 2006, at 10:56, Пётр Косаревский wrote:
> > Is there high level operator/(inline)function for rotating bits?
> No.
> > Am I supposed to implement rotating bits (like ror/rol in i386 asm)  
> > by inline assembler or some ugly workarounds (shifts and or-s)?
> Yes. I think there's already a feature request to provide these  
> operations, but no one worked on it yet.
> Jonas_______________________________________________

Why don't use this code?

{$INLINE ON}
interface
{$IFDEF CPUI386}
 function brol(b: byte; c: byte): byte; assembler; inline;
 function wrol(w: word; c: byte): word; assembler; inline;
 function lrol(l: longword; c: byte): longword; assembler; inline;
 function bror(b: byte; c: byte): byte; assembler; inline;
 function wror(w: word; c: byte): word; assembler; inline;
 function lror(l: longword; c: byte): longword; assembler; inline;
{$ELSE}
 function brol(b: byte; c: byte): byte; inline;
 function wrol(w: word; c: byte): word; inline;
 function lrol(l: longword; c: byte): longword; inline;
 function bror(b: byte; c: byte): byte; inline;
 function wror(w: word; c: byte): word; inline;
 function lror(l: longword; c: byte): longword; inline;
{$ENDIF}

implementation
{$IFDEF CPUI386}
 function brol(b: byte; c: byte): byte; assembler; inline;
   asm
   movb  b,%al
   movb  c,%cl
   rolb  %cl,%al
   movb  %al,result
   end ['al','cl'];
 function wrol(w: word; c: byte): word; assembler; inline;
   asm
   movw  w,%ax
   movb  c,%cl
   rolw  %cl,%ax
   movw  %ax,result
   end ['ax','cl'];
 function lrol(l: longword; c: byte): longword; assembler; inline;
   asm
   movl  l,%eax
   movb  c,%cl
   roll  %cl,%eax
   movl  %eax,result
   end ['eax','cl'];
 function bror(b: byte; c: byte): byte; assembler; inline;
   asm
   movb  b,%al
   movb  c,%cl
   rorb  %cl,%al
   movb  %al,result
   end ['al','cl'];
 function wror(w: word; c: byte): word; assembler; inline;
   asm
   movw  w,%ax
   movb  c,%cl
   rorw  %cl,%ax
   movw  %ax,result
   end ['ax','cl'];
 function lror(l: longword; c: byte): longword; assembler; inline;
   asm
   movl  l,%eax
   movb  c,%cl
   rorl  %cl,%eax
   movl  %eax,result
   end ['eax','cl'];
{$ELSE}
 function brol(b: byte; c: byte): byte; inline;
   var s,r: byte;
   begin
   s:=c and $7;
   r:=byte(b shl s);
   r:=r or byte(b shr (8-s)); // c may be over 8 and should be processed correctly
   brol:=r; // "result" is not supported in inline procedures
   end;
 function wrol(w: word; c: byte): word; inline;
   var s: byte; r: word;
   begin
   s:=c and $f;
   r:=word(w shl s);
   r:=r or word(w shr (16-s)); // c may be over 16 and should be processed correctly
   wrol:=r;
   end;
 function lrol(l: longword; c: byte): longword; inline;
   var s: byte; r: longword;
   begin
   s:=c and $1f;
   r:=longword(l shl s);
   r:=r or longword(l shr (32-s)); // c may be over 32 and should be processed correctly
   lrol:=r;
   end;
 function bror(b: byte; c: byte): byte; inline;
   var s,r: byte;
   begin
   s:=c and $7;
   r:=byte(b shr s);
   r:=r or byte(b shl (8-s)); // c may be over 8 and should be processed correctly
   bror:=r;
   end;
 function wror(w: word; c: byte): word; inline;
   var s: byte; r: word;
   begin
   s:=c and $f;
   r:=word(w shr s);
   r:=r or word(w shl (16-s)); // c may be over 16 and should be processed correctly
   wror:=r;
   end;
 function lror(l: longword; c: byte): longword; inline;
   var s: byte; r: longword;
   begin
   s:=c and $1f;
   r:=longword(l shr s);
   r:=r or longword(l shl (32-s)); // c may be over 32 and should be processed correctly
   lror:=r;
   end;
{$ENDIF}


Comments:
   I. style/consistency
      I didn't use all needed {$if}s: current code should word with range checks on both on i386 and not.
      {$Asmmode} was not used either.
      First symbol denotes type: while shl/shr emit longword, cyclic shifts shouldn't
      Endianness is not supported, because I don't understand, why it should be.
   II. performance
      "Result" is not supported in the inline mode.
      I don't know how to use "ret" to achieve the same goal with fewer commands.

Test:
{$INLINE ON}
program testb;
  uses commonthingies;
var i: byte;    b: byte;    w: word;    l: longword;
begin
write('Enter byte (dec):');readln(b);
for i:=0 to 16 do
  writeln('Orig:',binstr(b,8),'   Left:',binstr(brol(b,i),8),'   Right:',binstr(bror(b,i),8));
write('Enter word (dec):');readln(w);
for i:=0 to 32 do
  writeln('Orig:',binstr(w,16),'   Left:',binstr(wrol(w,i),16),'   Right:',binstr(wror(w,i),16));
write('Enter lw (dec)  :');readln(l);
for i:=0 to 64 do
  writeln('Orig:',binstr(l,32),'   Left:',binstr(lrol(l,i),32),'   Right:',binstr(lror(l,i),32));
end.



More information about the fpc-pascal mailing list