Sign in Join

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

Mailing lists / fpc-pascal / 2012-05

Reversing bit-order of byte

16 messages · 8 people · –

Reply by email Subscribe to this list Your subscription

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

Koenraad Lelong

Hi,

I'm porting a driver, originally written in C, for an LCD to be used with an embedded arm-processor (STM32).
The original driver uses SPI, my driver will use a USART in synchronous mode because the STM32 has no SPI for 9-bit. Unfortunately, the bit-order is reversed between SPI and USART transmission. Does anyone knows an efficient way to reverse bit-order of a byte for the arm-processor ? I'm going to look into the assembly language of the arm-processor, but maybe someone knows this immediately. For old processors like 8085 or Z80 I know how to do this, but arm-assembler is new to me.

Thanks for any hints.

Koenraad Lelong.

Reply by email

Mark Morgan Lloyd
to Koenraad Lelong: I'm porting a driver, originally written in C, for an LCD to be used with an embedded…
Koenraad Lelong wrote 12 lines
Hi, I'm porting a driver, originally written in C, for an LCD to be used with an embedded arm-processor (STM32). The original driver uses SPI, my driver will use a USART in synchronous mode because the STM32 has no SPI for 9-bit. Unfortunately, the bit-order is reversed between SPI and USART transmission. Does anyone knows an efficient way to reverse bit-order of a byte for the arm-processor ? I'm going to look into the assembly language of the arm-processor, but maybe someone knows this immediately. For old processors like 8085 or Z80 I know how to do this, but arm-assembler is new to me.

I think I'd use a lookup table (making sure it's cacheable), particularly since what you're doing is going to be called frequently and you're likely to have much more than 64K memory.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Thomas Schatzl
to Mark Morgan Lloyd

Hi,

Mark Morgan Lloyd wrote 13 lines
Koenraad Lelong wrote: > Hi, > > I'm porting a driver, originally written in C, for an LCD to be used > with an embedded arm-processor (STM32). > The original driver uses SPI, my driver will use a USART in synchronous > mode because the STM32 has no SPI for 9-bit. Unfortunately, the > bit-order is reversed between SPI and USART transmission. > Does anyone knows an efficient way to reverse bit-order of a byte for > the arm-processor ? I'm going to look into the assembly language of the > arm-processor, but maybe someone knows this immediately. > For old processors like 8085 or Z80 I know how to do this, but > arm-assembler is new to me.

E.g. see

http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith64BitsDiv

(which, in addition to the above way also gives other examples; then there is http://www.tekpool.com/node/208 which shows even more of them if you do not like 64 bit math)

Show quoted text 5 lines
I think I'd use a lookup table (making sure it's cacheable), particularly since what you're doing is going to be called frequently and you're likely to have much more than 64K memory.

... however I guess that a precomputed table is likely best for your application.

Thomas

Reply by email

Ludo Brands
to Koenraad Lelong: I'm porting a driver, originally written in C, for an LCD to be used with an embedded…
Show quoted text 17 lines
Hi, I'm porting a driver, originally written in C, for an LCD to be used with an embedded arm-processor (STM32). The original driver uses SPI, my driver will use a USART in synchronous mode because the STM32 has no SPI for 9-bit. Unfortunately, the bit-order is reversed between SPI and USART transmission. Does anyone knows an efficient way to reverse bit-order of a byte for the arm-processor ? I'm going to look into the assembly language of the arm-processor, but maybe someone knows this immediately. For old processors like 8085 or Z80 I know how to do this, but arm-assembler is new to me. Thanks for any hints.

You might also look into the RBIT instruction which does this in one cpu cycle. See
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489c/Cihjgdi d.html and applied to the STM32 USART
http://forum.micromouseonline.com/viewtopic.php?f=7&t=460

Ludo

Reply by email

David Butler
to Koenraad Lelong: I'm porting a driver, originally written in C, for an LCD to be used with an embedded…

If you want to go assembly:

