This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/37386] New: Interrupt service routine for arm target corrupts program counter
- From: "fede dot tft at hotmail dot it" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 5 Sep 2008 17:51:56 -0000
- Subject: [Bug c++/37386] New: Interrupt service routine for arm target corrupts program counter
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
Trying to compile this code:
#define U0THR (*((volatile unsigned char *) 0xE000C000))
template <typename T, unsigned int len>
class Queue
{
public:
/**
Constructor, create a new queue.
*/
Queue()
{
put_pos=get_pos=num_elem=0;
}
bool IRQget(T& elem)
{
if((put_pos==get_pos)&&(num_elem==0))//If queue empty
{
return false;
}
num_elem--;
elem=buffer[get_pos];
if(++get_pos==len) get_pos=0;
return true;
}
bool IRQput(T elem)
{
if((put_pos==get_pos)&&(num_elem!=0))//If queue full
{
return false;
}
num_elem++;
buffer[put_pos]=elem;
if(++put_pos==len) put_pos=0;
return true;
}
private:
//Queue data
T buffer[len];
volatile unsigned int num_elem;
volatile unsigned int put_pos;
volatile unsigned int get_pos;
};
Queue<char,32> tx_queue;
void serial_IRQ_Routine() __attribute__ ((interrupt("IRQ")));
void serial_IRQ_Routine()
{
char c;
int i;
for(i=0;i<16;i++)
{
//If software queue empty, stop
if(tx_queue.IRQget(c)==false) break;
U0THR=c;
}
}
with gcc 4.2.4, command line "arm-elf-g++ -mcpu=arm7tdmi -fno-exceptions
-fno-rtti -Os -Wall -S bug.cpp"
corrupts the program counter when returning from the ISR.
It happens only with -Os optimization flag. -O0 -O1 -O2 -O3 optimization flags
cause no bug.
Here's a piece of assembler code:
_Z18serial_IRQ_Routinev:
@ Interrupt Service Routine.
@ args = 0, pretend = 0, frame = 4
@ frame_needed = 0, uses_anonymous_args = 0
sub lr, lr, #4
stmfd sp!, {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr}
ldr r7, .L15
sub sp, sp, #4
ldr r6, .L15+4
mov r4, #0
add r5, sp, #3
.L10:
ldr r0, .L15+8
mov r1, r5
mov lr, pc
bx r7
cmp r0, #0
add r4, r4, #1
beq .L13
ldrb r3, [sp, #3] @ zero_extendqisi2
cmp r4, #16
strb r3, [r6, #0]
bne .L10
.L13:
add sp, sp, #4
ldmfd sp!, {r0, r1, r2, r3, r4, r5, r6, r7, ip, lr}
subs pc, lr, #4
at the beginning there's
" sub lr, lr, #4"
and at the end
" subs pc, lr, #4"
so the program counter is decremented by 8 instead of 4.
Here's the output of arm-elf-gcc -v:
arm-elf-g++ -v
Using built-in specs.
Target: arm-elf
Configured with: ../gcc-4.2.4/configure --target=arm-elf
--prefix=/usr/local/arm-elf --enable-interwork --enable-multilib
--with-float=soft --enable-languages=c,c++ --with-newlib
--with-headers=../newlib-1.16.0/newlib/libc/include
Thread model: single
gcc version 4.2.4
--
Summary: Interrupt service routine for arm target corrupts
program counter
Product: gcc
Version: 4.2.4
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: fede dot tft at hotmail dot it
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37386