CMM2: CSUB BitOrderReverse


Author Message
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1154
Posted: 05:08pm 09 Sep 2020      

This is a conversion of an old bit order reversal CFunction for MM2.

Demo and C source:
Bitorderreversal.zip

I needed it for a project.

BitOrderReverse Demo

Input:
0010111100101111001011110010111100101111001011110010111100101111
Output:
1111010011110100111101001111010011110100111101001111010011110100
10000 loops:  CSUB          FUNC          Empty      1x CSUB  1x FUNC
                 
              233ms         572ms         22ms         21us    55us


Regards
Michael

chris
Regular Member

Joined: 24/08/2020
Location: United Kingdom
Posts: 54
Posted: 01:23am 10 Sep 2020      

I wonder if you could get it faster by not using pointer indirection in the loop in your C code, or if the compiler already figured that out for you?

twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1154
Posted: 12:57pm 10 Sep 2020      

Hi Chis,

thanks for your attention! Good find!
You are absolutely right, if you don't use pointer indirection, it's faster (~ 15%)!
I need it to convert around 10,000 integers for a project - in a reasonable time (<500ms). I relied on the smartness of the compiler (Note: Never use pointer indirection in large loops!).

Result:
BitOrderReverse Demo

Input:
0010111100101111001011110010111100101111001011110010111100101111
Output:
1111010011110100111101001111010011110100111101001111010011110100
10000 loops:  CSUB          FUNC          Empty      1x CSUB  1x FUNC
             206ms         545ms         22ms         18us     52us



#include "ARMCFunctions.h"
// Bitorderreversal for CMM2 v1.01 (thanks to Chris@TBS)
// needs ~18us @400Mhz
// Usage: CSUB BitOrderReverse(nInput, nBits, RetValue)
// CSUB BitOrderReverse integer, integer, integer

void Bitorderreverse(long long *orig, long long *nbits, long long *reversed)
{
int i       = 1;
int n       = *nbits;
long long r = 0;
long long o = *orig;
unsigned long long bit_mask = 1;

for(;i<=n;i++)
{
if ((o & (bit_mask<<(i-1))) > 0)
r += bit_mask<<(n-i);
}
*reversed=r;
}


CSUB Bitorderreverse INTEGER,INTEGER,INTEGER
00000000
'Bitorderreverse
0FF0E92D AF00B090 61396178 230160FA 693B63FB 2300E9D3 62FB4613 0200F04F
0300F04F 230CE9C7 E9D3697B E9C72300 F04F2308 F04F0201 E9C70300 E03E2306
1E596BFB 2306E9D7 0620F1A1 0020F1C1 F501FA03 F606FA02 FA224335 4305F000
F401FA02 2308E9D7 0A02EA04 0B03EA05 030BEA5A 6AFAD020 1AD16BFB 2306E9D7
0620F1A1 0020F1C1 F901FA03 F606FA02 0906EA49 F000FA22 0900EA49 F801FA02
230CE9D7 0102EB18 EB496039 607B0303 2300E9D7 230CE9C7 33016BFB 6BFA63FB
429A6AFB 68F9DDBC 230CE9D7 2300E9C1 3740BF00 E8BD46BD 47700FF0
End CSUB



Bitorderreverse v1.01.zip


Kind regards
Michael

matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8674
Posted: 01:13pm 10 Sep 2020      

If you want it really fast then there is an ARM instruction to reverse the bit order in a word RBIT. You will need to include it as an ASM clause in the C source

https://developer.arm.com/documentation/dui0646/a/the-cortex-m7-instruction-set/general-data-processing-instructions/rev--rev16--revsh--and-rbit?lang=en

twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1154
Posted: 03:05pm 10 Sep 2020      

Hi Peter,

thanks for your suggestion.

But I fear without a template I can't achieve it. The CMM2 source is in this case not very helpful  
RBIT   R7, R8  ; Reverse bit order of value in R8 and write the result to R7.

I've already found this , but I need time to decode that ...
A template on this thread - or anywhere else - would be much appreciated. But I don't want to rush you.

Kind regards
Michael