Hi David,
W dniu 3.07.2023 o 16:52, David Brown pisze:
[------------]
But, before I dive into learning C++ (forgive the naive question)....
isn't it so, that C++ comes with a heavy runtime? One that will bloat
my tiny project? Or the bloat comes only when one uses particular
elaborated class/inheritance scenarios, and this particular case ( for
(...; ...; x = x->next) {} ) will not draw any of that into this project?
Let me make a few points (in no particular order) :
1. For some RISC targets, such as PowerPC, it is common to have a
section of memory called the "small data section". One of the registers
is dedicated as an anchor to this section, and data within it is
addressed as Rx + 16-bit offset. But this is primarily for data at
fixed (statically allocated) addresses, since reads and writes using
this address mode are smaller and faster than full 32-bit addresses.
Normal pointers are still 32-bit. It also requires a dedicated register
- not a big cost when you have 31 GPRs, but much more costly when you
have only 13.
I don't have any experience with PowerPC, all you say here is new to me.
And PPC architecture today is "kind of exotic", but I appreciate the
info and I may look it up for insight how "short pointers" influence
performance. Thenx.
2. C++ is only costly if you use costly features. On small embedded
systems, you want "-fno-exceptions -fno-rtti", and you will get as good
(or bad!) results for C++ as for C. Many standard library features
will, however, result in a great deal of code - it is usually fairly
obvious which classes and functions are appropriate.
OK. I become aware, that I will no longer be able to turn a blind eye on
C++. :(
3. In C, you could make a type such as :
typedef struct {
uint16_t p;
} small_pointer_t;
and conversion functions :
static const uintptr_t ram_base = 0x20000000;
static inline void * sp_to_voidp(small_pointer_t sp) {
return (void *)(ram_base + sp);
}
static inline small_pointer_t voidp_to_sp(void * p) {
small_pointer_t sp;
sp.p = (uintptr_t) p - ram_base;
return sp;
}
Then you would use these access functions to turn your "small pointers"
into normal pointers. The source code would become significantly harder
to read and write, and less type-safe, but could be quite efficient.
That actually is a problem. I really can make a lot of the code in
question into an assembler, and have it behave precisely as I desire,
but that'll make the project not portable - that's why I though of
casting the use case onto this list here. This way (I hoped) it may
inspire "the world" and have it supported at compiler level some time in
the future. Should it not be the case, I'd rather stay with "plain C"
and keep the code portable and readable (rather then obfuscate it ...
even by merely too "talkative sources").
[--------]
to ram and to peripheral groups. This mailing list is not really the
place to work through an implementation of such class templates - but it
certainly could be done.
OK. I fully agree.
FYI: it was never my intention to inquire for advice of how to cook such
"short/funny" pointers by special constructs / technic in c-programming.
Actually I was a little set back reading such advice as first responses
to my email. It was nice, but surprising.
I hoped to get a discussion more towards "how to let compiler know",
that a particular segment/section of a program-data will be emitted into
an executable in a "constraint output section", so that compiler could
"automagicly" know, that using "short" pointers for that data would
suffice, and in consequence would generate such instructions.... without
any change to the source code.
It's sort of obvious, that this would also require support from libc
(like a specific "malloc()" and friends), but application sources could
stay untouched, and that's IMHO key point here.
4. It is worth taking a step back, and thinking about how you would like
to use these pointers. It is likely that you would be better thinking
in terms of an array, rather than pointers - after all, you don't want
to be using dynamically allocated memory here if you can avoid it, and
certainly not generic malloc(). If you can use an array, then your
index type can be as small as you like - maybe uint8_t is enough.
I did that trip ... some time ago. May be I discarded the idea
prematurely, but I dropped it because I was afraid of cost of
multiplication (index calculation) in micros. That my "assumption" may
actually not be true, since today even the mini-minis often have integer
multiplication units, so my reasoning became false.
But. Even if I turn pointers into indices for tiny micros ... that'd
make the code not portable. I'm not to eager to do that.
Still, thank you very much for sharing those concepts.
With best regards,
-R