0

I'm trying to develop a program on a bare metal architecture (stm32f4 board with ARM cortex-m4f processor). I'm experiencing a strange problem with the ABI call __aebi_idivmod. The call is generated by the compiler because in the code there is multiple use of the % operand.The strange thing is that if I look at the dump of the .elf generated by the compilation using objdump, what I get is:

080080e0 <__aeabi_idivmod>:
 80080e0:   e3510000    cmp r1, #0
 80080e4:   0afffff9    beq 80080d0 <.divsi3_skip_div0_test+0x110>
 80080e8:   e92d4003    push    {r0, r1, lr}
 80080ec:   ebffffb3    bl  8007fc0 <.divsi3_skip_div0_test>
 80080f0:   e8bd4006    pop {r1, r2, lr}
 80080f4:   e0030092    mul r3, r2, r0
 80080f8:   e0411003    sub r1, r1, r3
 80080fc:   e12fff1e    bx  lr

On the other hand when I run the program on the board, if I look at the actual ABI call code using gdb I get:

(gdb) disas __aeabi_idivmod
Dump of assembler code for function __aeabi_idivmod:
   0x080080e0 <+0>:     movs    r0, r0
   0x080080e2 <+2>:     b.n 0x8008788
   0x080080e4 <+4>:         ; <UNDEFINED> instruction: 0xfff90aff
   0x080080e8 <+8>:     ands    r3, r0
   0x080080ea <+10>:    stmdb   sp!, {r0, r1, r4, r5, r7, r8, r9, r10, r11, r12, sp, lr, pc}
   0x080080ee <+14>:            ; <UNDEFINED> instruction: 0xebff4006
   0x080080f2 <+18>:    ldmia.w sp!, {r1, r4, r7}
   0x080080f6 <+22>:    b.n 0x8008100 <__aeabi_ldiv0>
   0x080080f8 <+24>:    asrs    r3, r0, #32
   0x080080fa <+26>:    b.n 0x8008180 <K+120>
   0x080080fc <+28>:    vrhadd.u16  d14, d14, d31
End of assembler dump.

The location of the code corresponds, but it is completely wrong: there are two instructions that are not even recognized by gdb and the second instruction:

0x080080e2 <+2>:        b.n 0x8008788

is jumping outside of the .text section of the process that ends at 0x866c:

Loading section .text, size 0x866c lma 0x8000000

Any clue about I'm doing wrong? Any help would be appreciated.

EDIT: I'm using this compiler: https://launchpad.net/gcc-arm-embedded/+download

arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.8.3 20131129 (release)     [ARM/embedded-4_8-branch revision 205641]

EDIT2 (following the response of Notlikethat): The command that I use to link my program is this:

$(ARMGNU)-ld -o program.gcc.thumb.elf -T memmap vectors.o program.gcc.thumb.o   $(OBJS2)     $(LIBGCC)

memmap is the linker script, vectors.o contains startup code, $(OBJS2) contains all the object files that must be linked together and $(LIBGCC) is the variable referencing the library containing the ABI call that we're discussing. From what I've understood from the comment of Notlikethat I should add some option here, to force the compilation of the libgcc to thumb code instead of normale ARM code. I've tried to add to the linker these options, but I'm getting the same error in both cases:

arm-none-eabi-ld: unrecognised emulation mode: cpu=cortex-m3
Supported emulations: armelf

EDIT3: I have realized only in this moment that the processor of my board is cortex-m4f not cortex-m3. I don't think this should not make much different.

user3768186
  • 5
  • 1
  • 5
  • Well, that disassembly is ARM instructions, which make no sense when the M3 tries to execute them as Thumb. What compiler/library are you using? (other than "the wrong one") – Notlikethat Jun 23 '14 at 17:01
  • Thank you for the answer, I will update the post with the required informations. Anyway I'm using this compiler: https://launchpad.net/gcc-arm-embedded/+download and the libraries provided with it. – user3768186 Jun 23 '14 at 17:58
  • Moreover, I don't know ARM assembly so deeply to be able to distinguish between normal ARM instructions and Thumb instructions, but I have compiled all the files using -mthumb option, so they should be compiled to Thumb instructions. – user3768186 Jun 23 '14 at 18:08

1 Answers1

0

The problem is that your toolchain, by default, has its standard library compiled to ARM instructions - since the Cortex-M processors only support Thumb-2*, they will fault when attempting to use an interworking branch to ARM code.

Now, the -mthumb option tells the compiler to compile your code to Thumb - the standard library is pre-compiled and doesn't even come into the picture until link time. Fortunately, the readme says that toolchain is multilib enabled, so you can pick a suitable library without having to find a v7-M-specific toolchain.

From what I understand of the inner workings of multilib, you have to provide the exact magic combination of options it's looking for, which in this case would be either:

-mthumb -mcpu=cortex-m4

or:

-mthumb -march=armv7e-m

which will cause GCC to give the linker a suitably compatible library instead of the default (there are further options listed in the docs if you need floating-point support too).

If you're using a seperate link step, I believe you need to use gcc as the link command in place of ld for multilib to work correctly - that's certainly the case for the Linaro toolchain I have here (which only has two-way hard-float/ARMv4+soft-float multilib).


* strictly, not-quite-all-of-Thumb-2

Notlikethat
  • 20,095
  • 3
  • 40
  • 77
  • First of all thank you for your answer, I was unaware of this fact. Since the space for the comment doesn't fit my reply, I will update my post up there. – user3768186 Jun 23 '14 at 20:36
  • @user3768186 Updated the answer. I omitted the cross-compiler prefix for clarity, but obviously you still need that. The host `gcc` won't work ;) – Notlikethat Jun 23 '14 at 22:07
  • Yes I'm using a separate link step, for the moment I've solved passing to the linker the correct libgcc (actually the error was due to the fact that I was passing the wrong one). I know that this is not ideal and the correct solution is the one suggested by you. – user3768186 Jun 24 '14 at 06:08