Was this example generated by a real world compiler? (Which one?)
[adamushkad@cplx219]/>mips-linux-uclibc-gcc -v Reading specs from /vobs/linux/tools/mips/gcc-3.4.2/bin/../lib/gcc/mips-linux-uclibc/3.4.2/specs Configured with: /vobs/linux/tools/buildroot/toolchain_build_mips/gcc-3.4.2/configure --prefix=/vobs/linux/tools/buildroot/build_mips/staging_dir --build=i386-pc-linux-gnu --host=i386-pc-linux-gnu --target=mips-linux-uclibc --enable-languages=c,c++ --enable-shared --disable-__cxa_atexit --enable-target-optspace -with-gnu-ld --disable-nls --enable-multilib Thread model: posix gcc version 3.4.2
I'm inclined to claim the example is broken WRT ABI rules since it doesn't enclose the whole user code in the prologue/epilogue bracket.
It's o32. So it explicitly requires that when the prologue and epilogue have been used in the function, all the user code must be place in between, right? In this light, the unlike(ofs == 0) in unwind_stack() aims at catching cases when <sp> is wrong (if addiu sp,sp,OFFSET is normally the very first instruction) ok, here is an example from kernel/sched.o (the same compiler). 00000098 <enqueue_task>: 98: 8c820018 lw v0,24(a0) <----- before the prologue 9c: 27bdfff8 addiu sp,sp,-8 a0: afbe0000 sw s8,0(sp) a4: 000210c0 sll v0,v0,0x3 a8: 00a21021 addu v0,a1,v0 ac: 24420018 addiu v0,v0,24 b0: 8c460004 lw a2,4(v0) b4: 24830020 addiu v1,a0,32 b8: ac430004 sw v1,4(v0) bc: ac820020 sw v0,32(a0) c0: ac660004 sw a2,4(v1) c4: acc30000 sw v1,0(a2) c8: 8c860018 lw a2,24(a0) cc: 24a70004 addiu a3,a1,4 d0: 03a0f021 move s8,sp d4: 00061142 srl v0,a2,0x5 d8: 00021080 sll v0,v0,0x2 dc: 00e23821 addu a3,a3,v0 e0: 8ce30000 lw v1,0(a3) e4: 30c6001f andi a2,a2,0x1f e8: 24020001 li v0,1 ec: 00c21004 sllv v0,v0,a2 f0: 00621825 or v1,v1,v0 f4: ace30000 sw v1,0(a3) f8: 8ca20000 lw v0,0(a1) fc: 03c0e821 move sp,s8 100: 8fbe0000 lw s8,0(sp) 104: 24420001 addiu v0,v0,1 108: 27bd0008 addiu sp,sp,8 10c: aca20000 sw v0,0(a1) 110: 03e00008 jr ra 114: ac850028 sw a1,40(a0) <------------ after the epilogue As I can see, normally this compiler places "addiu sp,sp,FRAME_SIZE" at the branch delay slot of "jr ra" but e.g. enqueue_task() (example above) and request_task() are exceptions. btw, the very first instruction is also placed before the epilogue. Are there any configure options that might have caused such a behaviour [hmmm... e.g. gcc was configured with --ignore-abi-rulles :] ? Although, I don't think this would be an option-dependent case.
Thiemo
-- Best regards, Dmitry Adamushko