Вызов ABI для __aeabi_idivmod ведет себя не так, как ожидалось

Я пытаюсь разработать программу на голой металлической архитектуре (плата stm32f4 с процессором ARM cortex-m4f). У меня возникла странная проблема с вызовом ABI __aebi_idivmod. Вызов генерируется компилятором, потому что в коде есть многократное использование операнда %. Странно то, что если я смотрю на дамп .elf, сгенерированный компиляцией с использованием objdump, я получаю следующее:

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

С другой стороны, когда я запускаю программу на плате, если я смотрю на фактический код вызова ABI с помощью gdb, я получаю:

(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.

Расположение кода соответствует, но совершенно неверно: есть две инструкции, которые даже не распознаются gdb и вторая инструкция:

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

выходит за пределы раздела .text процесса, который заканчивается на 0x866c:

Loading section .text, size 0x866c lma 0x8000000

Любая подсказка о том, что я делаю неправильно? Любая помощь будет оценена по достоинству.

РЕДАКТИРОВАТЬ: я использую этот компилятор: 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 (после ответа Notlikethat): команда, которую я использую для связывания своей программы, такова:

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

memmap — это скрипт компоновщика, vectors.o содержит код запуска, $(OBJS2) содержит все объектные файлы, которые должны быть связаны вместе, а $(LIBGCC) — это переменная, ссылающаяся на библиотеку, содержащую вызов ABI, который мы обсуждаем. Из того, что я понял из комментария Notlike, я должен добавить сюда какую-то опцию, чтобы принудительно компилировать код libgcc для просмотра вместо нормального кода ARM. Я пытался добавить в компоновщик эти параметры, но в обоих случаях получаю одну и ту же ошибку:

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

EDIT3: только в этот момент я понял, что процессор моей платы - cortex-m4f, а не cortex-m3. Я не думаю, что это не должно сильно отличаться.


person user3768186    schedule 23.06.2014    source источник
comment
Что ж, эта дизассемблирование — это инструкции ARM, которые не имеют смысла, когда M3 пытается выполнить их как Thumb. Какой компилятор/библиотеку вы используете? (кроме неправильного)   -  person Notlikethat    schedule 23.06.2014
comment
Спасибо за ответ, я обновлю пост с необходимой информацией. В любом случае я использую этот компилятор: launchpad.net/gcc-arm-embedded/+download и поставляемые с ним библиотеки.   -  person user3768186    schedule 23.06.2014
comment
Более того, я не настолько глубоко знаю ARM-ассемблер, чтобы различать обычные ARM-инструкции и Thumb-инструкции, но я скомпилировал все файлы с опцией -mthumb, поэтому их нужно компилировать в Thumb-инструкции.   -  person user3768186    schedule 23.06.2014


Ответы (1)


Проблема в том, что ваша цепочка инструментов по умолчанию имеет свою стандартную библиотеку, скомпилированную в инструкции ARM - поскольку процессоры Cortex-M поддерживают только Thumb-2 *, они будут ошибаться при попытке использовать межсетевую ветвь для кода ARM.

Теперь параметр -mthumb указывает компилятору скомпилировать ваш код в Thumb — стандартная библиотека предварительно скомпилирована и даже не появляется в кадре до момента компоновки. К счастью, в файле readme указано, что набор инструментов поддерживает работу с несколькими библиотеками, так что вы можете выбрать подходящую библиотеку без необходимости найти цепочку инструментов для v7-M.

Из того, что я понимаю о внутренней работе multilib, вы должны предоставить точную волшебную комбинацию опций, которую он ищет, что в этом случае будет:

-mthumb -mcpu=cortex-m4

or:

-mthumb -march=armv7e-m

что заставит GCC предоставить компоновщику подходящую совместимую библиотеку вместо библиотеки по умолчанию (в документации есть дополнительные параметры, если вам также нужна поддержка с плавающей запятой).

Если вы используете отдельный шаг связывания, я считаю, что вам нужно использовать gcc в качестве команды связывания вместо ld для правильной работы multilib — это, безусловно, относится к набору инструментов Linaro, который у меня есть (который имеет только двусторонний жесткий -float/ARMv4+soft-float multilib).


* строго, не совсем-все-из-Thumb-2

person Notlikethat    schedule 23.06.2014
comment
Прежде всего, спасибо за ваш ответ, я не знал об этом факте. Поскольку место для комментария не соответствует моему ответу, я обновлю свой пост там. - person user3768186; 24.06.2014
comment
@user3768186 user3768186 Обновил ответ. Я опустил префикс кросс-компилятора для ясности, но, очевидно, он вам все еще нужен. Хост gcc не будет работать ;) - person Notlikethat; 24.06.2014
comment
Да, я использую отдельный шаг ссылки, на данный момент я решил передать компоновщику правильный libgcc (на самом деле ошибка была из-за того, что я передал неправильный). Я знаю, что это не идеально, и правильным решением является предложенное вами. - person user3768186; 24.06.2014