function ReverseBits(const Value: LongWord): LongWord; register; assembler; asm
BSWAP EAX
MOV EDX, EAX
AND EAX, 0AAAAAAAAh
SHR EAX, 1
AND EDX, 055555555h
SHL EDX, 1
OR EAX, EDX
MOV EDX, EAX
AND EAX, 0CCCCCCCCh
SHR EAX, 2
AND EDX, 033333333h
SHL EDX, 2
OR EAX, EDX
MOV EDX, EAX
AND EAX, 0F0F0F0F0h
SHR EAX, 4
AND EDX, 00F0F0F0Fh
SHL EDX, 4
OR EAX, EDX
end;

On Thu, May 3, 2012 at 9:10 AM, Koenraad Lelong <

Show quoted text 22 lines
wrote: Hi, I'm porting a driver, originally written in C, for an LCD to be used with an embedded arm-processor (STM32). The original driver uses SPI, my driver will use a USART in synchronous mode because the STM32 has no SPI for 9-bit. Unfortunately, the bit-order is reversed between SPI and USART transmission. Does anyone knows an efficient way to reverse bit-order of a byte for the arm-processor ? I'm going to look into the assembly language of the arm-processor, but maybe someone knows this immediately. For old processors like 8085 or Z80 I know how to do this, but arm-assembler is new to me. Thanks for any hints. Koenraad Lelong. ______________________________**_________________ fpc-pascal maillist - http://lists.freepascal.org/**mailman/listinfo/fpc-pascal<http://lists.freepascal.org/mailman/listinfo/fpc-pascal>

Reply by email

Koenraad Lelong
to Ludo Brands: You might also look into the RBIT instruction which does this in one cpu cycle. See…
Ludo Brands wrote 8 lines
You might also look into the RBIT instruction which does this in one cpu cycle. See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489c/Cihjgdi d.html and applied to the STM32 USART http://forum.micromouseonline.com/viewtopic.php?f=7&t=460 Ludo

Hi,

Thanks all for your replies.
I already found the RBIT-instruction. I also found out I need to study the arm assembly language ;-)

But how do I get my variable ? Is that in some register ? Is there any documentation about such things ? Then I can use inline assembly.

Thanks,

Koenraad Lelong.

Reply by email

Ludo Brands
to Koenraad Lelong
Show quoted text 9 lines
Thanks all for your replies. I already found the RBIT-instruction. I also found out I need to study the arm assembly language ;-) But how do I get my variable ? Is that in some register ? Is there any documentation about such things ? Then I can use inline assembly.

ARM has different ABI's. A pragmatic solution is to create a full pascal (inline if you like) function with the function signature you like and a dummy body, look at the assembler generated (use debug info whe compiling) and then insert your instructions. For example

Function ReverseBits(b:byte):byte;
Begin
  result:=b shl 2;
End;
Look at how result:=b shl 2 is implemented and you'll find immmedialy the
registers used. Next you replace result:=b shl 2 with your asm block.

Note that RBIT is a thumb 2 instruction.

Ludo

Reply by email

Thomas Schatzl
to Ludo Brands

Hi,

Ludo Brands wrote 11 lines
> Thanks all for your replies. > I already found the RBIT-instruction. I also found out I need > to study > the arm assembly language ;-) > > But how do I get my variable ? Is that in some register ? Is > there any > documentation about such things ? Then I can use inline assembly. > ARM has different ABI's. A pragmatic solution is to create a full pascal

We use the standard ARM EABI as gcc uses; for the purpose of this code, it should be sufficient to know that r0 contains the first parameter value, and function values are returned in r0 as well.

Without testing, something like the following should be sufficient:

function reverse(b : byte) : byte; assembler; nostackframe;
asm
  rbit r0, r0
  // rbit reverses the whole word, so now you have
  // your value in bits 31-24... so shift right by that amount
  // should fix this up (bits 23-0 contain junk, we shift that out
  // anyway)
  lsr r0, r0, #24
end;

However, this may not compile because fpc may not recognize the rbit instruction.

Following is a version that encodes the instruction directly, retrieved from disassembling some gcc code:

function reverse(b : byte) : byte; assembler; nostackframe; asm
.long 0xe6ff0f30 // rbit r0, r0
lsr r0, r0, #24
end;

