Swap endian-ness in tools on big endian hosts#329
Conversation
|
@kilograham may feel differently (and his opinion matters much more than mine), but I think it might be simpler to keep everything on the Pico little-endian, and rely on the host-side tools ( (Of course, that's assuming that I'm correctly understanding what this PR is trying to do, which I might not be? 🤷 ) |
|
@lurch I think there may be a misunderstanding here. What the code does it make the data being accessed as little endian, regardless of the systems actual endianness. On a system which is already little endian, such as the Pico itself, this is a no-operation (and in fact the macros will expand to nothing). There is nothing here that will make anything big endian on the Pico. All conversions happen on the host side (and only if the host is big endian). |
Cool, please accept my apologies for my misunderstanding (I'm more of a Python guy than a low-level C guy). Is a similar patch needed for https://github.com/raspberrypi/picotool or does this PR already encompass that? |
|
@lurch Yes, I have a patch for |
|
Just out of curiosity, what big-endian host machine / OS / environment are you using? |
|
@lurch RCS Talos II (POWER9) with Gentoo Linux is my main host. I also have a big endian Raspberry Pi 3. 😸 |
I'd presumed you were on a Dec Alpha or a VAX or some such. Huh. I hadn't quite grokked that the Pi was Bi-endian. |
|
@aallan All ARM-v8 cores from ARM are bi-endian. VAX is little-endian only, though, having been designed in the 1970:s, just like x86. 😆 |
Having used a VAX a lot during my undergrad I have total false memories of it being big endian at that point. Huh. Guess I was brain washed by my many years on Dec Alphas during my postgrad years. 🤷♂️ |
|
can you rebase this on develop |
|
@kilograham Sure thing! |
|
I'm a bit torn over this; scalar_storage_order isn't supported on clang (even gcc mode). I don't believe we have any non target device which touches this which isn't C++ anyway. I'd be tempted perhaps to do (i will keep trying to think of a nice way to do this with typedefs - I guess we can guard with an #ifdef) #ifndef le_uint32_t
#define le_uint32_t uint32_t
#endifin the headers (or in a common one if we have one which works across elf2uf2, picotool, regular build etc) And that way we defer everything to the user. C code, can continue to have to reverse byte orders manually (or wrap the structure with another one which reverses the byte order using scalar_storage_order - if that's what they choose to do) In our C++ we can define |
Ah, ok. In that case at the very least there should be a conditional
Maybe I mistunderstand your point here, but C code compiled for the host using the relevant structs exist in the file
Right, but wouldn't it make sense for |
|
@kilograham I reworked the patch to work along the lines you described. The SDK patch wasn't affected that much. The |
kilograham
left a comment
There was a problem hiding this comment.
a few thoughts; will look at the picotool patch too
| } | ||
| #ifdef __cplusplus | ||
| } | ||
|
|
There was a problem hiding this comment.
note we should only need this for big endian systems... either omit, or make it a no-op on little endian host
There was a problem hiding this comment.
Sure. A modern compiler will in fact already turn this code into a no-op on little endian, but I can put an explicitly no-op version inside an #ifdef.
There was a problem hiding this comment.
(Here's what I mean about the compiler fixing this for you, btw: https://godbolt.org/z/3cTdTYGzY)
There was a problem hiding this comment.
Yeah, I figured, I didn't know they all did so so uniformly... still it is clearer, and some maniacs may use -O0.
| #include <cstdint> | ||
| #include <algorithm> | ||
| #include "pico/platform.h" | ||
| #define le_uint16_t stored_little_endian<uint16_t> |
There was a problem hiding this comment.
this could be in platform.h
There was a problem hiding this comment.
Ok, I guess if you want an alternate implementation you could make your #defines before including pico/platform.h instead of after.
|
Moved to 1.2.1 as I think i want to put the stuff in platform.h after all |
|
We are now carrying this as a patch to the Debian package of pico-sdk so that it works on s390x: https://salsa.debian.org/debian/pico-sdk/-/blob/master/debian/patches/329.patch?ref_type=heads This closes raspberrypi/picotool#104 |
|
FYI, the pico-sdk autopkgtest failed on (big endian) s390x before but with the (rebased) patch from this pull request it passes now: https://ci.debian.net/packages/p/pico-sdk/testing/s390x/47384722/ |
When the host running the SDK is not little endian, all data that is exchanged with the Pico must be converted to/from little endian byte order.
Instead of sprinking explicit swaps around the code, I used available mechanisms for doing the swaps implicitly. Unfortunately, there is no such mechanism that works with both C and C++, so because the code base mixes C and C++ double mechanisms need to be employed...
The C++ fix also suffers from the fact that some structures are declared as
__attribute__((packed)), which requires the contents to be POD. Because of this, thelittle_endiantemplate is not allowed to have a constructor. This is not a problem in the SDK itself, but inpicotoolit would have been convenient to be able to createstd::vector<little_endian<uint32_t>> programwith an initializer.