using toolchains:
"gcc-arm-none-eabi-9-2020-q2-update"
build cmd:
"arm-none-eabi-gcc -MMD -g -Wno-discarded-qualifiers -O0 -mcpu=cortex-r52 -c -DGCC -mthumb -mfloat-abi=hard -mfpu=fp-armv8 -nostartfiles -ffreestanding -falign-functions=16 -falign-jumps=8 -falign-loops=8 -fomit-frame-pointer -funroll-loops printf.c -o printf.o"
Found that the code:
printf("test hex long number = 0x%lx\n", 0x123456789abcdef0ul);
Compiled as:
401372: a315 add r3, pc, #84 ; (adr r3, 4013c8 <printf_test+0xd8>)
401374: e9d3 2300 ldrd r2, r3, [r3]
401378: f245 201c movw r0, #21020 ; 0x521c
40137c: f2c0 0040 movt r0, #64 ; 0x40
401380: f7ff ff76 bl 401270 <_printf>
Why not use "r1" register as params delivery? That make "_printf" print unexpected.
test hex long number = 0x9abcdef000000000
How to fix or workaround? Let "_printf" print as expected "0x123456789abcdef0"
The use of r2/r3
is correct. The AAPCS ABI specifies that 8-byte objects (or more precisely, objects needing 8-byte alignment) shall be passed in an even/odd register pair. See Section 6.3 stage C3. This is most likely so that ldrd/strd
can be used, as they have this same restriction.
The bug in your program is that 0x123456789abcdef0ul
is of type unsigned long long
despite the ul
suffix, since it is too large for the 32-bit unsigned long
. As such you need to use the %llx
format specifier with it. If you do, then printf
will correctly find the argument in r2/r3
and everything works fine.
With the code as it is, you ought to get a compiler warning about the format specifier not matching the argument type.