Hope this helps; I could not test due to lack of hardware. It may help to use -Cparmv6 and have your (cross-)assembler configured for armv6 code emission.

Thomas

Reply by email

Sven Barth
to David Butler: If you want to go assembly: function ReverseBits(const Value: LongWord): LongWord;…
David Butler wrote 24 lines
If you want to go assembly: function ReverseBits(const Value: LongWord): LongWord; register; assembler; asm BSWAP EAX MOV EDX, EAX AND EAX, 0AAAAAAAAh SHR EAX, 1 AND EDX, 055555555h SHL EDX, 1 OR EAX, EDX MOV EDX, EAX AND EAX, 0CCCCCCCCh SHR EAX, 2 AND EDX, 033333333h SHL EDX, 2 OR EAX, EDX MOV EDX, EAX AND EAX, 0F0F0F0F0h SHR EAX, 4 AND EDX, 00F0F0F0Fh SHL EDX, 4 OR EAX, EDX end;

You know that he asked for ARM not x86?

Regards,
Sven

Reply by email

Koenraad Lelong
to Thomas Schatzl: We use the standard ARM EABI as gcc uses; for the purpose of this code, it should be…

On 03-05-12 13:27, Thomas Schatzl wrote:
...

Show quoted text 22 lines
function reverse(b : byte) : byte; assembler; nostackframe; asm rbit r0, r0 // rbit reverses the whole word, so now you have // your value in bits 31-24... so shift right by that amount // should fix this up (bits 23-0 contain junk, we shift that out // anyway) lsr r0, r0, #24 end; However, this may not compile because fpc may not recognize the rbit instruction. Following is a version that encodes the instruction directly, retrieved from disassembling some gcc code: function reverse(b : byte) : byte; assembler; nostackframe; asm .long 0xe6ff0f30 // rbit r0, r0 lsr r0, r0, #24 end;

Thanks guys, I'll try and test this weekend.

Regards,

Koenraad Lelong.

Reply by email

Koenraad Lelong
to Thomas Schatzl: We use the standard ARM EABI as gcc uses; for the purpose of this code, it should be…

On 03-05-12 13:27, Thomas Schatzl wrote:
...

Show quoted text 6 lines
function reverse(b : byte) : byte; assembler; nostackframe; asm .long 0xe6ff0f30 // rbit r0, r0 lsr r0, r0, #23 end;

Hi,

I've been looking a bit disassembled the code and this is the result :

8000150: e6ff0f30 rbit r0, r0
8000154: ea4f 50d0 mov.w r0, r0, lsr #23 8000158: 46f7 mov pc, lr

Wouldn't it be possible to do
rbit r0, r0, lsr #23
When reading the ARM programming manual I believe it should.

But do I gain something ?

Regards,

Koenraad Lelong.

Reply by email

Thomas Schatzl
to Koenraad Lelong

Hi,

Koenraad Lelong wrote 16 lines
On 03-05-12 13:27, Thomas Schatzl wrote: ... > function reverse(b : byte) : byte; assembler; nostackframe; > asm > .long 0xe6ff0f30 // rbit r0, r0 > lsr r0, r0, #23 > end; > Hi, I've been looking a bit further at this. I disassembled the code and this is the result : 8000150: e6ff0f30 rbit r0, r0 8000154: ea4f 50d0 mov.w r0, r0, lsr #23

The constant is wrong here, it should be #24, not #23 imo... typo.

8000158: 46f7 mov pc, lr

It might be good to compile with -Cparmv6 (or -Cparmv7, do not know what type the processor you use is), this generates a "better" return instruction ("bx lr") - and for the rbit instruction you need armv6 already.

Wouldn't it be possible to do rbit r0, r0, lsr #23 When reading the ARM programming manual I believe it should.

No, rbit does not allow the "flexible operand" encoding.

But do I gain something ?

If it were possible, at most a few cpu cycles.

Compared to the other variants (e.g. with the multiplies, except for the table lookup) you already save a lot of cycles - although I guess they would be sufficiently fast anyway, considering the typical uart speeds.

Thomas

Reply by email

