Hi,

On Wed, Nov 6, 2024 at 7:13 AM Tomek CEDRO <to...@cedro.info> wrote:

>
> Nathan you mentioned the 8-bit and 16-bit platforms to use 32-bit
> unsigned. That would imply "virtual" type not natively supported by
> platform. Do you know what is the penalty for using such types? Is it
> safe? Does it work on all compilers? Is it slow? if no, then maybe we
> could also use int64_t on 32-bit platforms? :-P
>

It's safe, widely supported by compilers, and "slow" in that multiple
instructions will be used to support the operation instead of just one, and
multiple registers will carry the value instead of just one.

There's a penalty for it, but it's not really straightforward. Considering
a Cortex-M0 based processor, arithmetic operations on 64-bit values will
usually just be two or three instructions instead of one (eg, UMULL+MLA for
a 64-bit multiply for one operand 32-bit or less, or UMULL+MLA+MLA for two
64-bit operands). The real penalty kicks in for function arguments, though.
The common ARM calling convention reserves only four 32-bit registers for
function arguments, so passing three 32-bit arguments is entirely in
registers but passing three 64-bit arguments will put two 32-bit words on
the stack. Similarly, only registers r0-r3 and r12 can be used freely while
r4-r11 must have their values preserved. A function doing almost anything
with a 64-bit value is likely to use more than five registers and will need
to push and pop values.

You can see the difference in compiled output for a 32-bit function doing a
* b + c and a 64-bit function doing the same here:
https://godbolt.org/z/8bKj6an4z

As it happens the ARMv7 instruction set is designed to handle 64-bit values
with a minimum of fuss. For giggles try changing the compiler used by
godbolt to AVR GCC, where 64-bit multiplication is implemented as a libcall
and the ABI requires that 18 or so registers get preserved by the callee if
their contents can't be guaranteed to be non-volatile.

I don't think, personally, that any of this is reason enough to worry about
it. Using an int64_t for time_t is IMO a perfectly reasonable default for
32-bit and up targets. and possibly for all targets. Offering a kconfig
option to support 32-bit (signed or unsigned) time_t offers an easy
work-around should anyone find that the couple of percent increase in code
size and execution time causes their project to fail - or if anyone is in
the unfortunate situation where they depend on code that's made assumptions
about size or signedness.

-- 
Byron

Reply via email to