RE: [arm-gnu] thumb code calling arm subroutine causes undefined insn exception
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [arm-gnu] thumb code calling arm subroutine causes undefined insn exception



I might be wrong, but I'm pretty sure arm7tdmi does not support the blx instruction. blx was added in armv5t instruction set. arm7tdmi is armv4.

I'd try -mcpu=arm7tdmi or -march=armv4 to see if it'll stick to the right instruction set. Thumb interworking on pre armv5s is pretty nasty though. The lack of blx means it a lot of times have to jump through linker generated shims and generally spend a lot more effort.
________________________________________
From: Andrew Kohlsmith (mailing lists account) [aklists@xxxxxxxxxx]
Sent: Sunday, April 25, 2010 13:29
To: arm-gnu@xxxxxxxxxxxxxxxx
Subject: [arm-gnu] thumb code calling arm subroutine causes undefined insn exception

Good afternoon, everyone,

I received a really good education on my last post regarding compiler sections
and was able to put that knowledge to some good use, but I've run into a
problem that I am having a real difficult time getting myself out of.

I have a little arm7tdmi board that has been the subject of all my
experiments. I'm now playing with size optimization and have changed my
lowlevel bootup (reset vector) code from ARM to Thumb instructions.

It works great, but I seem to be running into a problem where if I'm running
in thumb mode and I call an ARM subroutine, the call fails.

The bootup code is in assembly, but it jumps to a C main() routine.  That
routine executes just fine until it calls the ARM subroutine.

I'm building the code with CodeSourcery's G++ Lite 2009q3-68 (GCC 4.4.1).

arm-none-eabi-as -o boot.o boot.s

arm-none-eabi-gcc -o irq.o -c -std=gnu99 -g -O0 -fno-builtin -nostdlib -
mcpu=arm7tdmi -mthumb-interwork -DNDEBUG -ffunction-sections -fdata-sections
irq.c

arm-none-eabi-gcc -o main.o -c -std=gnu99 -g -O0 -fno-builtin -nostdlib -
mcpu=arm7tdmi -mthumb -mthumb-interwork -DNDEBUG -ffunction-sections -fdata-
sections main.c

As you can see, I am running with -mthumb-interwork, and I've disabled -Os for
now. Linking is done with this command:

arm-none-eabi-gcc -o foo -std=gnu99 -g -O0 -fno-builtin -nostdlib -
mcpu=arm7tdmi -mthumb -mthumb-interwork -DNDEBUG -Trom.ld -Wl,-Map=foo.map -
Wl,--cref -Wl,--gc-sections boot.o main.o irq.o

objdumping the resultant file where the undefined instruction exception occurs
looks ok (to me, but I'm not an expert):

000007f4 <hw_init>:
 7f4:   b580            push    {r7, lr}
 7f6:   af00            add     r7, sp, #0
 7f8:   f000 e9a4       blx     b44 <irq_setup>
 7fc:   f7ff fe1e       bl      43c <rtc_init>
 800:   f7ff ff8c       bl      71c <vibe_init>
 804:   f7ff feba       bl      57c <spiflash_init>

The undefined instruction handler shows LR at 0x7fc, which, if my math is
correct, puts the undefined instruction at 0x7fa.

Now the irq_setup() routine lives in irq.c, which is compiled for ARM
instructions. It too seems fine to my untrained eye:

00000b44 <irq_setup>:
 b44:   e59fc048        ldr     ip, [pc, #72]   ; b94 <irq_setup+0x50>
 b48:   e59f3048        ldr     r3, [pc, #72]   ; b98 <irq_setup+0x54>
 b4c:   e3a00000        mov     r0, #0
 b50:   e58c0000        str     r0, [ip]
 b54:   e3a0c002        mov     ip, #2
 b58:   e583c004        str     ip, [r3, #4]
 b5c:   e59fc038        ldr     ip, [pc, #56]   ; b9c <irq_setup+0x58>
 b60:   e3a01001        mov     r1, #1
 b64:   e583100c        str     r1, [r3, #12]
 b68:   e583c01c        str     ip, [r3, #28]
 b6c:   e3a0c018        mov     ip, #24
 b70:   e583c014        str     ip, [r3, #20]
 b74:   e3e02000        mvn     r2, #0
 b78:   e583003c        str     r0, [r3, #60]   ; 0x3c
 b7c:   e5831004        str     r1, [r3, #4]
 b80:   e3a03010        mov     r3, #16
 b84:   e5023fef        str     r3, [r2, #-4079]        ; 0xfef
 b88:   e59f3010        ldr     r3, [pc, #16]   ; ba0 <irq_setup+0x5c>
 b8c:   e5023fcf        str     r3, [r2, #-4047]        ; 0xfcf
 b90:   e12fff1e        bx      lr
 b94:   40000c68        .word   0x40000c68
 b98:   e0004000        .word   0xe0004000
 b9c:   00006590        .word   0x00006590
 ba0:   00000b08        .word   0x00000b08

Now irq_setup() itself not having to be in ARM instructions (only the
interrupt handler itself), aside, why on earth would this code cause the ARM
to abort on an undefined instruction exception?

Any hints or guidance would be very much appreciated.

Regards,
Andrew