So it loads r0 and r1 with a 2 (well it does the plus one thing on current task+1
10648: e1a00003 mov r0, r3
1064c: e51b1010 ldr r1, [fp, #-16]
10650: eb00fd36 bl 4fb30 <____aeabi_uidivmod_veneer>
I guess they used _veneer to switch from arm to thumb, it is a trampoline to switch modes:
0004fb30 <____aeabi_uidivmod_veneer>:
4fb30: e51ff004 ldr pc, [pc, #-4] ; 4fb34 <____aeabi_uidivmod_veneer+0x4>
4fb34: 00010905 .word 0x00010905
That takes you here, the actual modulo operation, this is thumb code, thumb mode
00010904 <__aeabi_uidivmod>:
10904: 2900 cmp r1, #0
10906: d0f8 beq.n 108fa <__aeabi_uidiv+0x252>
10908: e92d 4003 stmdb sp!, {r0, r1, lr}
1090c: f7ff fecc bl 106a8 <__aeabi_uidiv>
10910: e8bd 4006 ldmia.w sp!, {r1, r2, lr}
10914: fb02 f300 mul.w r3, r2, r0
10918: eba1 0103 sub.w r1, r1, r3
1091c: 4770 bx lr
1091e: bf00 nop
So it looks to do a normal divide, then multiplies the result and subtracts for example
12345 % 100 = 12345 - ((12345/100)*100) = 12345 - (123*100) = 12345 - 12300 = 45
I wonder if the problem is thumb mode. The arm1176 definitely has thumb mode, the real one, and I qemu can do thumb.
You could try an experiment though to find out assemble and link:
.thumb
.thumb_func
.globl thumb_test
thumb_test:
add r0,#1
bx lr
arm-none-linux-gnueabi-as thumb_test.s -o thumb_test.o
or whatever your toolchain prefix is if any, and link the .o file in with everything else.
in the C code declare it as
unsigned int thumb_test ( unsigned int );
and whatever you pass it you should get that value plus one back...try this instead of the modulo.
Another thing to try is just a straight divide, see if divide works but not modulo, maybe the problem is the multiply instruction? Who knows.
Hmmmm, I think I see the problem:
0004fb30 <____aeabi_uidivmod_veneer>:
4fb30: e51ff004 ldr pc, [pc, #-4] ; 4fb34 <____aeabi_uidivmod_veneer+0x4>
4fb34: 00010905 .word 0x00010905
You cant switch modes with an ldr it has to be a bx or blx, it is probably going to the undefined handler when it tries to execute thumb code in arm mode.
I have some examples of how switching modes needs to work, in particular written for qemu. Now this is a low level example, no printf for example, I do have uart output with a way to see stuff on the uart. If this is the problem (switching to thumb mode) then you need to examine how you are compiling and linking your program. You might need to specify interwork or might need to understand how your toolchain was built if you are not using the formerly code sourcery (now consumed by mentor graphics) toolchain. that is assuming you are using something gnu/gcc based.
If you have a way to put an undefined handler in there or if you are able to watch the trace and see the pc drop to something near address 0x0000000 that is probably what is happening. If you build with my little thumb_test thing and it uses an ldr instead of bx to get there then that should not work either it should still crash...