Page 1 of 2
BSwap64/32/16
Posted: Thu Apr 13, 2023 6:32 am
by Lunasole
Hi again. Just coded that funny bicycle days ago to replace ASM-variants.
There already someone posted others (like using C lib swap functions), but let it be.
PS. Need bswap 8 also
Code: Select all
; 2023 Lunasole
; v 1.0.0.1
; Inverts byte order (BE <> LE)
; RETURN: inverted Quad/Long/Word
Procedure.q BSwap64(LL.q)
ProcedureReturn 255&LL>>56|(255&LL)<<56|(255&LL>>48)<<8|(255&LL>>8)<<48|(255&LL>>40)<<16|(255&LL>>16)<<40|(255&LL>>32)<<24|(255&LL>>24)<<32
EndProcedure
Procedure.l BSwap32(L.l)
ProcedureReturn 255&L>>24|(255&L)<<24|(255&L>>16)<<8|(255&L>>8)<<16
EndProcedure
Procedure.w BSwap16(S.w)
ProcedureReturn 255&S>>8|(255&S)<<8
EndProcedure
CompilerIf #PB_Compiler_IsMainFile
Define C.w = %1010011110010001
Define B.l = %10100111100100011011000110001111
Define A.q = %1010011110010001101100011000000110101101100000001110100110001001
If C = BSwap16(BSwap16(C))
Debug "OK16:"
Else
Debug "ERROR16:"
EndIf
Debug " 16:" + RSet(Bin(C, #PB_Word), 16, "0")
Debug "S16:" + LSet(Bin(BSwap16(C), #PB_Word), 16, "0")
Debug "d16:" + RSet(Bin(BSwap16(BSwap16(C)), #PB_Word), 16, "0")
If B = BSwap32(BSwap32(B))
Debug "OK32:"
Else
Debug "ERROR32:"
EndIf
Debug " 32:" + RSet(Bin(B, #PB_Long), 32, "0")
Debug "S32:" + LSet(Bin(BSwap32(B), #PB_Long), 32, "0")
Debug "d32:" + RSet(Bin(BSwap32(BSwap32(B)), #PB_Long), 32, "0")
If A = BSwap64(BSwap64(A))
Debug "OK64:"
Else
Debug "ERROR64:"
EndIf
Debug " 64:" + RSet(Bin(A, #PB_Quad), 64, "0")
Debug "S64:" + LSet(Bin(BSwap64(A), #PB_Quad), 64, "0")
Debug "d64:" + RSet(Bin(BSwap64(BSwap64(A)), #PB_Quad), 64, "0")
CompilerEndIf
Re: BSwap64/32/16
Posted: Thu Apr 13, 2023 7:23 am
by infratec
Hi,
if I use your code in PB 6.00 x86 on Windows 10 x64 with:
Code: Select all
Debug RSet(Hex(BSwap16($1234), #PB_Unicode), 4, "0")
Debug RSet(Hex(BSwap32($12345678), #PB_Long), 8, "0")
Debug RSet(Hex(BSwap64($123456789ABCDEFF), #PB_Quad), 16, "0")
I get
3412
00563412
00DEBC9A78563412
You forgot some braces:
But since shift operations always fills the shifted bits with 0,
you can simply use this corrected version:
Code: Select all
; 2023 Lunasole
; Inverts byte order (BE <> LE)
; RETURN: inverted Quad/Long/Word
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
CompilerEndIf
Procedure.q BSwap64(LL.q)
ProcedureReturn LL<<56|LL>>56|(255&LL>>48)<<8|(255&LL>>8)<<48|(255&LL>>40)<<16|(255&LL>>16)<<40|(255&LL>>32)<<24|(255&LL>>24)<<32
EndProcedure
Procedure.l BSwap32(L.l)
ProcedureReturn L<<24|L>>24|(255&L>>16)<<8|(255&L>>8)<<16
EndProcedure
Procedure.w BSwap16(S.w)
ProcedureReturn S>>8|S<<8
EndProcedure
CompilerIf #PB_Compiler_IsMainFile
Debug RSet(Hex(BSwap16($1234), #PB_Unicode), 4, "0")
Debug RSet(Hex(BSwap32($12345678), #PB_Long), 8, "0")
Debug RSet(Hex(BSwap64($123456789ABCDEFF), #PB_Quad), 16, "0")
CompilerEndIf
Results in:
3412
78563412
FFDEBC9A78563412
Re: BSwap64/32/16
Posted: Thu Apr 13, 2023 8:14 am
by Lunasole
infratec wrote: Thu Apr 13, 2023 7:23 am
Hm in this test your variant failed
Code: Select all
; 2023 Lunasole
; Inverts byte order (BE <> LE)
; RETURN: inverted Quad/Long/Word
Procedure.q BSwap64(LL.q)
ProcedureReturn (255&LL)<<56|255&LL>>56|(255&LL>>48)<<8|(255&LL>>8)<<48|(255&LL>>40)<<16|(255&LL>>16)<<40|(255&LL>>32)<<24|(255&LL>>24)<<32
EndProcedure
Procedure.l BSwap32(L.l)
ProcedureReturn (255&L)<<24|255&L>>24|(255&L>>16)<<8|(255&L>>8)<<16
EndProcedure
Procedure.w BSwap16(S.w)
ProcedureReturn 255&S>>8|(255&S)<<8
EndProcedure
;;;;
Procedure.q BSwap642(LL.q)
ProcedureReturn LL<<56|LL>>56|(255&LL>>48)<<8|(255&LL>>8)<<48|(255&LL>>40)<<16|(255&LL>>16)<<40|(255&LL>>32)<<24|(255&LL>>24)<<32
EndProcedure
Procedure.l BSwap322(L.l)
ProcedureReturn L<<24|L>>24|(255&L>>16)<<8|(255&L>>8)<<16
EndProcedure
Procedure.w BSwap162(S.w)
ProcedureReturn S>>8|S<<8
EndProcedure
Define C.w = %1010011110010001
Define B.l = %10100111100100011011000110001111
Define A.q = %1010011110010001101100011000000110101101100000001110100110001001
If LSet(Bin(BSwap16(C), #PB_Word), 16, "0") = "1001000110100111"
Debug "OK16"
Else
Debug "ERROR16"
EndIf
Debug "SRC:" + LSet(Bin(C, #PB_Word), 16, "0")
Debug "B16:" + LSet(Bin(BSwap16(C), #PB_Word), 16, "0")
Debug "B162:" + LSet(Bin(BSwap162(C), #PB_Word), 16, "0")
If LSet(Bin(BSwap32(B), #PB_Long), 32, "0") = "10001111101100011001000110100111"
Debug "OK32"
Else
Debug "ERROR32"
EndIf
Debug "SRC:" + LSet(Bin(B, #PB_Long), 32, "0")
Debug "B32:" + LSet(Bin(BSwap32(B), #PB_Long), 32, "0")
Debug "B322:" + LSet(Bin(BSwap322(B), #PB_Long), 32, "0")
If LSet(Bin(BSwap64(A), #PB_Quad),64,"0") = "1000100111101001100000001010110110000001101100011001000110100111"
Debug "OK64"
Else
Debug "ERROR64"
EndIf
Debug "SRC:" + LSet(Bin(A, #PB_Quad), 64, "0")
Debug "B64:" + LSet(Bin(BSwap64(A), #PB_Quad), 64, "0")
Debug "B642:" + LSet(Bin(BSwap642(A), #PB_Quad), 64, "0")
Output I get (your fixes are with extra 2)
Code: Select all
OK16
SRC:1010011110010001
B16:1001000110100111
B162:1111111110100111
OK32
SRC:10100111100100011011000110001111
B32:10001111101100011001000110100111
B322:11111111111111111111111110100111
OK64
SRC:1010011110010001101100011000000110101101100000001110100110001001
B64:1000100111101001100000001010110110000001101100011001000110100111
B642:1111111111111111111111111111111111111111111111111111111110100111
Re: BSwap64/32/16
Posted: Thu Apr 13, 2023 8:56 am
by Lunasole
Lunasole wrote: Thu Apr 13, 2023 8:14 am
Hm in this test your variant failed
While I see my even with some fixes fails on other values

Fk need more fixes and more complex expression
Re: BSwap64/32/16
Posted: Thu Apr 13, 2023 9:27 am
by infratec
The main problem is, that PB does not have unsigned long and quad.
Re: BSwap64/32/16
Posted: Thu Apr 13, 2023 9:53 am
by Lunasole
infratec wrote: Thu Apr 13, 2023 9:27 am
The main problem is, that PB does not have unsigned long and quad.
Anyway those bit operations should work regardless of signed/unsigned, but well need to look better on this all, maybe I already forgot something hah
Re: BSwap64/32/16
Posted: Thu Apr 13, 2023 10:52 am
by Lunasole
Seems fixed this craziness, the problem was with LShift/Rshift priority, now looks working as should

So I farted a bit like old fart.
Added also that test code.
Re: BSwap64/32/16
Posted: Thu Apr 13, 2023 12:12 pm
by infratec
There is still one problem:
If you define D.u and use your tests, it fails, because it compares now signed with unsigned.
To avoid this you need BSwap16w() and BSwap16u() with the correct return types.
Re: BSwap64/32/16
Posted: Thu Apr 13, 2023 12:18 pm
by mk-soft
It was me with the bswap32
ASM und c-backend bswap32
Have you ever thought about doing it the way it is? Byte swap instead of bit shifting
Code: Select all
Structure ArrayOfByte
b.b[0]
EndStructure
Procedure.l bswap32(Value.l)
Protected *pVal.ArrayOfByte
*pVal = @value
Swap *pVal\b[0], *pVal\b[3]
Swap *pVal\b[1], *pVal\b[2]
ProcedureReturn Value
EndProcedure
Val.l = $FF1234EE
r1.l = bswap32(val)
Debug Hex(Val, #PB_Long) + " -> " + Hex(r1, #PB_Long)
Re: BSwap64/32/16
Posted: Thu Apr 13, 2023 1:37 pm
by Lunasole
infratec wrote: Thu Apr 13, 2023 12:12 pm
There is still one problem:
If you define D.u and use your tests, it fails, because it compares now signed with unsigned.
To avoid this you need BSwap16w() and BSwap16u() with the correct return types.
That's right, needs to be changed like you said if needed. Or can use macro instead of procedures here.
mk-soft wrote: Thu Apr 13, 2023 12:18 pm
It was me with the bswap32
ASM und c-backend bswap32
Have you ever thought about doing it the way it is? Byte swap instead of bit shifting
Yes, simply swap bytes is more obvious at all, just liked to play with this a bit^^
I've seen your variants somewhere in search when looked recently (maybe also someone's else in other topics).
What about ASM there is also +1
viewtopic.php?t=14524&hilit=BSwap
Re: BSwap64/32/16
Posted: Sat Apr 15, 2023 2:05 am
by idle
I would suggest this topic
viewtopic.php?p=572356#p572356
The methodology your using is for unsigned types, and the main problem is with the << (shift arithmetic right)
You can do both 32 and 16 bit byte swaps in a quad and mask it off but you can't do the same for 64 bit with that method
Code: Select all
;Macro BSWAP64(v)
; v = ((v >> 8) & $00FF00FF00FF00FF) | ((v & $00FF00FF00FF00FF) << 8) ;flip adjacent bytes
; v = ((v >> 16) & $0000ffff0000ffff) | ((v & $0000ffff0000ffff) << 16) ; flip words
; v = (v >> 32) | (v << 32) ;flip dwords
;EndMacro
Macro BSWAP32(v)
vi.q = v
vi = ((vi >> 8) & $00FF00FF) | ((vi & $00FF00FF) << 8) ;flip adjacent bytes
vi = (vi >> 16) | vi << 16 ;flip words
v = vi & $FFFFFFFF
EndMacro
Macro BSWAP16(v)
vi.q = v
vi = ((vi >> 8) & $00FF) | ((vi & $00FF) << 8) ;flip adjacent bytes
v = vi & $FFFF
EndMacro
or you can use a dirty macro hack to enable unsigned but it only works fasm windows and linux
Code: Select all
;EnableUnsigned v1.0a
;Author Idle 25/3/16
;Supports PB 5.42LTS Window, Linux
;Unsigned arithmetic and logical comparisons for
;x64: Long, Integer, Quads
;x86: Long, Integer
;Usage:
;Scope unsigned arithmetic and logic in EnableUnsigned() DisableUnsigned() blocks
;EnableUnsigned()
;if ux > uy ; changes the operators to unsigned: supports < > <= >= <> =
; do something unsigned: supports * / + - << >>
; DisableUnsigned()
; ;back to signed
;EndIf
;Disableunsigned() ;Note you can call Disableunsigned() where ever you need it
CompilerIf SizeOf(integer) = 4
Macro EnableUnsigned()
!macro IDIV var
!{
!mov edx,0
!div var
!}
!macro IMUL reg,var
!{
!mov eax,reg
!mul var
!mov reg,eax
!}
!macro SAR reg,var
!{
!shr reg,var
!}
!macro SAL reg,var
!{
!shl reg,var
!}
!macro CDQ {}
!macro JG arg
!{
!JA arg
!}
!macro JGE arg
!{
!JAE arg
!}
!macro JL arg
!{
!JB arg
!}
!macro JLE arg
!{
!JBE arg
!}
EndMacro
Macro DisableUnsigned()
!purge IDIV
!purge IMUL
!purge SAR
!purge SAL
!purge CDQ
!purge JG
!purge JGE
!purge JL
!purge JLE
EndMacro
CompilerElse
Macro EnableUnsigned()
!macro IDIV var
!{
!mov rdx,0
!div var
!}
!macro IMUL reg,var
!{
!match =qword x , var
!\{ mov rax, reg
!mov r15, var
!\}
!mul reg
!mov reg,rax
!}
!macro SAR reg,var
!{
!shr reg,var
!}
!macro SAL reg,var
!{
!shl reg,var
!}
!macro MOVSXD reg,var
!{
!match =dword x , var
!\{ mov eax, var
!mov reg,rax \}
!}
!macro CQO {}
!macro CDO {}
!macro CWD {}
!macro CBW {}
!macro CWDE{}
!macro CDQE {}
!macro CDQ {}
!macro JG arg
!{
!JA arg
!}
!macro JGE arg
!{
!JAE arg
!}
!macro JL arg
!{
!JB arg
!}
!macro JLE arg
!{
!JBE arg
!}
EndMacro
Macro DisableUnsigned()
!purge IDIV
!purge IMUL
!purge SAR
!purge SAL
!purge MOVSXD
!purge CQO
!purge CDO
!purge CWD
!purge CBW
!purge CWDE
!purge CDQE
!purge CDQ
!purge JG
!purge JGE
!purge JL
!purge JLE
EndMacro
CompilerEndIf
Macro BSWAP64(v)
v = ((v >> 8) & $00FF00FF00FF00FF) | ((v & $00FF00FF00FF00FF) << 8) ;flip adjacent bytes
v = ((v >> 16) & $0000ffff0000ffff) | ((v & $0000ffff0000ffff) << 16);flip words
v = (v >> 32) | (v << 32) ;flip dwords
EndMacro
Macro BSWAP32(v)
v = ((v >> 8) & $00FF00FF) | ((v & $00FF00FF) << 8) ;flip adjacent bytes
v = (v >> 16) | v << 16 ;flip words
EndMacro
Macro BSWAP16(v)
v = ((v >> 8) & $00FF) | ((v & $00FF) << 8) ;flip adjacent bytes
EndMacro
Global vl.l = $fedcba12; // 32-bit word to reverse bit order
Global vi.i = $FEDCBA9876543210
EnableUnsigned()
bswap32(vl)
bswap64(vi)
DisableUnsigned()
Debug Hex(vl,#PB_Long)
Debug Hex(vi,#PB_Quad)
Re: BSwap64/32/16
Posted: Sun Apr 16, 2023 10:19 am
by Lunasole
Anyway another one variant for this small question (I posted as didn't found here already), I like more this shifts-based idea like it is quite more optimized and there are no risks unless someone mess the types.
Re: BSwap64/32/16
Posted: Sun Apr 16, 2023 12:37 pm
by mk-soft
Lunasole wrote: Sun Apr 16, 2023 10:19 am
Anyway another one variant for this small question (I posted as didn't found here already), I like more this shifts-based idea like it is quite more optimized and there are no risks unless someone mess the types.
Sorry,
But the most optimal method is to use the ASM code or __builtin_xyz.
Re: BSwap64/32/16
Posted: Sun Apr 16, 2023 4:35 pm
by Lunasole
mk-soft wrote: Sun Apr 16, 2023 12:37 pm
Sorry,
But the most optimal method is to use the ASM code or __builtin_xyz.
Yes. ASM is the most optimal, and I didn't said that this one is the most (this one is more optimal comparing to other methods like mentioned here before).
C builtin depends on optimizations probably (and maybe macro like this may be more optimal than calling C subs, maybe not), I haven't need to check this.
Re: BSwap64/32/16
Posted: Sun Apr 16, 2023 5:20 pm
by Lunasole
mk-soft wrote: Sun Apr 16, 2023 12:37 pm
Btw, you variant unfortunately also lacks BSwap8... It's hard to find solution for that.