|
|
I'm writing that article now. =)
I'm not too interested in making the stack smaller on the x64 because I can't think of a great use case for that.
I'm interested in making it smaller on the AMTel AVR 8-bit monsters, the 32-bit Tensilica XTensa LX6 variants, and the ARM Cortex-M line processors because there are a number of issues primarily around the low cost, and low capabilities of these processors. There's usually so little ram (8kB to 320kb depending on the system) that the programs themselves are run off of flash PSRAM which is slow, and so at least on the XTensa it will cache potions of the program in RAM that are called frequently. This is like a much less sophisticated L1 cache system but even more important because flash I/O over an SPI serial bus makes you want to get out and push.
The problem is you only have 320kB to work with (307kB in the wild, I've found after it "boots") and you can't waste it on nonsense. Including stack canaries.
But I also can't have a lot of code around because of the cache issue. I at least need great locality, and the the degree that I'm not sure how exceptions interfere with I am assuming they will negatively impact it. It's more caution in my ignorance than anything, but even if I was more confident, I don't like the extra hidden stuff that exceptions introduce in terms of code flow and stack space, and potentially locality and goddess knows what else (what will throwing an exception from an ISR routine do?!) I'd just as soon write my code so as not to use them.
Real programmers use butterflies
|
|
|
|
|
I too am still using C++17 - and you can still use constexpr in a lot of places, just not quite as many as with C++20 (and you don't have concepts). In my latest project (it's not exactly embedded, but it's an emulator running on Windows for an embedded processor with attached UARTs and other devices), I have things like a CRC with lookup table that is generated at compile-time using constexpr functions (which means those functions can be unit tested and debugged at runtime by passing non-constexpr parameters), a whole set of bitmask and bitfield register functions that do as much work as possible at compile-time to ensure that a) bit-mask constants can be used in a constexpr context, and b) bit-field registers do as little as possible at runtime.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Stuart Dootson wrote: a whole set of bitmask and bitfield register functions that do as much work as possible at compile-time to ensure that a) bit-mask constants can be used in a constexpr context
This is exactly what I'm doing right now with my pixel library. Made extra difficult for the fact that in certain cases (like with 1 bit monochrome) I am not reading and writing on byte boundaries, but *bit* boundaries
mono1_t::int_type value = mono1_t::get_pixel((const uint8_t*)bitmap, index);
Mono is the easy case.
Consider an 18-bit color format (shockingly common)
rgb666be_t::int_type value = rgb666be_t::get_pixel((const uint8_t*)bitmap, index);
where index = 17.
And I'm trying to compute everything needed to do this stuff at compile time.
These ones are fun.
Real programmers use butterflies
|
|
|
|
|
honey the codewitch wrote: Made extra difficult for the fact that in certain cases (like with 1 bit monochrome) I am not reading and writing on byte boundaries, but bit boundaries
Same here - I've got control registers like this:
Bit Number | Label | Value |
---|
31..13 | Not Used | - | 12 | Table Entry Lock | 0 = Unlocked 1 = Locked | 11..9 | Not Used | - | 8 | Page Access | 0 = Enabled 1 = Disabled | 7..6 | Data Bus Width | 01b = 16-bit 10b = 32-bit | 5..0 | Wait States Setting | 000000b = 0 Wait States 000001b = 1 Wait State … 111110b = 62 Wait States 111111b = 63 Wait States
|
I'm modelling each bit-field with a struct templatised on its bit locations, each register with a templatised list of bit-fields - something like this:
using bf1 = bit_field_t<21, 10>;
using bf2 = bit_field_t<31, 24>;
using bf3 = bit_field_t<0, 0>;
using bf4 = bit_field_t<1, 1>;
using bf5 = bit_field_t<2, 2>;
using bf6 = bit_field_t<3, 3>;
using bf7 = bit_field_t<4, 8>;
using bf9 = bit_field_t<6, 6>;
using reg1_t = bit_field_register_t<bf1, bf2, bf3, bf4, bf5, bf6, bf7>;
using reg2_t = bit_field_register_t<bf1, bf2, bf3, bf4, bf5, bf6, bf9>;
(Why all the types? So the compiler can detect attempts to access incorrect bit-fields).
Each field of a bit-field register can be manipulated like so:
int foo(reg1_t *r1) {
r1->insert<bf1>(123);
return r1->extract<bf7>();
}
and that code compiles to the following on AMD64 targets:
mov eax, dword ptr [rdi]
mov ecx, eax
and ecx, -4193281
or ecx, 125952
mov dword ptr [rdi], ecx
shr eax, 4
and eax, 31
ret
This isn't intended for memory-mapped registers (as I said - it's an emulation of that), but could probably be used for that with a few mods.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
That's cool. I'm sitting here super impressed by the compiler right now as I haven't done any hand optimizations to this yet except special casing when the pixel is represented natively (can be cast directly to the destination buffer):
constexpr inline static int_type at(const uint8_t* bitmap,size_t index) {
if(native_int) {
const size_t offs = index;
return order_guard(*(((int_type*)bitmap)+offs));
}
const size_t ofsb=((index*bit_depth)/8);
bitmap+=ofsb;
const size_t ofsm=(index*bit_depth)-(ofsb*8);
int_type result = 0;
uint8_t dat = *(bitmap);
for(size_t i = 0;i<bit_depth;++i) {
const size_t bit = 7-((ofsm+i)&7);
const uint8_t msk = (1<<bit);
const bool mov = bit==7;
result<<=1;
result|=(0!=(dat&msk));
if(mov) dat=*(++bitmap);
}
return order_guard(result);
}
... (below is from main)
typedef channel_traits<channel_name::V,channel_kind::luminosity,uint8_t,1> mono_1bit_luminosity_channel_t;
typedef pixel<color_model::none, false, mono_1bit_luminosity_channel_t> mono1_t;
uint16_t data=0xCCCC;
for(size_t x=0;x<16;++x) {
auto val = mono1_t::at((uint8_t*)&data,x);
printf("%d",val);
}
printf("\r\n");
return 0;
Nevertheless, the assembly is better than i expected (this is the entire main but it pretty much goes from .L2:
main:
push rbp
mov ebp, 1
push rbx
xor ebx, ebx
sub rsp, 24
mov WORD PTR [rsp+14], -13108
.L2:
mov rcx, rbx
mov rdx, rbx
mov eax, ebp
xor esi, esi
not rcx
shr rdx, 3
mov edi, OFFSET FLAT:.LC0
and ecx, 7
sal eax, cl
test BYTE PTR [rsp+14+rdx], al
setne sil
xor eax, eax
inc rbx
call printf
cmp rbx, 16
jne .L2
mov edi, OFFSET FLAT:.LC1
call puts
add rsp, 24
xor eax, eax
pop rbx
pop rbp
ret
Edit: VS Code (at least under Linux undoes clipboard copy commands when you use undo! )
I don't care that it's not optimized yet because I've set the code up where I can optimize by adding if statements which will always be settled at compile time.
Real programmers use butterflies
modified 15-Mar-21 10:35am.
|
|
|
|
|
But did you find the limerick?
Truth,
James
|
|
|
|
|
In a freak accident today, a photographer was killed when a huge lump of cheddar landed on him.
To be fair though, the people who were being photographed did try to warn him.
|
|
|
|
|
Cheesy.
|
|
|
|
|
I would prefer stilton (and a glass of port to go with it)
|
|
|
|
|
Andy stares right back at me,
Slack jawed sunglasses and Warhol effects
over Campbell's Soup SPI by way of TFT
it's everything i've come to expect
it's the last thing he'll ever see
the transmission stumbles,
the DC pin goes low
everything wrong is right again
and the data starts to flow
RST goes high and
and Andy's smirking face is erased in a blaze
of pain and
of collapsing transistor gates
the dance of bits in the end ruined like
the cadence and rhyme of this poem.
*smashes everything around me to punctuate the piece*
The wreckage[^]
Real programmers use butterflies
modified 12-Mar-21 15:17pm.
|
|
|
|
|
Computing by Warhol!
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Are all chicken coops militarily backed?
"I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
"Common sense is so rare these days, it should be classified as a super power" - Random T-shirt
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Do you know feather that rumor is a load of spur-ious crop? It's always easy to peck on the military, their fife's and drum-sticks.
(Did Colonel Sanders influence your post?)
Ravings en masse^ |
---|
"The difference between genius and stupidity is that genius has its limits." - Albert Einstein | "If you are searching for perfection in others, then you seek disappointment. If you seek perfection in yourself, then you will find failure." - Balboos HaGadol Mar 2010 |
|
|
|
|
|
|
(I'm waiting for Steve Austin.)
|
|
|
|
|
Now I've got that silly "bionic" sound as an earworm!
|
|
|
|
|
|
Woodkid - Iron[^]
Google recommended some Metalhammer article to me last week, 10 pop song black metal fans should listen to.
The 10 songs had absolutely nothing to do with black metal.
For example, Portishead and Kanye West were on it.
The rationale was that these songs were "emotional, just like good black metal."
Ok, so that's a huge stretch, but whatever, it's not like all 10 songs sucked (some did).
In fact, this one song stuck around in my playlist.
Awesome song, or as the Metalhammer guy describes it "Melancholia and introspection. Woodkid finds your emotional wounds, stabs them and twists the knife for good measure."
Not a lot of emotion or stabbing or twisting on my side, but a great song nonetheless!
|
|
|
|
|
Thank you for this. Now added to my playlist.
|
|
|
|
|
Also added. Thanks for pointing it out. Reminds me a bit of Cosmo Sheldrake (who I'm certain I mentioned before).
|
|
|
|
|
Can totally hear it too, nice one!
|
|
|
|
|
|
Interesting, I don't think I've (knowingly) heard the genre before!
It all sounds a bit alike though... Not something I can listen to for two hours
|
|
|
|
|
Tonight is the first I've heard it, too. Some of the 'destruction' music I really liked. But I can't argue that a lot of it was alike.
|
|
|
|
|