http://llvm.org/bugs/show_bug.cgi?id=16857
Bug ID: 16857
Summary: llvm generates pop pc on ARMv4 in thumb mode (broken
interworking)
Product: clang
Version: 3.3
Hardware: PC
OS: Linux
Status: NEW
Severity: normal
Priority: P
Component: LLVM Codegen
Assignee: [email protected]
Reporter: [email protected]
CC: [email protected]
Classification: Unclassified
Command:
clang -target arm-softfloat-eabi -mcpu=arm7tdmi -mthumb -O2 -S -o - foo.c
Contents of foo.c:
#include <stdint.h>
int foo(int a, int64_t b, int64_t c) {
return a + (int)(b/c);
}
Assembler code generated:
foo:
push {r4, r5, r6, r7, lr}
add r7, sp, #12
sub sp, #4
mov r4, r0
ldr r5, [sp, #24]
ldr r6, [sp, #28]
mov r0, r2
mov r1, r3
mov r2, r5
mov r3, r6
bl __aeabi_ldivmod
adds r0, r0, r4
add sp, #4
pop {r4, r5, r6, r7, pc}
Problem description:
If foo is called from thumb mode, then lr is an odd address. If foo is called
from arm mode, then lr is an even address. On ARMv4, the address popped to pc
must be even according to arm documentation:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489i/Cihedhif.html
Also according to arm documentation, a pop pc (or ldmia sp!, pc) cannot be used
for switching between arm and thumb mode on ARMv4. Hence, the above assembler
code does not switch back to arm mode if the caller was arm mode. The bx
instruction has to be used to switch mode on ARMv4.
The code generated by gcc for ARMv4 looks something like this:
pop {r4, r5, r6, r7}
pop {r0}
bx r0
As far as I know, interworking is mandatory for arm-eabi. I tried using the
command line switch -mthumb-interwork to clang, but it is ignored.
Note that the code above doesn't work for ARMv4 at all since mov is used with
two low registers. I filed that as bug 16855.
--
You are receiving this mail because:
You are on the CC list for the bug.
_______________________________________________
LLVMbugs mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/llvmbugs