Thread: Re: [Algorithms] Byte Swapping
Brought to you by:
vexxed72
From: Jens A. <jAy...@ne...> - 2000-07-16 06:48:05
|
> I can do the obvious method, but I was wondering if anyone have any > cool/fast code snippets for byte swapping integers and floats? Depends on the platform. PowerPCs have "load word byte-reversed indexed" (lwbrx) and "load halfword byte-reversed indexed" (lhbrx) instructions, for instance. -- Jens Ayton |
From: Jens A. <jAy...@ne...> - 2000-07-16 07:14:20
|
Tom Hubina: > Jens Ayton: >> Tom Hubina: >>> >>> I can do the obvious method, but I was wondering if anyone >>> have any cool/fast code snippets for byte swapping integers >>> and floats? >> >> Depends on the platform. PowerPCs have "load word byte- >> reversed indexed" (lwbrx) and "load halfword byte-reversed >> indexed" (lhbrx) instructions, for instance. > > Since that happens to be my platform, perhaps you would have > some routines handy that work in Codewarrior for the Mac that > make those calls to reverse the bytes I'm loading? These instructions are available as intrinsics. If you have an aligned array theLittleEndianArrayOfLongs of wrong-endian longs, this: long theLong = __lwbrx(theLittleEndianArrayOfLongs, n); is equivalent to long theLong = theBigEndianArrayOfLongs[n]; for right-endian data. Similarly, you can use short theShort = __lhbrx(theLittleEndianArrayOfShorts, n); ^ Note the "w" vs. "h" as marked. -- Jens Ayton |
From: Aaron D. <ri...@ho...> - 2000-07-18 01:58:58
|
I'm assuming you're not after portability here. Off the top of my head you could use an assembler snippet like below. Its in x86. I'm not sure if there is a mac equiv of the xchg instruction but if thats not supported its 3 xors for each. The code below doesn't rely on bswap. mov ebx,eax shr ebx,16 xchg al,ah xchg bl,bh shl eax,16 or eax,ebx -----Original Message----- From: Conor Stokes <cs...@tp...> To: gda...@li... <gda...@li...> Date: Tuesday, 18 July 2000 11:19 Subject: Re: [Algorithms] Byte Swapping > >> Errr............ you'd better use the BSWAP instruction........ same >result >> with one line of assembly............ >> >BSWAP is an x86 instruction :) Not much good if you wanna swap bytes on the >Mac. > >Possibly there is a Mac equivelent, but I think it is RISC practice to avoid >such instructions. > >Conor Stokes > > >_______________________________________________ >GDAlgorithms-list mailing list >GDA...@li... >http://lists.sourceforge.net/mailman/listinfo/gdalgorithms-list > |
From: Aaron D. <ri...@ho...> - 2000-07-18 02:29:04
|
It looks like the way this is meant to work is that it swaps the top and bottom 16 bits then proceeds to do the old 3 xor byte swapping trick (x^=y^=x) for each of the two 16 bit segments but I think the code is a little bit broken. I can't see how that second bit works. -----Original Message----- From: brian sharon <br...@hu...> To: gda...@li... <gda...@li...> Date: Tuesday, 18 July 2000 12:02 Subject: Re: [Algorithms] Byte Swapping > >> From: Charles Bloom <cb...@cb...> >> >> Jumping in late : I'm sure you don't need it now, but >> here's a crazy ANSI C byte-swapper : >> >> let x = a 32 bit ulong , ABCD >> then y = DCBA >> >> y = (x = x>>16 | x<<16) ^ (x = (x^x>>8) & 0x00FF00FF) ^ (x<<8); >> > >wow, I'll say that's crazy...but unfortunately non-functional. see the >results of this program: > >#include <stdio.h> > >long swap1(long x) >{ > return (x = x>>16 | x<<16) ^ (x = (x^x>>8) & 0x00FF00FF) ^ (x<<8); >} > >long swap2(long x) >{ > return ((x >> 24) & 0x000000FF) > | ((x >> 8 ) & 0x0000FF00) > | ((x << 8 ) & 0x00FF0000) > | ((x << 24) & 0xFF000000) > ; >} > >int main(int argc, char **argv) >{ > long test = 0x01020304; > > printf("swap1: 0x%08X 0x%08X 0x%08X \n", test, swap1(test), >swap1(swap1(test))); > > printf("swap2: 0x%08X 0x%08X 0x%08X \n", test, swap2(test), >swap2(swap2(test))); >} > >swap1: 0x01020304 0x07000300 0x03000700 >swap2: 0x01020304 0x04030201 0x01020304 > > > >anyway, in case anyone hasn't gotten their fill of this stuff, here is our >comparatively lame byteswapping code that uses those fast swappers on >PowerPC: > >#ifndef _MBSWAP_H_ >#define _MBSWAP_H_ > >// swapping macros/inlines >#include <Runtime/MBBase.h> > >inline MBint16 MBSwap(const MBint16 & swap) >{ >#if defined(MB_MAC) && defined(MB_POWERPC) > return __lhbrx(const_cast<MBint16 *>(&swap), 0); >#else > return ((swap >> 8 ) & 0x00FF) > | ((swap << 8 ) & 0xFF00) > ; >#endif >} > >inline MBuint16 MBSwap(const MBuint16 & swap) >{ >#if defined(MB_MAC) && defined(MB_POWERPC) > return __lhbrx(const_cast<MBuint16 *>(&swap), 0); >#else > return ((swap >> 8 ) & 0x00FF) > | ((swap << 8 ) & 0xFF00) > ; >#endif >} > >inline MBint32 MBSwap(const MBint32 & swap) >{ >#if defined(MB_MAC) && defined(MB_POWERPC) > return __lwbrx(const_cast<MBint32 *>(&swap), 0); >#else > return ((swap >> 24) & 0x000000FF) > | ((swap >> 8 ) & 0x0000FF00) > | ((swap << 8 ) & 0x00FF0000) > | ((swap << 24) & 0xFF000000) > ; >#endif >} > >inline MBuint32 MBSwap(const MBuint32 & swap) >{ >#if defined(MB_MAC) && defined(MB_POWERPC) > return __lwbrx(const_cast<MBuint32 *>(&swap), 0); >#else > return ((swap >> 24) & 0x000000FF) > | ((swap >> 8 ) & 0x0000FF00) > | ((swap << 8 ) & 0x00FF0000) > | ((swap << 24) & 0xFF000000) > ; >#endif >} > >inline MBfloat MBSwap(const MBfloat & swap) >{ > MBuint32 temp = *(const MBuint32*)&swap; > temp = MBSwap(temp); > return *(const MBfloat *)&temp; >} > >#ifdef MB_MSB > > #define MBSwapMSBToNative( s ) s > #define MBSwapNativeToMSB( s ) s > > #define MBSwapLSBToNative MBSwap > #define MBSwapNativeToLSB MBSwap > >#elif defined(MB_LSB) > > #define MBSwapLSBToNative( s ) s > #define MBSwapNativeToLSB( s ) s > > #define MBSwapMSBToNative MBSwap > #define MBSwapNativeToMSB MBSwap > >#endif > >#endif // header guard > > > >_______________________________________________ >GDAlgorithms-list mailing list >GDA...@li... >http://lists.sourceforge.net/mailman/listinfo/gdalgorithms-list > |
From: Charles B. <cb...@cb...> - 2000-07-18 02:50:48
|
Hmm... I'm not sure what's wrong with it, it's some C order of operations problem that I'm not familiar with. If you expand it out into simple steps : y = x = (x>>16)|(x<<16); y ^= (x = ((x^(x>>8)) & 0x00FF00FF)); y ^= (x<<8); then it works just fine. If you have four bytes ABCD, the first line turns them into CDAB. The second line gives you (0D0B^0C0A). The last line is thus (D0B0^C0A0). Put them all together : y = CDAB^0D0B^0C0A^D0B0^C0A0 = DCBA Anyway, this is all just a curiosity because I don't think that's the most efficient way to do it :^) At 12:36 PM 7/18/2000 +1000, you wrote: >It looks like the way this is meant to work is that it swaps the top and >bottom 16 bits then proceeds to do the old 3 xor byte swapping trick >(x^=y^=x) for each of the two 16 bit segments but I think the code is a >little bit broken. I can't see how that second bit works. > > >-----Original Message----- >From: brian sharon <br...@hu...> >To: gda...@li... ><gda...@li...> >Date: Tuesday, 18 July 2000 12:02 >Subject: Re: [Algorithms] Byte Swapping > > >> >>> From: Charles Bloom <cb...@cb...> >>> >>> Jumping in late : I'm sure you don't need it now, but >>> here's a crazy ANSI C byte-swapper : >>> >>> let x = a 32 bit ulong , ABCD >>> then y = DCBA >>> >>> y = (x = x>>16 | x<<16) ^ (x = (x^x>>8) & 0x00FF00FF) ^ (x<<8); >>> >> >>wow, I'll say that's crazy...but unfortunately non-functional. see the >>results of this program: >> >>#include <stdio.h> >> >>long swap1(long x) >>{ >> return (x = x>>16 | x<<16) ^ (x = (x^x>>8) & 0x00FF00FF) ^ (x<<8); >>} >> >>long swap2(long x) >>{ >> return ((x >> 24) & 0x000000FF) >> | ((x >> 8 ) & 0x0000FF00) >> | ((x << 8 ) & 0x00FF0000) >> | ((x << 24) & 0xFF000000) >> ; >>} >> >>int main(int argc, char **argv) >>{ >> long test = 0x01020304; >> >> printf("swap1: 0x%08X 0x%08X 0x%08X \n", test, swap1(test), >>swap1(swap1(test))); >> >> printf("swap2: 0x%08X 0x%08X 0x%08X \n", test, swap2(test), >>swap2(swap2(test))); >>} >> >>swap1: 0x01020304 0x07000300 0x03000700 >>swap2: 0x01020304 0x04030201 0x01020304 >> >> >> >>anyway, in case anyone hasn't gotten their fill of this stuff, here is our >>comparatively lame byteswapping code that uses those fast swappers on >>PowerPC: >> >>#ifndef _MBSWAP_H_ >>#define _MBSWAP_H_ >> >>// swapping macros/inlines >>#include <Runtime/MBBase.h> >> >>inline MBint16 MBSwap(const MBint16 & swap) >>{ >>#if defined(MB_MAC) && defined(MB_POWERPC) >> return __lhbrx(const_cast<MBint16 *>(&swap), 0); >>#else >> return ((swap >> 8 ) & 0x00FF) >> | ((swap << 8 ) & 0xFF00) >> ; >>#endif >>} >> >>inline MBuint16 MBSwap(const MBuint16 & swap) >>{ >>#if defined(MB_MAC) && defined(MB_POWERPC) >> return __lhbrx(const_cast<MBuint16 *>(&swap), 0); >>#else >> return ((swap >> 8 ) & 0x00FF) >> | ((swap << 8 ) & 0xFF00) >> ; >>#endif >>} >> >>inline MBint32 MBSwap(const MBint32 & swap) >>{ >>#if defined(MB_MAC) && defined(MB_POWERPC) >> return __lwbrx(const_cast<MBint32 *>(&swap), 0); >>#else >> return ((swap >> 24) & 0x000000FF) >> | ((swap >> 8 ) & 0x0000FF00) >> | ((swap << 8 ) & 0x00FF0000) >> | ((swap << 24) & 0xFF000000) >> ; >>#endif >>} >> >>inline MBuint32 MBSwap(const MBuint32 & swap) >>{ >>#if defined(MB_MAC) && defined(MB_POWERPC) >> return __lwbrx(const_cast<MBuint32 *>(&swap), 0); >>#else >> return ((swap >> 24) & 0x000000FF) >> | ((swap >> 8 ) & 0x0000FF00) >> | ((swap << 8 ) & 0x00FF0000) >> | ((swap << 24) & 0xFF000000) >> ; >>#endif >>} >> >>inline MBfloat MBSwap(const MBfloat & swap) >>{ >> MBuint32 temp = *(const MBuint32*)&swap; >> temp = MBSwap(temp); >> return *(const MBfloat *)&temp; >>} >> >>#ifdef MB_MSB >> >> #define MBSwapMSBToNative( s ) s >> #define MBSwapNativeToMSB( s ) s >> >> #define MBSwapLSBToNative MBSwap >> #define MBSwapNativeToLSB MBSwap >> >>#elif defined(MB_LSB) >> >> #define MBSwapLSBToNative( s ) s >> #define MBSwapNativeToLSB( s ) s >> >> #define MBSwapMSBToNative MBSwap >> #define MBSwapNativeToMSB MBSwap >> >>#endif >> >>#endif // header guard >> >> >> >>_______________________________________________ >>GDAlgorithms-list mailing list >>GDA...@li... >>http://lists.sourceforge.net/mailman/listinfo/gdalgorithms-list >> > > >_______________________________________________ >GDAlgorithms-list mailing list >GDA...@li... >http://lists.sourceforge.net/mailman/listinfo/gdalgorithms-list > > -------------------------------------- Charles Bloom www.cbloom.com |
From: Peter D. <pd...@mm...> - 2000-07-18 15:52:28
|
> Hmm... I'm not sure what's wrong with it, it's some C order of operations > problem > that I'm not familiar with. The code assigns to x several times without an intervening sequence point and invokes undefined behavior. The compiler is free to do the assignments to x in any order. -- Peter Dimov Multi Media Ltd. |
From: Daniel K. <Dan...@ix...> - 2000-07-18 09:42:06
|
Hi Listizens, well, if you look at the line y = (x = x>>16 | x<<16) ^ (x = (x^x>>8) & 0x00FF00FF) ^ (x<<8); especially at the first xor op (x = x>>16 | x<<16) ^ (x = (x^x>>8) & 0x00FF00FF) then you see that the result of the first assignment (x = x>>16 | x<<16), let's call it 'z' is used in the calculation of the second term (x = (x^x>>8) & 0x00FF00FF) or (x = (z^z>>8) & 0x00ff00ff) The new result will overwrite the old content of x (which was z), i.e. the whole operation y = (x = x>>16 | x<<16) ^ (x = (x^x>>8) & 0x00FF00FF) ^ (x<<8) doesnt equal y = z ^ x ^ (x<<8) as expected but y = x ^ x ^ (x<<8) which basically is y = 0 ^(x<<8) = (x<<8) ! That gets us x = 0x01020304 new x #1 (=z) = 0x03040102 new x #2 = (0x03040102 ^ 0x00030401) & 0x00ff00ff = 0x00070003 y = 0 ^ (0x00070003<<8) = 0x07000300. When you write it as y = x = (x>>16)|(x<<16); y ^= (x = ((x^(x>>8)) & 0x00FF00FF)); y ^= (x<<8); the 'z' from above is stored in 'y' as well. That's why the threeliner gives the correct result... Cheers, Daniel. > -----Original Message----- > From: Charles Bloom [mailto:cb...@cb...] > Sent: Tuesday, July 18, 2000 4:50 AM > To: gda...@li... > Subject: Re: [Algorithms] Byte Swapping > > > > Hmm... I'm not sure what's wrong with it, it's some C order > of operations > problem > that I'm not familiar with. If you expand it out into simple steps : > > y = x = (x>>16)|(x<<16); > y ^= (x = ((x^(x>>8)) & 0x00FF00FF)); > y ^= (x<<8); > > then it works just fine. If you have four bytes ABCD, the first line > turns them into CDAB. The second line gives you (0D0B^0C0A). The > last line is thus (D0B0^C0A0). Put them all together : > > y = CDAB^0D0B^0C0A^D0B0^C0A0 = DCBA > > Anyway, this is all just a curiosity because I don't think that's the > most efficient way to do it :^) > > At 12:36 PM 7/18/2000 +1000, you wrote: > >It looks like the way this is meant to work is that it swaps > the top and > >bottom 16 bits then proceeds to do the old 3 xor byte swapping trick > >(x^=y^=x) for each of the two 16 bit segments but I think > the code is a > >little bit broken. I can't see how that second bit works. > > > > > >-----Original Message----- > >From: brian sharon <br...@hu...> > >To: gda...@li... > ><gda...@li...> > >Date: Tuesday, 18 July 2000 12:02 > >Subject: Re: [Algorithms] Byte Swapping > > > > > >> > >>> From: Charles Bloom <cb...@cb...> > >>> > >>> Jumping in late : I'm sure you don't need it now, but > >>> here's a crazy ANSI C byte-swapper : > >>> > >>> let x = a 32 bit ulong , ABCD > >>> then y = DCBA > >>> > >>> y = (x = x>>16 | x<<16) ^ (x = (x^x>>8) & 0x00FF00FF) ^ (x<<8); > >>> > >> > >>wow, I'll say that's crazy...but unfortunately > non-functional. see the > >>results of this program: > >> > >>#include <stdio.h> > >> > >>long swap1(long x) > >>{ > >> return (x = x>>16 | x<<16) ^ (x = (x^x>>8) & > 0x00FF00FF) ^ (x<<8); > >>} > >> > >>long swap2(long x) > >>{ > >> return ((x >> 24) & 0x000000FF) > >> | ((x >> 8 ) & 0x0000FF00) > >> | ((x << 8 ) & 0x00FF0000) > >> | ((x << 24) & 0xFF000000) > >> ; > >>} > >> > >>int main(int argc, char **argv) > >>{ > >> long test = 0x01020304; > >> > >> printf("swap1: 0x%08X 0x%08X 0x%08X \n", test, swap1(test), > >>swap1(swap1(test))); > >> > >> printf("swap2: 0x%08X 0x%08X 0x%08X \n", test, swap2(test), > >>swap2(swap2(test))); > >>} > >> > >>swap1: 0x01020304 0x07000300 0x03000700 > >>swap2: 0x01020304 0x04030201 0x01020304 > >> > >> > >> > > > [snip] > |
From: Tom H. <to...@3d...> - 2000-07-16 06:56:57
|
At 08:42 AM 7/16/2000 +0200, you wrote: > > I can do the obvious method, but I was wondering if anyone have any > > cool/fast code snippets for byte swapping integers and floats? > >Depends on the platform. PowerPCs have "load word byte-reversed indexed" >(lwbrx) and "load halfword byte-reversed indexed" (lhbrx) instructions, >for instance. Since that happens to be my platform, perhaps you would have some routines handy that work in Codewarrior for the Mac that make those calls to reverse the bytes I'm loading? Tom |