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



On Sunday 25 April 2010 10:43:51 pm Mark Mitchell wrote:
> Andrew Kohlsmith (mailing lists account) wrote:
> > Since I am already using -mcpu=arm7tdmi, would this indicate that there
> > is a bug in the compiler wherein it is assuming that the BLX instruction
> > exists on the ARM7TDMI/TDMI-S?
> 
> Please post your exact options for all of (a) code compiled with
> GCC/G++, (b) code assembled with GAS, (c) link line.

Actually some further inspection seems to lead to the conclusion that 
incorrect bootup code (in my case it's using msr in thumb mode) causes the 
linker to become confused.

-A.

boot.s:
------------------
.equ MIN_STACK,         0x0004          /* enough for a RET */
.equ IRQ_STACK_LEN,     0x0080          /* 128 words */       
.equ STACK_LEN,         0x0200          /* 512 words */       

/* .text is used instead of .section .text so it works with arm-aout too. */

        .text
        .code 32

        .align  0

        .extern main
        .global start
        .global endless_loop

start:
        ldr r0, =thumb_start + 1                /* +1 to set LSB to identify 
destination as thumb code */
        bx r0                                                                                            

        .code 16

thumb_start:
        ldr r0, =.asm_arm_code
        bx r0                 

/* ARM code section to set up stack for all modes */

        .code 32

.asm_arm_code:
        ldr r0, =.asm_back_to_thumb
        bx r0

/* back to Thumb mode for the rest of the initialization */

        .code 16

.asm_back_to_thumb:
        ldr r6, =main + 1

/* set up call stack */
        ldr r3, =exit + 1               /* return address */
        mov lr, r3
        mov r0, #0              /* argc = 0 */
        mov r1, #0              /* **argv = NULL */
        bx r6

/*** Uncomment this and change the exit + 1 to just exit above to "fix" the bug
        .align 4
        .code 32
*/
exit:
        mov r4, #0
        msr CPSR_c, r4

        b exit

endless_loop:
        b endless_loop

.section .startup,"ax"
        .code 32
        .align 0

        b start
        b undefined_instruction_exception
        b software_interrupt_exception
        b prefetch_abort_exception
        b data_abort_exception
        b reserved_exception
        b interrupt_exception
        b fast_interrupt_exception

/* end */
.end


main.c
-----------------------
unsigned int alloword;

void thumb_func(void)
{
}

int allo_main(void)
{
}

int main(void)
{
        irq_init();

        do {
                arm_func();
                thumb_func();
        } while(1);

        return 0;
}



irq.c:
------------------------------
void irq_handler(void)  __attribute__ ((interrupt("IRQ")));

void irq_handler(void)
{
}

void arm_func(void)
{
}

void irq_init(void)
{
}


rom.ld:
---------------------
ENTRY(start);                                           

MEMORY {
        flash : ORIGIN = 0, LENGTH = 32K
        ram : ORIGIN = 0x40000000, LENGTH = 8K
}                                             

_stack_end = 0x40000000 + 8K - 4;

SECTIONS {
        . = 0;
        . = ALIGN(0x4);

/* interrupt vector table and CRC of the image */
        startup : { KEEP(*(.startup)) } >flash   

        .text : {
                *(.text .text.* .gnu.linkonce.t.*)
                *(.glue_7 .glue_7t)               
                *(.rodata .rodata.*)              
        } >flash                                  

        _etext = .;

        .data : {
                _data = .;
                *(.data .data.*)
        } >ram AT>flash         

        _data_src = LOADADDR(.data);
        _data_len = SIZEOF(.data);  

        .bss : {
                _bss = .;
                *(.bss .bss.*)
        } >ram                

        _bss_len = SIZEOF(.bss);

/*
 * Align here to ensure that the .bss section occupies space up to
 * _end.  Align after .bss to ensure correct alignment even if the
 * .bss section disappears because there are no input sections.   
 */                                                               
        . = ALIGN(0x4);                                           
} 

Makefile:
-----------------
AS=arm-none-eabi-as
CC=arm-none-eabi-gcc
LD=arm-none-eabi-ld
OBJCOPY=arm-none-eabi-objcopy

DEBUG=-g -O0
THUMB=-mthumb -mthumb-interwork
#CFLAGS=$(DEBUG) -std=gnu99 -fno-builtin -mcpu=arm7tdmi-s $(THUMB)
CFLAGS=$(DEBUG) -fno-builtin -mcpu=arm7tdmi-s $(THUMB)

OBJS=boot.o main.o irq.o

blxtest: $(OBJS)
        $(CC) -T rom.ld -Wl,-Map=$@.map -Wl,--cref -Wl,--gc-sections -o $@ $^

# irq code cannot be thumb
irq.o: irq.c
        $(CC) $(DEBUG) -fno-builtin -mcpu=arm7tdmi-s -c -o $@ $<

clean:
        rm -f *.o blxtest*


With boot.s as pasted here:
$ arm-none-eabi-objdump -S blxtest | grep blx
blxtest:     file format elf32-littlearm
  7c:   f000 e81a       blx     b4 <irq_init>
  80:   f000 e80e       blx     a0 <arm_func>

With boot.s properly using msr in .code32:
$ arm-none-eabi-objdump -S blxtest | grep blx
blxtest:     file format elf32-littlearm

$ arm-none-eabi-gcc -v
Using built-in specs.
Target: arm-none-eabi
Configured with: /scratch/julian/2009q3-respin-eabi-lite/src/gcc-4.4/configure 
--build=i686-pc-linux-gnu --host=i686-pc-linux-gnu --target=arm-none-eabi --
enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --
enable-extra-sgxxlite-multilibs --with-gnu-as --with-gnu-ld --with-
specs='%{O2:%{!fno-remove-local-statics: -fremove-local-statics}} %{O*:%{O|O0|
O1|O2|Os:;:%{!fno-remove-local-statics: -fremove-local-statics}}}' --enable-
languages=c,c++ --disable-shared --disable-lto --with-newlib --with-
pkgversion='Sourcery G++ Lite 2009q3-68' --with-
bugurl=https://support.codesourcery.com/GNUToolchain/ --disable-nls --
prefix=/opt/codesourcery --with-headers=yes --with-
sysroot=/opt/codesourcery/arm-none-eabi --with-build-
sysroot=/scratch/julian/2009q3-respin-eabi-lite/install/arm-none-eabi --with-
gmp=/scratch/julian/2009q3-respin-eabi-lite/obj/host-libs-2009q3-68-arm-none-
eabi-i686-pc-linux-gnu/usr --with-mpfr=/scratch/julian/2009q3-respin-eabi-
lite/obj/host-libs-2009q3-68-arm-none-eabi-i686-pc-linux-gnu/usr --with-
ppl=/scratch/julian/2009q3-respin-eabi-lite/obj/host-libs-2009q3-68-arm-none-
eabi-i686-pc-linux-gnu/usr --with-host-libstdcxx='-static-libgcc -Wl,-
Bstatic,-lstdc++,-Bdynamic -lm' --with-cloog=/scratch/julian/2009q3-respin-
eabi-lite/obj/host-libs-2009q3-68-arm-none-eabi-i686-pc-linux-gnu/usr --
disable-libgomp --enable-poison-system-directories --with-build-time-
tools=/scratch/julian/2009q3-respin-eabi-lite/install/arm-none-eabi/bin --
with-build-time-tools=/scratch/julian/2009q3-respin-eabi-lite/install/arm-
none-eabi/bin
Thread model: single
gcc version 4.4.1 (Sourcery G++ Lite 2009q3-68)