Koenraad Lelong
to Thomas Schatzl
Thomas Schatzl wrote 22 lines
It might be good to compile with -Cparmv6 (or -Cparmv7, do not know what type the processor you use is), this generates a "better" return instruction ("bx lr") - and for the rbit instruction you need armv6 already. > Wouldn't it be possible to do > rbit r0, r0, lsr #23 > When reading the ARM programming manual I believe it should. > No, rbit does not allow the "flexible operand" encoding. > But do I gain something ? > If it were possible, at most a few cpu cycles. Compared to the other variants (e.g. with the multiplies, except for the table lookup) you already save a lot of cycles - although I guess they would be sufficiently fast anyway, considering the typical uart speeds. Thomas

Hi Thomas,

My processor flags : -Wpstm32f103rb -Cparmv7m.
The #23 is no typo, I need to reverse 9 bits. I'm using 9 bit synchronous transmission. My first usart-tests person that made the driver recommends max. 6Mbps.
If I need more spare time I'll have to see what DMA can do.

Thanks for all information.

Regards,

Koenraad Lelong.

Reply by email

Koenraad Lelong
to Koenraad Lelong
Koenraad Lelong wrote
On 04-05-12 14:31, Thomas Schatzl wrote:

...

Show quoted text 13 lines
> > Compared to the other variants (e.g. with the multiplies, except for the > table lookup) you already save a lot of cycles - although I guess they > would be sufficiently fast anyway, considering the typical uart speeds. > > Thomas Hi Thomas, My processor flags : -Wpstm32f103rb -Cparmv7m. The #23 is no typo, I need to reverse 9 bits. I'm using 9 bit synchronous transmission. My first usart-tests person that made the driver recommends max. 6Mbps.

Hi,

I tested some things this weekend. Strange things happen ;-) The code does not work. Trying to debug with gdb, around the code I got an error, something like 'recovering from a double fault'.

After searching the STM32 forum of ST I found that some toolchains assemble the rbit instruction in a wrong way. Someone made a work-around : .word 0xFxAyFA9y //RBIT Rx,Ry x, y = 0 to F
My Freepascal version is this :
.word 0xFA90
.word 0xF0A0
Then when I disassemble in gdb, I get rbit r0,r0
Disassembling with objdump gives a strange result.

I'm going to try this as soon as I can.

Regards,

Koenraad Lelong.

Reply by email

Geoffrey Barton
Show quoted text 47 lines
Message: 4 Date: Mon, 07 May 2012 12:59:58 +0200 From: Koenraad Lelong Subject: Re: RE : RE : [fpc-pascal] Reversing bit-order of byte To: Message-ID: Content-Type: text/plain; charset=UTF-8; format=flowed On 04-05-12 14:53, Koenraad Lelong wrote: > On 04-05-12 14:31, Thomas Schatzl wrote: ... >> >> Compared to the other variants (e.g. with the multiplies, except for the >> table lookup) you already save a lot of cycles - although I guess they >> would be sufficiently fast anyway, considering the typical uart speeds. >> >> Thomas > > Hi Thomas, > > My processor flags : -Wpstm32f103rb -Cparmv7m. > The #23 is no typo, I need to reverse 9 bits. I'm using 9 bit > synchronous transmission. My first usart-tests person > that made the driver recommends max. 6Mbps. Hi, I tested some things this weekend. Strange things happen ;-) The code does not work. Trying to debug with gdb, around the code I got an error, something like 'recovering from a double fault'. After searching the STM32 forum of ST I found that some toolchains assemble the rbit instruction in a wrong way. Someone made a work-around : .word 0xFxAyFA9y //RBIT Rx,Ry x, y = 0 to F My Freepascal version is this : .word 0xFA90 .word 0xF0A0 Then when I disassemble in gdb, I get rbit r0,r0 Disassembling with objdump gives a strange result. I'm going to try this as soon as I can. Regards, Koenraad Lelong.

I have beed using this:-

function bitreverse(input:dword):dword;assembler;nostackframe;  {single instruction rbit r0,r0  bit reverses r0}
asm
.long 0xf0a0fa90
end;

quite successfully.

You can then choose which byte(s) you need using normal pascal functions.

regards,
Geoffrey

Reply by email