Aarch64 Frame pointer - arm

I saw this code on page 120 of ArmV8 Programmer's Guide:
foo//
SUB SP, SP, #0x30
STR W0, [SP, #0x2C]
STR W1, [SP, #0x28]
STR D0, [SP, #0x20]
STR D1, [SP, #0x18]
LDR W0, [SP, #0x2C]
STR W0, [SP, #0]
LDR W0, [SP, #0x28]
STR W0, [SP, #4]
LDR W0, [SP, #0x20]
STR W0, [SP, #8]
LDR W0, [SP, #0x18]
STR W0, [SP, #10]
LDR X9, [SP, #0x0]
STR X9, [X8, #0]
LDR X9, [SP, #8]
STR X9, [X8, #8]
LDR X9, [SP, #0x10]
STR X9, [X8, #0x10]
ADD SP, SP, #0x30
RET
bar//
STP X29, X30, [SP, #0x10]!
MOV X29, SP
SUB SP, SP, #0x20
ADD X8, SP, #8
MOV W0, WZR
ORR W1, WZR, #1
FMOV D0, #1.00000000
FMOV D1, #2.00000000
BL foo:
ADRP X8, {PC}, 0x78
ADD X8, X8, #0
LDR X9, [SP, #8]
STR X9, [X8, #0]
LDR X9, [SP, #0x10]
STR X9, [X8, #8]
LDR X9, [SP, #0x18]
STR X9, [X8, #0x10]
MOV SP, X29
LDP X20, X30, [SP], #0x10
RET
My question is regarding to following instruction at the end of bar routine:
LDP X20, X30, [SP], #0x10
LDP is for loading pair of registers from stack and restriction for this instruction will not allow loading to registers at that distance.
First, why this line can be valid ?
Second, why FP is loaded into x20 ? Isn't it supposed to load into x29 ?
From ARM Procedure call standard :
Each frame shall link to the frame of its caller by means of a frame record of two 64-bit values on the stack
Of course it also mentions cases which these requirements are not mandatory, but in this case FP seems to be not valid because it is pointing to sp - 0x10 which which has fp and lr .

Related

How arguments are passed to the printf() function?

I am trying to understand the assembly code for a simple program, shown below.
void f()
{
int i, x = 0;
for (i = 0; i < 10; i++)
x++;
printf("Value of x: %d\n", x);
}
and its corresponding assembly code on my machine is
00000000000007d4 <f>:
7d4: a9be7bfd stp x29, x30, [sp, #-32]!
7d8: 910003fd mov x29, sp
7dc: b9001fff str wzr, [sp, #28]
7e0: b9001bff str wzr, [sp, #24]
7e4: 14000007 b 800 <f+0x2c>
7e8: b9401fe0 ldr w0, [sp, #28]
7ec: 11000400 add w0, w0, #0x1
7f0: b9001fe0 str w0, [sp, #28]
7f4: b9401be0 ldr w0, [sp, #24]
7f8: 11000400 add w0, w0, #0x1
7fc: b9001be0 str w0, [sp, #24]
800: b9401be0 ldr w0, [sp, #24]
804: 7100241f cmp w0, #0x9
808: 54ffff0d b.le 7e8 <f+0x14>
80c: b9401fe1 ldr w1, [sp, #28]
810: 90000000 adrp x0, 0 <__abi_tag-0x278>
814: 9121c000 add x0, x0, #0x870
818: 97ffff9a bl 680 <printf#plt>
81c: d503201f nop
820: a8c27bfd ldp x29, x30, [sp], #32
824: d65f03c0 ret
I understand the loop, but line 814 - 818 is really confusion to me. What's the purpose of adding #0x870 to x0? What does line 818 mean? And how arguments are passed to the printf() function?
I expect words like "Value of x: " appears in the assembly code, but it seems like the compiler simply knows what to print.

Why are w8,w9 used instead of w1,w2?

I am studying about armv8.
The following c language code
When converted to assembly with clang, w0 seems to be used for the return value, and w8 and w9 are used to save the variable values.
It is said that the arm has w series registers w0 to w30, but why are w8 and w9 used instead of w1 and w2?
int main() {
int a = 3;
int b = 5;
int c = a + b;
return c;
}
main: // #main
sub sp, sp, #16 // =16
str wzr, [sp, #12]
mov w8, #3
str w8, [sp, #8]
mov w8, #5
str w8, [sp, #4]
ldr w8, [sp, #8]
ldr w9, [sp, #4]
add w8, w8, w9
str w8, [sp]
ldr w0, [sp]
add sp, sp, #16 // =16
ret

Timer interrupts in ARM processor QEMU not occurring

I am trying to get interrupts to work on an ARM processor using QEMU. I have tried Google and various attempts to solve it, but I cannot get my IRQ handler to be called.
I also tried keyboard interrupts, which did not work either. I think the book I have may have a few mistakes, as the UART driver ended up being slightly different than described.
My assembly code:
.code 32
.global start, vectors_start, vectors_end, lock, unlock
start:
LDR sp, =stack_top
BL copy_vector
MSR cpsr, #0x92
LDR sp, =irq_stack_top
MSR cpsr, #0x13
bl unlock
BL main
B .
irq_handler:
sub lr, lr, #4
stmfd sp!, {r0-r12, lr}
bl IRQ_handler
ldmfd sp!, {r0-r12, pc}^
vectors_start:
LDR PC, reset_handler_addr
LDR PC, undef_handler_addr
LDR PC, swi_handler_addr
LDR PC, prefetch_abort_handler_addr
LDR PC, data_abort_handler_addr
B .
LDR PC, irq_handler_addr
LDR PC, fiq_handler_addr
reset_handler_addr: .word start
undef_handler_addr: .word undef_handler
swi_handler_addr: .word swi_handler
prefetch_abort_handler_addr: .word prefetch_abort_handler
data_abort_handler_addr: .word data_abort_handler
irq_handler_addr: .word irq_handler
fiq_handler_addr: .word fiq_handler
vectors_end:
lock:
MRS r0, CPSR
ORR r0,r0,#0x80
MSR CPSR, r0
mov PC, lr
unlock:
MRS r0,CPSR
BIC r0,r0,#0x80
MSR CPSR, r0
mov PC, lr
Relevant C functions:
void copy_vector(void){
extern u32 vectors_start, vectors_end;
u32 *vectors_src = &vectors_start;
u32 *vectors_dst = (u32 *) 0;
while (vectors_src<&vectors_end){
*vectors_dst++ = *vectors_src++;
}
}
// this function has been modified somewhat because the book was incomplete
// the print statement never prints
void IRQ_handler(void){
int vicstatus = 0;
uprints(uarts,"in interupt");
// int vicstatus = 0;
if(1){
if(*(tp[0]->base+TVALUE)==0){
timer_handler(0);
}
if(*(tp[1]->base+TVALUE)==0){
timer_handler(1);
}
}
if( 1){
if(*(tp[2]->base+TVALUE)==0){
timer_handler(2);
}
if(*(tp[3]->base+TVALUE)==0){
timer_handler(3);
}
}
}
void timer_init()
{
// timers[0].base = (u32*) 0x101E2000;
// timers[1].base = (u32*) 0x101E2020;
// timers[2].base = (u32*) 0x101E3000;
// timers[3].base = (u32*) 0x101E3020;
int i; TIMER * tp;
for (i = 0; i<4; ++i){
tp = &timers[i];
if(i==0) tp->base = (u32*) 0x101E2000;
if(i==1) tp->base = (u32*) 0x101E2020;
if (i == 2) tp->base = (u32*) 0x101E3000;
if (i == 3) tp->base = (u32*) 0x101E3020;
*(tp->base+TLOAD) = 0x0;
*(tp->base+TVALUE) = 0xFFFFFFFF;
*(tp->base+TRIS) = 0x0;
*(tp->base+TMIS) = 0x0;
*(tp->base+TLOAD) = 0x100;
*(tp->base+TCNTL) = 0x66;
*(tp->base+TBGLOAD) = 0x1C00;
*(tp->base ) |= (unsigned int)(1<<6);
tp->tick = 0;
///uprints(uarts,"timer init");
}
}
When I reset the machine in QEMU I get the message Timer with delta zero disabling.
I can get the message to disappear by changing: *(tp->base+TLOAD) = 0x0;
to *(tp->base+TLOAD) = 0x1; but the timer still doesn't work.
Lastly, my build script is:
arm-none-eabi-as -o start3.o start3.s
arm-none-eabi-gcc -c main3.c
arm-none-eabi-ld -T t.ld -o start3.elf start3.o main3.o
arm-none-eabi-nm start3.elf
arm-none-eabi-objcopy -O binary start3.elf start3.bin
qemu-system-arm -M versatilepb -m 128M -kernel start3.bin
edit: in addition here is the disassembled code from my main.c file (which includes a few other c files for the drivers)
the board is the versatilepb which according to the docs emulates the following:
ARM926E, ARM1136 or Cortex-A8 CPU
00000000 <uart_init>:
0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
4: e28db000 add fp, sp, #0
8: e24dd00c sub sp, sp, #12
c: e3a03000 mov r3, #0
10: e50b3008 str r3, [fp, #-8]
14: ea000011 b 60 <uart_init+0x60>
18: e51b3008 ldr r3, [fp, #-8]
1c: e1a03183 lsl r3, r3, #3
20: e59f2064 ldr r2, [pc, #100] ; 8c <uart_init+0x8c>
24: e0833002 add r3, r3, r2
28: e50b300c str r3, [fp, #-12]
2c: e51b2008 ldr r2, [fp, #-8]
30: e59f3058 ldr r3, [pc, #88] ; 90 <uart_init+0x90>
34: e0823003 add r3, r2, r3
38: e1a03603 lsl r3, r3, #12
3c: e1a02003 mov r2, r3
40: e51b300c ldr r3, [fp, #-12]
44: e5832000 str r2, [r3]
48: e51b300c ldr r3, [fp, #-12]
4c: e51b2008 ldr r2, [fp, #-8]
50: e5832004 str r2, [r3, #4]
54: e51b3008 ldr r3, [fp, #-8]
58: e2833001 add r3, r3, #1
5c: e50b3008 str r3, [fp, #-8]
60: e51b3008 ldr r3, [fp, #-8]
64: e3530003 cmp r3, #3
68: daffffea ble 18 <uart_init+0x18>
6c: e59f3018 ldr r3, [pc, #24] ; 8c <uart_init+0x8c>
70: e59f201c ldr r2, [pc, #28] ; 94 <uart_init+0x94>
74: e5832018 str r2, [r3, #24]
78: e1a00000 nop ; (mov r0, r0)
7c: e1a00003 mov r0, r3
80: e28bd000 add sp, fp, #0
84: e49db004 pop {fp} ; (ldr fp, [sp], #4)
88: e12fff1e bx lr
8c: 00000000 .word 0x00000000
90: 000101f1 .word 0x000101f1
94: 10009000 .word 0x10009000
00000098 <ugetc>:
98: e52db004 push {fp} ; (str fp, [sp, #-4]!)
9c: e28db000 add fp, sp, #0
a0: e24dd00c sub sp, sp, #12
a4: e50b0008 str r0, [fp, #-8]
a8: e1a00000 nop ; (mov r0, r0)
ac: e51b3008 ldr r3, [fp, #-8]
b0: e5933000 ldr r3, [r3]
b4: e2833018 add r3, r3, #24
b8: e5d33000 ldrb r3, [r3]
bc: e2033010 and r3, r3, #16
c0: e3530000 cmp r3, #0
c4: 1afffff8 bne ac <ugetc+0x14>
c8: e51b3008 ldr r3, [fp, #-8]
cc: e5933000 ldr r3, [r3]
d0: e5d33000 ldrb r3, [r3]
d4: e1a00003 mov r0, r3
d8: e28bd000 add sp, fp, #0
dc: e49db004 pop {fp} ; (ldr fp, [sp], #4)
e0: e12fff1e bx lr
000000e4 <uputc>:
e4: e52db004 push {fp} ; (str fp, [sp, #-4]!)
e8: e28db000 add fp, sp, #0
ec: e24dd00c sub sp, sp, #12
f0: e50b0008 str r0, [fp, #-8]
f4: e1a03001 mov r3, r1
f8: e54b3009 strb r3, [fp, #-9]
fc: e1a00000 nop ; (mov r0, r0)
100: e51b3008 ldr r3, [fp, #-8]
104: e5933000 ldr r3, [r3]
108: e2833018 add r3, r3, #24
10c: e5d33000 ldrb r3, [r3]
110: e2033020 and r3, r3, #32
114: e3530000 cmp r3, #0
118: 1afffff8 bne 100 <uputc+0x1c>
11c: e51b3008 ldr r3, [fp, #-8]
120: e5933000 ldr r3, [r3]
124: e55b2009 ldrb r2, [fp, #-9]
128: e5c32000 strb r2, [r3]
12c: e1a00000 nop ; (mov r0, r0)
130: e1a00003 mov r0, r3
134: e28bd000 add sp, fp, #0
138: e49db004 pop {fp} ; (ldr fp, [sp], #4)
13c: e12fff1e bx lr
00000140 <ugets>:
140: e92d4800 push {fp, lr}
144: e28db004 add fp, sp, #4
148: e24dd008 sub sp, sp, #8
14c: e50b0008 str r0, [fp, #-8]
150: e50b100c str r1, [fp, #-12]
154: ea000007 b 178 <ugets+0x38>
158: e51b300c ldr r3, [fp, #-12]
15c: e5d33000 ldrb r3, [r3]
160: e1a01003 mov r1, r3
164: e51b0008 ldr r0, [fp, #-8]
168: ebfffffe bl e4 <uputc>
16c: e51b300c ldr r3, [fp, #-12]
170: e2833001 add r3, r3, #1
174: e50b300c str r3, [fp, #-12]
178: e51b0008 ldr r0, [fp, #-8]
17c: ebfffffe bl 98 <ugetc>
180: e1a03000 mov r3, r0
184: e20320ff and r2, r3, #255 ; 0xff
188: e51b300c ldr r3, [fp, #-12]
18c: e5c32000 strb r2, [r3]
190: e51b300c ldr r3, [fp, #-12]
194: e5d33000 ldrb r3, [r3]
198: e353000d cmp r3, #13
19c: 1affffed bne 158 <ugets+0x18>
1a0: e51b300c ldr r3, [fp, #-12]
1a4: e3a02000 mov r2, #0
1a8: e5c32000 strb r2, [r3]
1ac: e1a00000 nop ; (mov r0, r0)
1b0: e1a00003 mov r0, r3
1b4: e24bd004 sub sp, fp, #4
1b8: e8bd4800 pop {fp, lr}
1bc: e12fff1e bx lr
000001c0 <uprints>:
1c0: e92d4800 push {fp, lr}
1c4: e28db004 add fp, sp, #4
1c8: e24dd008 sub sp, sp, #8
1cc: e50b0008 str r0, [fp, #-8]
1d0: e50b100c str r1, [fp, #-12]
1d4: ea000006 b 1f4 <uprints+0x34>
1d8: e51b300c ldr r3, [fp, #-12]
1dc: e2832001 add r2, r3, #1
1e0: e50b200c str r2, [fp, #-12]
1e4: e5d33000 ldrb r3, [r3]
1e8: e1a01003 mov r1, r3
1ec: e51b0008 ldr r0, [fp, #-8]
1f0: ebfffffe bl e4 <uputc>
1f4: e51b300c ldr r3, [fp, #-12]
1f8: e5d33000 ldrb r3, [r3]
1fc: e3530000 cmp r3, #0
200: 1afffff4 bne 1d8 <uprints+0x18>
204: e1a00000 nop ; (mov r0, r0)
208: e1a00003 mov r0, r3
20c: e24bd004 sub sp, fp, #4
210: e8bd4800 pop {fp, lr}
214: e12fff1e bx lr
00000218 <fbuf_init>:
218: e52db004 push {fp} ; (str fp, [sp, #-4]!)
21c: e28db000 add fp, sp, #0
220: e59f3060 ldr r3, [pc, #96] ; 288 <fbuf_init+0x70>
224: e3a02602 mov r2, #2097152 ; 0x200000
228: e5832000 str r2, [r3]
22c: e59f3058 ldr r3, [pc, #88] ; 28c <fbuf_init+0x74>
230: e59f2058 ldr r2, [pc, #88] ; 290 <fbuf_init+0x78>
234: e5832000 str r2, [r3]
238: e59f3054 ldr r3, [pc, #84] ; 294 <fbuf_init+0x7c>
23c: e59f2054 ldr r2, [pc, #84] ; 298 <fbuf_init+0x80>
240: e5832000 str r2, [r3]
244: e59f3050 ldr r3, [pc, #80] ; 29c <fbuf_init+0x84>
248: e59f2050 ldr r2, [pc, #80] ; 2a0 <fbuf_init+0x88>
24c: e5832000 str r2, [r3]
250: e59f304c ldr r3, [pc, #76] ; 2a4 <fbuf_init+0x8c>
254: e59f204c ldr r2, [pc, #76] ; 2a8 <fbuf_init+0x90>
258: e5832000 str r2, [r3]
25c: e59f3048 ldr r3, [pc, #72] ; 2ac <fbuf_init+0x94>
260: e3a02602 mov r2, #2097152 ; 0x200000
264: e5832000 str r2, [r3]
268: e59f3040 ldr r3, [pc, #64] ; 2b0 <fbuf_init+0x98>
26c: e59f2040 ldr r2, [pc, #64] ; 2b4 <fbuf_init+0x9c>
270: e5832000 str r2, [r3]
274: e1a00000 nop ; (mov r0, r0)
278: e1a00003 mov r0, r3
27c: e28bd000 add sp, fp, #0
280: e49db004 pop {fp} ; (ldr fp, [sp], #4)
284: e12fff1e bx lr
288: 00000000 .word 0x00000000
28c: 1000001c .word 0x1000001c
290: 00002c77 .word 0x00002c77
294: 10120000 .word 0x10120000
298: 3f1f3f9c .word 0x3f1f3f9c
29c: 10120004 .word 0x10120004
2a0: 090b61df .word 0x090b61df
2a4: 10120008 .word 0x10120008
2a8: 071f1800 .word 0x071f1800
2ac: 10120010 .word 0x10120010
2b0: 10120018 .word 0x10120018
2b4: 0000082b .word 0x0000082b
000002b8 <draw_box>:
2b8: e52db004 push {fp} ; (str fp, [sp, #-4]!)
2bc: e28db000 add fp, sp, #0
2c0: e24dd01c sub sp, sp, #28
2c4: e50b0010 str r0, [fp, #-16]
2c8: e50b1014 str r1, [fp, #-20] ; 0xffffffec
2cc: e50b2018 str r2, [fp, #-24] ; 0xffffffe8
2d0: e50b301c str r3, [fp, #-28] ; 0xffffffe4
2d4: e3a03000 mov r3, #0
2d8: e50b3008 str r3, [fp, #-8]
2dc: ea00001c b 354 <draw_box+0x9c>
2e0: e3a03000 mov r3, #0
2e4: e50b300c str r3, [fp, #-12]
2e8: ea000012 b 338 <draw_box+0x80>
2ec: e59f3084 ldr r3, [pc, #132] ; 378 <draw_box+0xc0>
2f0: e5932000 ldr r2, [r3]
2f4: e51b100c ldr r1, [fp, #-12]
2f8: e51b3014 ldr r3, [fp, #-20] ; 0xffffffec
2fc: e0813003 add r3, r1, r3
300: e59f1074 ldr r1, [pc, #116] ; 37c <draw_box+0xc4>
304: e5911000 ldr r1, [r1]
308: e0010193 mul r1, r3, r1
30c: e51b3008 ldr r3, [fp, #-8]
310: e0811003 add r1, r1, r3
314: e51b3010 ldr r3, [fp, #-16]
318: e0813003 add r3, r1, r3
31c: e1a03103 lsl r3, r3, #2
320: e0823003 add r3, r2, r3
324: e51b201c ldr r2, [fp, #-28] ; 0xffffffe4
328: e5832000 str r2, [r3]
32c: e51b300c ldr r3, [fp, #-12]
330: e2833001 add r3, r3, #1
334: e50b300c str r3, [fp, #-12]
338: e51b200c ldr r2, [fp, #-12]
33c: e51b3018 ldr r3, [fp, #-24] ; 0xffffffe8
340: e1520003 cmp r2, r3
344: baffffe8 blt 2ec <draw_box+0x34>
348: e51b3008 ldr r3, [fp, #-8]
34c: e2833001 add r3, r3, #1
350: e50b3008 str r3, [fp, #-8]
354: e51b2008 ldr r2, [fp, #-8]
358: e51b3018 ldr r3, [fp, #-24] ; 0xffffffe8
35c: e1520003 cmp r2, r3
360: baffffde blt 2e0 <draw_box+0x28>
364: e1a00000 nop ; (mov r0, r0)
368: e1a00000 nop ; (mov r0, r0)
36c: e28bd000 add sp, fp, #0
370: e49db004 pop {fp} ; (ldr fp, [sp], #4)
374: e12fff1e bx lr
...
00000380 <timer_init>:
380: e52db004 push {fp} ; (str fp, [sp, #-4]!)
384: e28db000 add fp, sp, #0
388: e24dd00c sub sp, sp, #12
38c: e3a03000 mov r3, #0
390: e50b3008 str r3, [fp, #-8]
394: ea000048 b 4bc <timer_init+0x13c>
398: e51b3008 ldr r3, [fp, #-8]
39c: e1a03183 lsl r3, r3, #3
3a0: e59f2134 ldr r2, [pc, #308] ; 4dc <timer_init+0x15c>
3a4: e0833002 add r3, r3, r2
3a8: e50b300c str r3, [fp, #-12]
3ac: e51b3008 ldr r3, [fp, #-8]
3b0: e3530000 cmp r3, #0
3b4: 1a000002 bne 3c4 <timer_init+0x44>
3b8: e51b300c ldr r3, [fp, #-12]
3bc: e59f211c ldr r2, [pc, #284] ; 4e0 <timer_init+0x160>
3c0: e5832000 str r2, [r3]
3c4: e51b3008 ldr r3, [fp, #-8]
3c8: e3530001 cmp r3, #1
3cc: 1a000002 bne 3dc <timer_init+0x5c>
3d0: e51b300c ldr r3, [fp, #-12]
3d4: e59f2108 ldr r2, [pc, #264] ; 4e4 <timer_init+0x164>
3d8: e5832000 str r2, [r3]
3dc: e51b3008 ldr r3, [fp, #-8]
3e0: e3530002 cmp r3, #2
3e4: 1a000002 bne 3f4 <timer_init+0x74>
3e8: e51b300c ldr r3, [fp, #-12]
3ec: e59f20f4 ldr r2, [pc, #244] ; 4e8 <timer_init+0x168>
3f0: e5832000 str r2, [r3]
3f4: e51b3008 ldr r3, [fp, #-8]
3f8: e3530003 cmp r3, #3
3fc: 1a000002 bne 40c <timer_init+0x8c>
400: e51b300c ldr r3, [fp, #-12]
404: e59f20e0 ldr r2, [pc, #224] ; 4ec <timer_init+0x16c>
408: e5832000 str r2, [r3]
40c: e51b300c ldr r3, [fp, #-12]
410: e5933000 ldr r3, [r3]
414: e3a02000 mov r2, #0
418: e5832000 str r2, [r3]
41c: e51b300c ldr r3, [fp, #-12]
420: e5933000 ldr r3, [r3]
424: e2833004 add r3, r3, #4
428: e3e02000 mvn r2, #0
42c: e5832000 str r2, [r3]
430: e51b300c ldr r3, [fp, #-12]
434: e5933000 ldr r3, [r3]
438: e2833010 add r3, r3, #16
43c: e3a02000 mov r2, #0
440: e5832000 str r2, [r3]
444: e51b300c ldr r3, [fp, #-12]
448: e5933000 ldr r3, [r3]
44c: e2833014 add r3, r3, #20
450: e3a02000 mov r2, #0
454: e5832000 str r2, [r3]
458: e51b300c ldr r3, [fp, #-12]
45c: e5933000 ldr r3, [r3]
460: e3a02c01 mov r2, #256 ; 0x100
464: e5832000 str r2, [r3]
468: e51b300c ldr r3, [fp, #-12]
46c: e5933000 ldr r3, [r3]
470: e2833008 add r3, r3, #8
474: e3a02066 mov r2, #102 ; 0x66
478: e5832000 str r2, [r3]
47c: e51b300c ldr r3, [fp, #-12]
480: e5933000 ldr r3, [r3]
484: e2833018 add r3, r3, #24
488: e3a02b07 mov r2, #7168 ; 0x1c00
48c: e5832000 str r2, [r3]
490: e51b300c ldr r3, [fp, #-12]
494: e5933000 ldr r3, [r3]
498: e5932000 ldr r2, [r3]
49c: e3822040 orr r2, r2, #64 ; 0x40
4a0: e5832000 str r2, [r3]
4a4: e51b300c ldr r3, [fp, #-12]
4a8: e3a02000 mov r2, #0
4ac: e5832004 str r2, [r3, #4]
4b0: e51b3008 ldr r3, [fp, #-8]
4b4: e2833001 add r3, r3, #1
4b8: e50b3008 str r3, [fp, #-8]
4bc: e51b3008 ldr r3, [fp, #-8]
4c0: e3530003 cmp r3, #3
4c4: daffffb3 ble 398 <timer_init+0x18>
4c8: e1a00000 nop ; (mov r0, r0)
4cc: e1a00000 nop ; (mov r0, r0)
4d0: e28bd000 add sp, fp, #0
4d4: e49db004 pop {fp} ; (ldr fp, [sp], #4)
4d8: e12fff1e bx lr
4dc: 00000000 .word 0x00000000
4e0: 101e2000 .word 0x101e2000
4e4: 101e2020 .word 0x101e2020
4e8: 101e3000 .word 0x101e3000
4ec: 101e3020 .word 0x101e3020
000004f0 <timer_clearInterupt>:
4f0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
4f4: e28db000 add fp, sp, #0
4f8: e24dd014 sub sp, sp, #20
4fc: e50b0010 str r0, [fp, #-16]
500: e51b3010 ldr r3, [fp, #-16]
504: e1a03183 lsl r3, r3, #3
508: e59f2028 ldr r2, [pc, #40] ; 538 <timer_clearInterupt+0x48>
50c: e0833002 add r3, r3, r2
510: e50b3008 str r3, [fp, #-8]
514: e51b3008 ldr r3, [fp, #-8]
518: e5933000 ldr r3, [r3]
51c: e283300c add r3, r3, #12
520: e3e02000 mvn r2, #0
524: e5832000 str r2, [r3]
528: e1a00000 nop ; (mov r0, r0)
52c: e28bd000 add sp, fp, #0
530: e49db004 pop {fp} ; (ldr fp, [sp], #4)
534: e12fff1e bx lr
538: 00000000 .word 0x00000000
0000053c <timer_handler>:
53c: e92d4800 push {fp, lr}
540: e28db004 add fp, sp, #4
544: e24dd010 sub sp, sp, #16
548: e50b0010 str r0, [fp, #-16]
54c: e51b3010 ldr r3, [fp, #-16]
550: e1a03183 lsl r3, r3, #3
554: e59f203c ldr r2, [pc, #60] ; 598 <timer_handler+0x5c>
558: e0833002 add r3, r3, r2
55c: e50b3008 str r3, [fp, #-8]
560: e51b3008 ldr r3, [fp, #-8]
564: e5933004 ldr r3, [r3, #4]
568: e2832001 add r2, r3, #1
56c: e51b3008 ldr r3, [fp, #-8]
570: e5832004 str r2, [r3, #4]
574: e51b0010 ldr r0, [fp, #-16]
578: ebfffffe bl 4f0 <timer_clearInterupt>
57c: e59f1018 ldr r1, [pc, #24] ; 59c <timer_handler+0x60>
580: e59f0018 ldr r0, [pc, #24] ; 5a0 <timer_handler+0x64>
584: ebfffffe bl 1c0 <uprints>
588: e1a00000 nop ; (mov r0, r0)
58c: e24bd004 sub sp, fp, #4
590: e8bd4800 pop {fp, lr}
594: e12fff1e bx lr
...
000005a4 <timer_start>:
5a4: e92d4800 push {fp, lr}
5a8: e28db004 add fp, sp, #4
5ac: e24dd010 sub sp, sp, #16
5b0: e50b0010 str r0, [fp, #-16]
5b4: e59f1044 ldr r1, [pc, #68] ; 600 <timer_start+0x5c>
5b8: e59f0044 ldr r0, [pc, #68] ; 604 <timer_start+0x60>
5bc: ebfffffe bl 1c0 <uprints>
5c0: e51b3010 ldr r3, [fp, #-16]
5c4: e1a03183 lsl r3, r3, #3
5c8: e59f2038 ldr r2, [pc, #56] ; 608 <timer_start+0x64>
5cc: e0833002 add r3, r3, r2
5d0: e50b3008 str r3, [fp, #-8]
5d4: e51b3008 ldr r3, [fp, #-8]
5d8: e5933000 ldr r3, [r3]
5dc: e2832008 add r2, r3, #8
5e0: e5922000 ldr r2, [r2]
5e4: e2833008 add r3, r3, #8
5e8: e3822080 orr r2, r2, #128 ; 0x80
5ec: e5832000 str r2, [r3]
5f0: e1a00000 nop ; (mov r0, r0)
5f4: e24bd004 sub sp, fp, #4
5f8: e8bd4800 pop {fp, lr}
5fc: e12fff1e bx lr
600: 00000010 .word 0x00000010
...
0000060c <timer_stop>:
60c: e52db004 push {fp} ; (str fp, [sp, #-4]!)
610: e28db000 add fp, sp, #0
614: e24dd014 sub sp, sp, #20
618: e50b0010 str r0, [fp, #-16]
61c: e51b3010 ldr r3, [fp, #-16]
620: e1a03183 lsl r3, r3, #3
624: e59f2028 ldr r2, [pc, #40] ; 654 <timer_stop+0x48>
628: e0833002 add r3, r3, r2
62c: e50b3008 str r3, [fp, #-8]
630: e51b3008 ldr r3, [fp, #-8]
634: e5933000 ldr r3, [r3]
638: e2833008 add r3, r3, #8
63c: e3a0207f mov r2, #127 ; 0x7f
640: e5832000 str r2, [r3]
644: e1a00000 nop ; (mov r0, r0)
648: e28bd000 add sp, fp, #0
64c: e49db004 pop {fp} ; (ldr fp, [sp], #4)
650: e12fff1e bx lr
654: 00000000 .word 0x00000000
00000658 <undef_handler>:
658: e92d4800 push {fp, lr}
65c: e28db004 add fp, sp, #4
660: e59f1014 ldr r1, [pc, #20] ; 67c <undef_handler+0x24>
664: e59f0014 ldr r0, [pc, #20] ; 680 <undef_handler+0x28>
668: ebfffffe bl 1c0 <uprints>
66c: e1a00000 nop ; (mov r0, r0)
670: e24bd004 sub sp, fp, #4
674: e8bd4800 pop {fp, lr}
678: e12fff1e bx lr
67c: 00000020 .word 0x00000020
680: 00000000 .word 0x00000000
00000684 <swi_handler>:
684: e92d4800 push {fp, lr}
688: e28db004 add fp, sp, #4
68c: e59f1014 ldr r1, [pc, #20] ; 6a8 <swi_handler+0x24>
690: e59f0014 ldr r0, [pc, #20] ; 6ac <swi_handler+0x28>
694: ebfffffe bl 1c0 <uprints>
698: e1a00000 nop ; (mov r0, r0)
69c: e24bd004 sub sp, fp, #4
6a0: e8bd4800 pop {fp, lr}
6a4: e12fff1e bx lr
6a8: 00000020 .word 0x00000020
6ac: 00000000 .word 0x00000000
000006b0 <prefetch_abort_handler>:
6b0: e92d4800 push {fp, lr}
6b4: e28db004 add fp, sp, #4
6b8: e59f1014 ldr r1, [pc, #20] ; 6d4 <prefetch_abort_handler+0x24>
6bc: e59f0014 ldr r0, [pc, #20] ; 6d8 <prefetch_abort_handler+0x28>
6c0: ebfffffe bl 1c0 <uprints>
6c4: e1a00000 nop ; (mov r0, r0)
6c8: e24bd004 sub sp, fp, #4
6cc: e8bd4800 pop {fp, lr}
6d0: e12fff1e bx lr
6d4: 00000020 .word 0x00000020
6d8: 00000000 .word 0x00000000
000006dc <data_abort_handler>:
6dc: e92d4800 push {fp, lr}
6e0: e28db004 add fp, sp, #4
6e4: e59f1014 ldr r1, [pc, #20] ; 700 <data_abort_handler+0x24>
6e8: e59f0014 ldr r0, [pc, #20] ; 704 <data_abort_handler+0x28>
6ec: ebfffffe bl 1c0 <uprints>
6f0: e1a00000 nop ; (mov r0, r0)
6f4: e24bd004 sub sp, fp, #4
6f8: e8bd4800 pop {fp, lr}
6fc: e12fff1e bx lr
700: 00000020 .word 0x00000020
704: 00000000 .word 0x00000000
00000708 <fiq_handler>:
708: e92d4800 push {fp, lr}
70c: e28db004 add fp, sp, #4
710: e59f1014 ldr r1, [pc, #20] ; 72c <fiq_handler+0x24>
714: e59f0014 ldr r0, [pc, #20] ; 730 <fiq_handler+0x28>
718: ebfffffe bl 1c0 <uprints>
71c: e1a00000 nop ; (mov r0, r0)
720: e24bd004 sub sp, fp, #4
724: e8bd4800 pop {fp, lr}
728: e12fff1e bx lr
72c: 00000020 .word 0x00000020
730: 00000000 .word 0x00000000
00000734 <copy_vector>:
734: e52db004 push {fp} ; (str fp, [sp, #-4]!)
738: e28db000 add fp, sp, #0
73c: e24dd00c sub sp, sp, #12
740: e59f3050 ldr r3, [pc, #80] ; 798 <copy_vector+0x64>
744: e50b3008 str r3, [fp, #-8]
748: e3a03000 mov r3, #0
74c: e50b300c str r3, [fp, #-12]
750: ea000007 b 774 <copy_vector+0x40>
754: e51b2008 ldr r2, [fp, #-8]
758: e2823004 add r3, r2, #4
75c: e50b3008 str r3, [fp, #-8]
760: e51b300c ldr r3, [fp, #-12]
764: e2831004 add r1, r3, #4
768: e50b100c str r1, [fp, #-12]
76c: e5922000 ldr r2, [r2]
770: e5832000 str r2, [r3]
774: e51b3008 ldr r3, [fp, #-8]
778: e59f201c ldr r2, [pc, #28] ; 79c <copy_vector+0x68>
77c: e1530002 cmp r3, r2
780: 3afffff3 bcc 754 <copy_vector+0x20>
784: e1a00000 nop ; (mov r0, r0)
788: e1a00000 nop ; (mov r0, r0)
78c: e28bd000 add sp, fp, #0
790: e49db004 pop {fp} ; (ldr fp, [sp], #4)
794: e12fff1e bx lr
...
000007a0 <kbd_init>:
7a0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
7a4: e28db000 add fp, sp, #0
7a8: e24dd00c sub sp, sp, #12
7ac: e59f302c ldr r3, [pc, #44] ; 7e0 <kbd_init+0x40>
7b0: e50b3008 str r3, [fp, #-8]
7b4: e51b3008 ldr r3, [fp, #-8]
7b8: e3a02014 mov r2, #20
7bc: e5c32000 strb r2, [r3]
7c0: e51b3008 ldr r3, [fp, #-8]
7c4: e283300c add r3, r3, #12
7c8: e3a02008 mov r2, #8
7cc: e5c32000 strb r2, [r3]
7d0: e1a00000 nop ; (mov r0, r0)
7d4: e28bd000 add sp, fp, #0
7d8: e49db004 pop {fp} ; (ldr fp, [sp], #4)
7dc: e12fff1e bx lr
7e0: 10006000 .word 0x10006000
000007e4 <IRQ_handler>:
7e4: e92d4800 push {fp, lr}
7e8: e28db004 add fp, sp, #4
7ec: e24dd008 sub sp, sp, #8
7f0: e3a03000 mov r3, #0
7f4: e50b3008 str r3, [fp, #-8]
7f8: e59f10a4 ldr r1, [pc, #164] ; 8a4 <IRQ_handler+0xc0>
7fc: e59f00a4 ldr r0, [pc, #164] ; 8a8 <IRQ_handler+0xc4>
800: ebfffffe bl 1c0 <uprints>
804: e59f30a0 ldr r3, [pc, #160] ; 8ac <IRQ_handler+0xc8>
808: e5933000 ldr r3, [r3]
80c: e5933000 ldr r3, [r3]
810: e2833004 add r3, r3, #4
814: e5933000 ldr r3, [r3]
818: e3530000 cmp r3, #0
81c: 1a000001 bne 828 <IRQ_handler+0x44>
820: e3a00000 mov r0, #0
824: ebfffffe bl 53c <timer_handler>
828: e59f307c ldr r3, [pc, #124] ; 8ac <IRQ_handler+0xc8>
82c: e5933004 ldr r3, [r3, #4]
830: e5933000 ldr r3, [r3]
834: e2833004 add r3, r3, #4
838: e5933000 ldr r3, [r3]
83c: e3530000 cmp r3, #0
840: 1a000001 bne 84c <IRQ_handler+0x68>
844: e3a00001 mov r0, #1
848: ebfffffe bl 53c <timer_handler>
84c: e59f3058 ldr r3, [pc, #88] ; 8ac <IRQ_handler+0xc8>
850: e5933008 ldr r3, [r3, #8]
854: e5933000 ldr r3, [r3]
858: e2833004 add r3, r3, #4
85c: e5933000 ldr r3, [r3]
860: e3530000 cmp r3, #0
864: 1a000001 bne 870 <IRQ_handler+0x8c>
868: e3a00002 mov r0, #2
86c: ebfffffe bl 53c <timer_handler>
870: e59f3034 ldr r3, [pc, #52] ; 8ac <IRQ_handler+0xc8>
874: e593300c ldr r3, [r3, #12]
878: e5933000 ldr r3, [r3]
87c: e2833004 add r3, r3, #4
880: e5933000 ldr r3, [r3]
884: e3530000 cmp r3, #0
888: 1a000001 bne 894 <IRQ_handler+0xb0>
88c: e3a00003 mov r0, #3
890: ebfffffe bl 53c <timer_handler>
894: e1a00000 nop ; (mov r0, r0)
898: e24bd004 sub sp, fp, #4
89c: e8bd4800 pop {fp, lr}
8a0: e12fff1e bx lr
8a4: 00000030 .word 0x00000030
...
000008b0 <main>:
8b0: e92d4800 push {fp, lr}
8b4: e28db004 add fp, sp, #4
8b8: e24dd010 sub sp, sp, #16
8bc: ebfffffe bl 218 <fbuf_init>
8c0: ebfffffe bl 0 <uart_init>
8c4: ebfffffe bl 380 <timer_init>
8c8: ebfffffe bl 7a0 <kbd_init>
8cc: e3a03000 mov r3, #0
8d0: e50b3008 str r3, [fp, #-8]
8d4: ea00000b b 908 <main+0x58>
8d8: e51b3008 ldr r3, [fp, #-8]
8dc: e1a03183 lsl r3, r3, #3
8e0: e59f20dc ldr r2, [pc, #220] ; 9c4 <main+0x114>
8e4: e0832002 add r2, r3, r2
8e8: e59f10d8 ldr r1, [pc, #216] ; 9c8 <main+0x118>
8ec: e51b3008 ldr r3, [fp, #-8]
8f0: e7812103 str r2, [r1, r3, lsl #2]
8f4: e51b0008 ldr r0, [fp, #-8]
8f8: ebfffffe bl 5a4 <timer_start>
8fc: e51b3008 ldr r3, [fp, #-8]
900: e2833001 add r3, r3, #1
904: e50b3008 str r3, [fp, #-8]
908: e51b3008 ldr r3, [fp, #-8]
90c: e3530003 cmp r3, #3
910: dafffff0 ble 8d8 <main+0x28>
914: e59f10b0 ldr r1, [pc, #176] ; 9cc <main+0x11c>
918: e59f00b0 ldr r0, [pc, #176] ; 9d0 <main+0x120>
91c: ebfffffe bl 1c0 <uprints>
920: e59f309c ldr r3, [pc, #156] ; 9c4 <main+0x114>
924: e5931004 ldr r1, [r3, #4]
928: e59f30a4 ldr r3, [pc, #164] ; 9d4 <main+0x124>
92c: e0c32391 smull r2, r3, r1, r3
930: e1a021c3 asr r2, r3, #3
934: e1a03fc1 asr r3, r1, #31
938: e0422003 sub r2, r2, r3
93c: e1a03002 mov r3, r2
940: e1a03183 lsl r3, r3, #3
944: e0433002 sub r3, r3, r2
948: e1a03183 lsl r3, r3, #3
94c: e0433002 sub r3, r3, r2
950: e1a03103 lsl r3, r3, #2
954: e0412003 sub r2, r1, r3
958: e1a03002 mov r3, r2
95c: e54b3009 strb r3, [fp, #-9]
960: e55b3009 ldrb r3, [fp, #-9]
964: e2833037 add r3, r3, #55 ; 0x37
968: e20330ff and r3, r3, #255 ; 0xff
96c: e1a01003 mov r1, r3
970: e59f0058 ldr r0, [pc, #88] ; 9d0 <main+0x120>
974: ebfffffe bl e4 <uputc>
978: e55b3009 ldrb r3, [fp, #-9]
97c: e383386e orr r3, r3, #7208960 ; 0x6e0000
980: e3833001 orr r3, r3, #1
984: e50b3010 str r3, [fp, #-16]
988: e51b3010 ldr r3, [fp, #-16]
98c: e3a02064 mov r2, #100 ; 0x64
990: e3a0100a mov r1, #10
994: e3a0000a mov r0, #10
998: ebfffffe bl 2b8 <draw_box>
99c: e59f3020 ldr r3, [pc, #32] ; 9c4 <main+0x114>
9a0: e5933004 ldr r3, [r3, #4]
9a4: e3530000 cmp r3, #0
9a8: 0affffdc beq 920 <main+0x70>
9ac: e3a03b32 mov r3, #51200 ; 0xc800
9b0: e3a02032 mov r2, #50 ; 0x32
9b4: e3a010fa mov r1, #250 ; 0xfa
9b8: e3a000c8 mov r0, #200 ; 0xc8
9bc: ebfffffe bl 2b8 <draw_box>
9c0: eaffffd6 b 920 <main+0x70>
...
9cc: 0000003c .word 0x0000003c
9d0: 00000000 .word 0x00000000
9d4: 094f2095 .word 0x094f2095
also my linker script:
ENTRY(start)
SECTIONS{
. = 0x10000;
.text : {*(.text)}
.data : {*(.data)}
.bss : {*(.bss)}
. =ALIGN(8);
. =. + 0x1000;
stack_top = .;
. = . + 0x1000;
irq_stack_top = .;
}
So I do not have a complete example but something looks wrong, really wrong that you will need to sort out. And maybe you are already through all of these basic steps to get to this point.
qemu-system-arm -M versatilepb -m 128M -kernel notmain.bin
Implies a binary memory image file as in objcopy -O binary is being used. And there is no addressing information, so some default built into that machine or simulation is being used. What is that address....
strap.s
mov sp,#0x10000
bl notmain
b .
.globl GETPC
GETPC:
mov r0,pc
bx lr
.globl PUT32
PUT32:
str r1,[r0]
bx lr
notmain.c
void PUT32 ( unsigned int, unsigned int );
unsigned int GETPC ( void );
#define UART_BASE 0x101F1000
#define UARTDR (UART_BASE+0x000)
static void uart_send ( unsigned int x )
{
PUT32(UARTDR,x);
}
static void hexstrings ( unsigned int d )
{
unsigned int rb;
unsigned int rc;
rb=32;
while(1)
{
rb-=4;
rc=(d>>rb)&0xF;
if(rc>9) rc+=0x37; else rc+=0x30;
uart_send(rc);
if(rb==0) break;
}
uart_send(0x20);
}
static void hexstring ( unsigned int d )
{
hexstrings(d);
uart_send(0x0D);
uart_send(0x0A);
}
int notmain ( void )
{
hexstring(GETPC());
return(0);
}
uart address culled from the source code to qemu. so far I find you can cheat and just write to the tx buffer, it does not actually emulate the time it takes to send out a character and overflow a fifo, etc. So I cheat.
/* memmap */
MEMORY
{
ram : ORIGIN = 0x00000000, LENGTH = 32K
}
SECTIONS
{
.text : { *(.text*) } > ram
.bss : { *(.text*) } > ram
}
build
arm-none-eabi-as --warn --fatal-warnings -march=armv4t strap.s -o strap.o
arm-none-eabi-gcc -c -Wall -O2 -ffreestanding -march=armv4t notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles strap.o notmain.o -T memmap -o notmain.elf
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy notmain.elf -O binary notmain.bin
examine output
Disassembly of section .text:
00000000 <GETPC-0xc>:
0: e3a0d801 mov sp, #65536 ; 0x10000
4: eb000004 bl 1c <notmain>
8: eafffffe b 8 <GETPC-0x4>
0000000c <GETPC>:
c: e1a0000f mov r0, pc
10: e12fff1e bx lr
00000014 <PUT32>:
14: e5801000 str r1, [r0]
18: e12fff1e bx lr
0000001c <notmain>:
1c: e92d4070 push {r4, r5, r6, lr}
20: ebfffff9 bl c <GETPC>
24: e3a04020 mov r4, #32
my entry point is where I want it. I am not loading an elf I am loading a binary image. If I wanted the entry point to be different and load an elf it may be possible that using ENTRY() in the linker script then having the entry point wherever might work.
qemu-system-arm -M versatilepb -m 128M -kernel notmain.bin
then view the serial0 output of 00010014 so they are loading us at 0x10000 so change memmap
ram : ORIGIN = 0x00010000, LENGTH = 32K
Now your linker script implies it should have put your code at 0x10000 but
clearly it has not based on your disassembly, so how are you running anything at all. Also your entry point using a binary image is not the bootstrap it is not the first instructions you want to be executing. maybe you disassembled an object not the final binary?
So for fun before changing the memory map to 0x10000 if I instead
qemu-system-arm -M versatilepb -m 128M -kernel notmain.elf
Then I get 00000014 on the output. it used the address defined in the elf file.
If I add this
b .
.globl _start
_start:
mov sp,#0x10000
bl notmain
b .
and this
/* memmap */
ENTRY(_start)
MEMORY
{
ram : ORIGIN = 0x00000000, LENGTH = 32K
}
SECTIONS
{
.text : { *(.text*) } > ram
.bss : { *(.text*) } > ram
}
and execute the elf I do get output of 00000018 so it is entering at the entry point not the first word of the loadable image.
run the .bin and you get no serial output as expected.
Change memmap to 0x10000 and run the elf you get 0x10018 as expected.
So that was a simple way to see how qemu loads our program.
so same build and linker script (with the 0x10000)
.globl _start
_start:
ldr pc,reset_handler
ldr pc,undefined_handler
ldr pc,swi_handler
ldr pc,prefetch_handler
ldr pc,data_handler
ldr pc,unused_handler
ldr pc,irq_handler
ldr pc,fiq_handler
reset_handler: .word reset
undefined_handler: .word hang
swi_handler: .word swi
prefetch_handler: .word hang
data_handler: .word hang
unused_handler: .word hang
irq_handler: .word hang
fiq_handler: .word hang
reset:
mov r0,#0x10000
mov r1,#0x00000
ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9}
stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9}
ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9}
stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9}
;# FIQ 110 10001
msr cpsr_c,#0xD1
mov sp,#0x1000
;# IRQ 110 10010
msr cpsr_c,#0xD2
mov sp,#0x2000
;# SVC 110 10011
msr cpsr_c,#0xD3
mov sp,#0x3000
;# ABT 110 10111
msr cpsr_c,#0xD7
mov sp,#0x4000
;# UND 110 11011
msr cpsr_c,#0xDB
mov sp,#0x5000
;# SYS 110 11111
msr cpsr_c,#0xDF
mov sp,#0x6000
;# SVC 110 10011
msr cpsr_c,#0xD3
bl notmain
hang:
b hang
swi:
push {r4-r12,lr}
bl swi_main
pop {r4-r12,lr}
movs pc,lr
.globl DO_SWI
DO_SWI:
push {lr}
svc 0
pop {lr}
bx lr
.globl GO_USER
GO_USER:
;# USER 110 10000
msr cpsr_c,#0xD0
bl gouser
b .
gouser:
bx r0
.globl GETMODE
GETMODE:
mrs r0,cpsr
bx lr
.globl GETPC
GETPC:
mov r0,pc
bx lr
.globl GETSP
GETSP:
mov r0,sp
bx lr
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.globl GET32
GET32:
ldr r0,[r0]
bx lr
and
void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
unsigned int GETPC ( void );
unsigned int GETSP ( void );
unsigned int GETMODE ( void );
unsigned int GO_USER ( unsigned int );
unsigned int DO_SWI ( unsigned int, unsigned int, unsigned int, unsigned int );
#define UART_BASE 0x101F1000
#define UARTDR (UART_BASE+0x000)
#define UARTFR (UART_BASE+0x018)
static void uart_send ( unsigned int x )
{
while(1)
{
if(GET32(UARTFR)&(1<<7)) break;
}
PUT32(UARTDR,x);
}
static void hexstrings ( unsigned int d )
{
unsigned int rb;
unsigned int rc;
rb=32;
while(1)
{
rb-=4;
rc=(d>>rb)&0xF;
if(rc>9) rc+=0x37; else rc+=0x30;
uart_send(rc);
if(rb==0) break;
}
uart_send(0x20);
}
static void hexstring ( unsigned int d )
{
hexstrings(d);
uart_send(0x0D);
uart_send(0x0A);
}
unsigned int swi_main ( unsigned int a, unsigned int b, unsigned int c, unsigned int d )
{
hexstring(0xAABBCCDD);
switch(a)
{
case 0:
{
return(~b);
}
case 1:
{
return(GETMODE());
}
}
return(0);
}
void user_main ( void )
{
hexstring(GETMODE());
hexstring(GETSP());
hexstring(DO_SWI(0,0x1234,0,0));
hexstring(DO_SWI(1,0x1234,0,0));
}
int notmain ( void )
{
hexstring(GETMODE());
hexstring(GETSP());
GO_USER((unsigned int)user_main);
return(0);
}
get even a trivial swi in place first before attempting an interrupt. getting the exception table in place, the banked stack registers, etc. seems trivial but even with experience those things bite you and you end up chasing the wrong thing.
400001D3
00002FF8
200001D0
00005FF8
AABBCCDD
FFFFEDCB
AABBCCDD
600001D3
this was a bit overkill with mode changes and such, but it still has the swi handler in the right place. The code is linked for
notmain.elf: file format elf32-littlearm
Disassembly of section .text:
00010000 <_start>:
10000: e59ff018 ldr pc, [pc, #24] ; 10020 <reset_handler>
10004: e59ff018 ldr pc, [pc, #24] ; 10024 <undefined_handler>
10008: e59ff018 ldr pc, [pc, #24] ; 10028 <swi_handler>
1000c: e59ff018 ldr pc, [pc, #24] ; 1002c <prefetch_handler>
10010: e59ff018 ldr pc, [pc, #24] ; 10030 <data_handler>
10014: e59ff018 ldr pc, [pc, #24] ; 10034 <unused_handler>
10018: e59ff018 ldr pc, [pc, #24] ; 10038 <irq_handler>
1001c: e59ff018 ldr pc, [pc, #24] ; 1003c <fiq_handler>
00010020 <reset_handler>:
10020: 00010040 andeq r0, r1, r0, asr #32
00010024 <undefined_handler>:
10024: 00010090 muleq r1, r0, r0
packing the exception table with its pc-relative addresses and letting the toolchain do all the work of sorting out addresses for you, you can then simply copy it to 0x00000000 from 0x10000. It is probably fine but in your case I would at least put some level of alignment before your table, something makes me want to think it wants to be aligned. However you wish to copy it is your deal, I would not use C in a bootstrap, the habit creates problems from time to time that are easily avoided.
Knowing what we know of course if we linked for address 0x00000000 and used the elf file then we do not have to copy/move the exception table. It lands in the right place on load.
Newer cores have a VTOR register and you can simply choose a different exception or vector table address, but it does need to have a level of alignment that you cannot forget.
I did not go and research this timer, but I assume long before you attempted an interrupt you wrote very many throwaway programs that used polling to fully understand the timer and how to clear its interrupt, etc? Depending on the chip (not necessarily core) then there may also be arm side registers you can poll, disable interrupts into the core, poll the gvic or vpic or whatever it is called and see the interrupt hit the edge of the core, be able to turn it off, etc. Then.....enable it into the core now that you have mastered that peripheral. Sometimes leaving nothing left to work on, for some cores though there is some interrupt stuff that can only be done in an isr (how to detect and clear the interrupt source) this virtual machine predates that by a long time though, so no worries there.
so...
If that is your linker script then why is your output zero based, and why is the uart function up front and not the bootstrap entry point? If that is the disassembly of the final binary then there are all kinds of problems going on there.
I was seeing this as baremetal but forgetting qemu is loading linux-like so at some address like 0x8000, 0x10000, or 0x80000 are some examples, so yes you either need a core with a VTOR or copy the exception table over, and letting the tools build the addresses and pc-relative loads is the way to go. That copy is probably fine if you are actually booting right and executing it.
Then have you completely mastered that peripheral?
This is an emulated core so it may resemble one/some of the products from arm but remember they are not all identical some come with interrupt controllers some do not, some folks like the raspi folks disable that interrupt controller, etc. The base address of add on peripherals for real arm cores is based on the chip vendor not arm. Etc....Best to dig through the source code for the specific machine emulation and see what it is doing to truly get a qemu machine to work.
So maybe you have done all of these things and it still does not work. The question as written has some issues, the disassembly does not make sense for example. Need to resolve that. What if you try with an elf file first and an entry point then do the extra work to be able to run without the elf file and the bin file instead. Do not re-write but add more content to the question if you need further help. Unless someone else sees the issue with what has been presented.

Issues with ARMv7-A bare metal call stack [duplicate]

This question already has an answer here:
Rustc/LLVM generates faulty code for aarch64 with opt-level=0
(1 answer)
Closed 7 years ago.
I'm trying to get a small ARM kernel up and running on QEMU (Versatile Express for Cortex-A15). Currently it simply sets sp to the top of a small stack and sends a single character to UART0.
_start.arm:
.set stack_size, 0x10000
.comm stack, stack_size
.global _start
_start:
ldr sp, =stack+stack_size
bl start
1:
b 1b
.size _start, . - _start
start.c:
/* UART_0 is a struct overlaid on 0x1c090000 */
void printChar(char c)
{
while (UART_0->flags & TRANSMIT_FULL);
UART_0->data = c;
}
void start()
{
while (UART_0->flags & TRANSMIT_FULL);
UART_0->data = 'A';
printChar('a');
}
From GDB, I know that execution progresses through _start into start and successfully sends 'A' to UART_0. printChar gets called and completes, but doesn't seem to print anything to the serial port . When running without GDB, the kernel repeatedly prints 'A', though I'm not sure if this is the processor resetting or jumping incorrectly.
From objdump:
Disassembly of section .stub:
00010000 <_start>:
10000: e59fd004 ldr sp, [pc, #4] ; 1000c <__STACK_SIZE+0xc>
10004: eb000016 bl 10064 <start>
10008: eafffffe b 10008 <_start+0x8>
1000c: 000200d0 .word 0x000200d0
Disassembly of section .text:
00010010 <printChar>:
10010: e52db004 push {fp} ; (str fp, [sp, #-4]!)
10014: e28db000 add fp, sp, #0
10018: e24dd00c sub sp, sp, #12
1001c: e1a03000 mov r3, r0
10020: e54b3005 strb r3, [fp, #-5]
10024: e1a00000 nop ; (mov r0, r0)
10028: e3a03000 mov r3, #0
1002c: e3413c09 movt r3, #7177 ; 0x1c09
10030: e1d331ba ldrh r3, [r3, #26]
10034: e6ff3073 uxth r3, r3
10038: e2033020 and r3, r3, #32
1003c: e3530000 cmp r3, #0
10040: 1afffff8 bne 10028 <printChar+0x18>
10044: e3a03000 mov r3, #0
10048: e3413c09 movt r3, #7177 ; 0x1c09
1004c: e55b2005 ldrb r2, [fp, #-5]
10050: e6ff2072 uxth r2, r2
10054: e1c320b2 strh r2, [r3, #2]
10058: e24bd000 sub sp, fp, #0
1005c: e49db004 pop {fp} ; (ldr fp, [sp], #4)
10060: e12fff1e bx lr
00010064 <start>:
10064: e52db008 str fp, [sp, #-8]!
10068: e58de004 str lr, [sp, #4]
1006c: e28db004 add fp, sp, #4
10070: e1a00000 nop ; (mov r0, r0)
10074: e3a03000 mov r3, #0
10078: e3413c09 movt r3, #7177 ; 0x1c09
1007c: e1d331ba ldrh r3, [r3, #26]
10080: e6ff3073 uxth r3, r3
10084: e2033020 and r3, r3, #32
10088: e3530000 cmp r3, #0
1008c: 1afffff8 bne 10074 <start+0x10>
10090: e3a03000 mov r3, #0
10094: e3413c09 movt r3, #7177 ; 0x1c09
10098: e5d32002 ldrb r2, [r3, #2]
1009c: e3a02000 mov r2, #0
100a0: e3822041 orr r2, r2, #65 ; 0x41
100a4: e5c32002 strb r2, [r3, #2]
100a8: e5d32003 ldrb r2, [r3, #3]
100ac: e3a02000 mov r2, #0
100b0: e5c32003 strb r2, [r3, #3]
100b4: e3a00061 mov r0, #97 ; 0x61
100b8: ebffffd4 bl 10010 <printChar>
100bc: e24bd004 sub sp, fp, #4
100c0: e59db000 ldr fp, [sp]
100c4: e28dd004 add sp, sp, #4
100c8: e49df004 pop {pc} ; (ldr pc, [sp], #4)
000100cc <UART_0>:
100cc: 1c090000 ....
I may have missed something, but I am not seeing where you have enabled interrupts, or poll to see if you can send the next character. If you have enabled the interrupts and set up the UART hardware correctly, your driver my have a bug. If you have not setup the UART hardware correctly, it may not be generating interrupts, or it may not be doing the FIFO correctly, or any number of other problems.

Inline assembly instruction on ARM64 (iOS) fails

I'm trying out the new arm64 instructions on iOS and I'm having a peculiar issue. I hope someone can help me with this.
In particular this fails with 'Invalid operand for instruction'
void test()
{
register long long signed int r=0,c=0,d=0;
register signed int a=0,b=0,e=0,f=0;
// this fails
asm volatile("smaddl %0, %1, %2, %3" : "=r"(r) : "r"(a), "r"(b), "r"(c));
};
I'm not sure what I'm doing wrong, to the best that I can tell, I'm following the instruction and syntax correctly. Here's how it is defined in the docs:
"SMADDL Xd, Wn, Wm, Xa
Signed Multiply-Add Long: Xd = Xa + (Wn × Wm), treating source operands as signed."
where X denotes a 64bit register and W denotes a 32 bit one.
Any help will be appreciated.
Thx
I was able to fix it by using recommendation in this post:
asm volatile("smaddl %x0, %w1, %w2, %x3" : "=r"(r) : "r"(a), "r"(b), "r"(c));
This produces the following assembly:
_test: ; #test
; BB#0:
sub sp, sp, #48
movz w8, #0
movz x9, #0
stp x9, x9, [sp, #32]
str x9, [sp, #24]
stp w8, w8, [sp, #16]
stp w8, w8, [sp, #8]
ldp w10, w8, [sp, #16]
ldr x9, [sp, #32]
; InlineAsm Start
smaddl x9, w8, w10, x9
; InlineAsm End
str x9, [sp, #40]
add sp, sp, #48
ret lr
It seems you need to use 'w' to specifically mark 32-bit registers.
See also aarch64-inline-asm.c for a few more inline asm examples.

Resources