Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2021-01

ROL/ROR with Carry

7 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Sven Barth

Hello together!

Considering that jamie philbrook has given up on his feature request ( https://bugs.freepascal.org/view.php?id=38341 ) rather quickly and that it had been my idea for him to open that bug report I'd like to discuss this here.

So the idea is to add support for ROL/ROR with Carry support as the current Rol*/Ror* functions don't support that. Florian then said that he's open to suggestions under some restrictions. Considering that the current Rol*/Ror* intrinsics aren't available for all platforms as intrinsics either, but as functions then, this could be done to support CPUs without suitable Carry support as well. And the code snippet that jamie showed would be a nice base:

=== code begin ===

Function ROLByteWithCarry(Const AByte:Byte; Var ACarry:Boolean):Byte;Inline;
var
   LocalIn:Boolean;
  Begin
   LocalIN := Acarry;
   ACarry := ShortInt(Abyte) < 0;
   Result := (AByte shl 1);
   IF LocalIn then Result := Result or 1;
  End;

=== code end ===

Am I missing something?

Regards,
Sven

Reply by email

Karoly Balogh
to Sven Barth

Hi,

Sven Barth wrote 19 lines
So the idea is to add support for ROL/ROR with Carry support as the current Rol*/Ror* functions don't support that. Florian then said that he's open to suggestions under some restrictions. Considering that the current Rol*/Ror* intrinsics aren't available for all platforms as intrinsics either, but as functions then, this could be done to support CPUs without suitable Carry support as well. And the code snippet that jamie showed would be a nice base: === code begin === Function ROLByteWithCarry(Const AByte:Byte; Var ACarry:Boolean):Byte;Inline; var   LocalIn:Boolean;  Begin   LocalIN := Acarry;   ACarry := ShortInt(Abyte) < 0;   Result := (AByte shl 1);   IF LocalIn then Result := Result or 1;  End;

We can name it rolx/rorx... I don't think such a long name is a good idea, because such construct will be used a lot in longer formulas?

Btw, as the code, what's wrong with:

begin
  result:=(abyte shl 1) or ord(acarry);
  acarry:=shortint(abyte) < 0;
end;

No local var, no branches...

The problem is with this ROL-with-carry as library function approach, that it tries to mimic internal working of some CPU, so it inherently leads to less efficient code, because it's very difficult to actually map this into a CPU instruction... Even when we provide an instrinsic for it, because how on earth you populate the carry flag first based on that boolean coming from that argument? So I feel people will try to use this for "smart" algos and optimization, while it's totally counterproductive in a high level language.

It's much better to write such code as <value * 2> + previous carry then clamp it, then let the compiler optimize it, rather than trying to mess with a rorx/rolx function.

I think whoever wants such a ching is just better off extending their byte to a word, doing the shift/rotate, and masking the carry off as needed.

My 2 cents.

Charlie

Reply by email

J. Gareth Moreton
to Karoly Balogh

I do agree that populating the carry bit is not that straightforward, especially on processors that don't have an explicit carry.

An alternative approach is to go for something similar to the SHRD instruction, that pulls in bits from another register rather than the carry bit - https://www.felixcloutier.com/x86/shrd - then again, this might be overkill when you want to rotate with a single carry bit, which is effectively akin to rotating a register that is 1 bit larger than the normal word size.

Gareth aka. Kit

Karoly Balogh wrote 58 lines
Hi, On Mon, 11 Jan 2021, Sven Barth via fpc-devel wrote: > So the idea is to add support for ROL/ROR with Carry support as the > current Rol*/Ror* functions don't support that. Florian then said that > he's open to suggestions under some restrictions. Considering that the > current Rol*/Ror* intrinsics aren't available for all platforms as > intrinsics either, but as functions then, this could be done to support > CPUs without suitable Carry support as well. And the code snippet that > jamie showed would be a nice base: > > === code begin === > > Function ROLByteWithCarry(Const AByte:Byte; Var ACarry:Boolean):Byte;Inline; > var >   LocalIn:Boolean; >  Begin >   LocalIN := Acarry; >   ACarry := ShortInt(Abyte) < 0; >   Result := (AByte shl 1); >   IF LocalIn then Result := Result or 1; >  End; We can name it rolx/rorx... I don't think such a long name is a good idea, because such construct will be used a lot in longer formulas? Btw, as the code, what's wrong with: begin result:=(abyte shl 1) or ord(acarry); acarry:=shortint(abyte) < 0; end; No local var, no branches... The problem is with this ROL-with-carry as library function approach, that it tries to mimic internal working of some CPU, so it inherently leads to less efficient code, because it's very difficult to actually map this into a CPU instruction... Even when we provide an instrinsic for it, because how on earth you populate the carry flag first based on that boolean coming from that argument? So I feel people will try to use this for "smart" algos and optimization, while it's totally counterproductive in a high level language. It's much better to write such code as <value * 2> + previous carry then clamp it, then let the compiler optimize it, rather than trying to mess with a rorx/rolx function. I think whoever wants such a ching is just better off extending their byte to a word, doing the shift/rotate, and masking the carry off as needed. My 2 cents. Charlie _______________________________________________ fpc-devel maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus

Reply by email

Florian Klämpfl
to Sven Barth: Hello together! Considering that jamie philbrook has given up on his feature request (…
Sven Barth wrote 33 lines
Hello together! Considering that jamie philbrook has given up on his feature request ( https://bugs.freepascal.org/view.php?id=38341 ) rather quickly and that it had been my idea for him to open that bug report I'd like to discuss this here. So the idea is to add support for ROL/ROR with Carry support as the current Rol*/Ror* functions don't support that. Florian then said that he's open to suggestions under some restrictions. Considering that the current Rol*/Ror* intrinsics aren't available for all platforms as intrinsics either, but as functions then, this could be done to support CPUs without suitable Carry support as well. And the code snippet that jamie showed would be a nice base: === code begin === Function ROLByteWithCarry(Const AByte:Byte; Var ACarry:Boolean):Byte;Inline; var   LocalIn:Boolean;  Begin   LocalIN := Acarry;   ACarry := ShortInt(Abyte) < 0;   Result := (AByte shl 1);   IF LocalIn then Result := Result or 1;  End; === code end === Am I missing something?

The question is what one wants to achieve. The performance of rcl/rcr is not really exiting either (throughput 4 times lower than that of shl/shr). Can someone please provide an algorithm which uses ROLByteWithCarry?

Reply by email

Sven Barth
to Karoly Balogh: We can name it rolx/rorx... I don't think such a long name is a good idea, because such…
Karoly Balogh wrote 34 lines
Hi, On Mon, 11 Jan 2021, Sven Barth via fpc-devel wrote: > So the idea is to add support for ROL/ROR with Carry support as the > current Rol*/Ror* functions don't support that. Florian then said that > he's open to suggestions under some restrictions. Considering that the > current Rol*/Ror* intrinsics aren't available for all platforms as > intrinsics either, but as functions then, this could be done to support > CPUs without suitable Carry support as well. And the code snippet that > jamie showed would be a nice base: > > === code begin === > > Function ROLByteWithCarry(Const AByte:Byte; Var ACarry:Boolean):Byte;Inline; > var >   LocalIn:Boolean; >  Begin >   LocalIN := Acarry; >   ACarry := ShortInt(Abyte) < 0; >   Result := (AByte shl 1); >   IF LocalIn then Result := Result or 1; >  End; We can name it rolx/rorx... I don't think such a long name is a good idea, because such construct will be used a lot in longer formulas? Btw, as the code, what's wrong with: begin result:=(abyte shl 1) or ord(acarry); acarry:=shortint(abyte) < 0; end; No local var, no branches...

That code is nice as well. I had thought of a similar one since I had written my mail.

Show quoted text 8 lines
The problem is with this ROL-with-carry as library function approach, that it tries to mimic internal working of some CPU, so it inherently leads to less efficient code, because it's very difficult to actually map this into a CPU instruction... Even when we provide an instrinsic for it, because how on earth you populate the carry flag first based on that boolean coming from that argument? So I feel people will try to use this for "smart" algos and optimization, while it's totally counterproductive in a high level language.

If it can't be implemented more efficiently than the library function (e.g. yours) already does it for a specific target, then it could just as well use that. After all we don't provide intrinsic ROL/ROR for every target either.

Show quoted text 6 lines
It's much better to write such code as <value * 2> + previous carry then clamp it, then let the compiler optimize it, rather than trying to mess with a rorx/rolx function. I think whoever wants such a ching is just better off extending their byte to a word, doing the shift/rotate, and masking the carry off as needed.

Sadly the user who had an interest in this had redacted their example code from the forum after their feature request didn't go through thus I can't tell you what they had done with the carry...

Regards,
Sven

Reply by email