; #include <stdlib.h>
;
; void leaf_call(int b, int c, int d, int e, int f, int g, int h)
; {
; }
;
; void nonleaf_call(int a, int b, int c, int d, int e, int f, int g, int h)
; {
; /* use some local data */
; *(char*)alloca(220) = 'L';
; leaf_call(b, c, d, e, f, g, h);
; }
;
; int main()
; {
; nonleaf_call(0, 1, 2, 3, 4, 5, 6, 7);
; return 0;
; }
; output from netbsd-4.0.1-cats w/ gcc 4.1.2
00000000 <leaf_call>:
0: e1a0c00d mov ip, sp
4: e92dd800 stmdb sp!, {fp, ip, lr, pc}
8: e24cb004 sub fp, ip, #4 ; 0x4
c: e24dd010 sub sp, sp, #16 ; 0x10
10: e50b0010 str r0, [fp, #-16]
14: e50b1014 str r1, [fp, #-20]
18: e50b2018 str r2, [fp, #-24]
1c: e50b301c str r3, [fp, #-28]
20: e24bd00c sub sp, fp, #12 ; 0xc
24: e89da800 ldmia sp, {fp, sp, pc}
00000028 <nonleaf_call>:
28: e1a0c00d mov ip, sp ; |
;spill here, if needed: stmdb sp!, {r0, r1, r2, r3} ; | just for ref, if present this would change below offsets
2c: e92dd800 stmdb sp!, {fp, ip, lr, pc} ; |
30: e24cb004 sub fp, ip, #4 ; | prolog
34: e24dd020 sub sp, sp, #32 ; |
38: e50b0010 str r0, [fp, #-16] ; in arg 0 -> temp space in local area
3c: e50b1014 str r1, [fp, #-20] ; in arg 1 -> temp space in local area
40: e50b2018 str r2, [fp, #-24] ; in arg 2 -> temp space in local area
44: e50b301c str r3, [fp, #-28] ; in arg 3 -> temp space in local area
48: e24dd0e0 sub sp, sp, #224 ; alloca(220) - with padding to guarantee alignment
4c: e28d200c add r2, sp, #12 ; |
50: e50b2020 str r2, [fp, #-32] ; | @@@ pointless push of r2 to local area to put it back ...
54: e51b2020 ldr r2, [fp, #-32] ; | @@@ ... into r2
58: e2823003 add r3, r2, #3 ; | start of (aligned) alloca()'d memory -> r3, leaving room at top of stack for param area
5c: e1a03123 mov r3, r3, lsr #2 ; |
60: e1a03103 mov r3, r3, lsl #2 ; /
64: e50b3020 str r3, [fp, #-32] ; \
68: e51b2020 ldr r2, [fp, #-32] ; | r2 -> r3, to free r2 (kinda pointless as followup code could use r2 and r3 the other way round)
6c: e3a0304c mov r3, #76 ; 'L' -> r3, and ...
70: e5c23000 strb r3, [r2] ; ... store in local area (of alloca()'d space)
74: e59b3008 ldr r3, [fp, #8] ; arg 4 (fetched from prev frame's param area), and ...
78: e58d3000 str r3, [sp] ; ... "pushed" onto stack
7c: e59b300c ldr r3, [fp, #12] ; arg 5 (fetched from prev frame's param area), and ...
80: e58d3004 str r3, [sp, #4] ; ... "pushed" onto stack
84: e59b3010 ldr r3, [fp, #16] ; arg 6 (fetched from prev frame's param area), and ...
88: e58d3008 str r3, [sp, #8] ; ... "pushed" onto stack
8c: e51b0014 ldr r0, [fp, #-20] ; arg 0
90: e51b1018 ldr r1, [fp, #-24] ; arg 1
94: e51b201c ldr r2, [fp, #-28] ; arg 2
98: e59b3004 ldr r3, [fp, #4] ; arg 3 (fetched from prev frame's param area)
9c: ebfffffe bl 9c <nonleaf_call+0x74> ; return address -> r14/lr, and call
a0: e24bd00c sub sp, fp, #12 ; |
a4: e89da800 ldmia sp, {fp, sp, pc} ; | epilog
000000a8 <main>:
a8: e1a0c00d mov ip, sp ; |
ac: e92dd800 stmdb sp!, {fp, ip, lr, pc} ; |
b0: e24cb004 sub fp, ip, #4 ; | prolog
b4: e24dd010 sub sp, sp, #16 ; |
b8: e3a03004 mov r3, #4 ; arg 4, and ...
bc: e58d3000 str r3, [sp] ; ... "pushed" onto stack
c0: e3a03005 mov r3, #5 ; arg 5, and ...
c4: e58d3004 str r3, [sp, #4] ; ... "pushed" onto stack
c8: e3a03006 mov r3, #6 ; arg 6, and ...
cc: e58d3008 str r3, [sp, #8] ; ... "pushed" onto stack
d0: e3a03007 mov r3, #7 ; arg 7, and ...
d4: e58d300c str r3, [sp, #12] ; ... "pushed" onto stack
d8: e3a00000 mov r0, #0 ; arg 0
dc: e3a01001 mov r1, #1 ; arg 1
e0: e3a02002 mov r2, #2 ; arg 2
e4: e3a03003 mov r3, #3 ; arg 3
e8: ebfffffe bl e8 <main+0x40> ; return address -> r14/lr, and call
ec: e3a03000 mov r3, #0 ; return value via r3, ... (a bit unoptimal)
f0: e1a00003 mov r0, r3 ; ... to r0
f4: e24bd00c sub sp, fp, #12 ; |
f8: e89da800 ldmia sp, {fp, sp, pc} ; | epilog
; output from freebsd-11.0_r260099-raspberrypi w/ clang 3.3
00000000 <leaf_call>:
0: e24dd030 sub sp, sp, #48 ; 0x30
4: e58d002c str r0, [sp, #44]
8: e58d1028 str r1, [sp, #40]
c: e58d2024 str r2, [sp, #36]
10: e58d3020 str r3, [sp, #32]
14: e59dc030 ldr ip, [sp, #48]
18: e58dc01c str ip, [sp, #28]
1c: e59dc034 ldr ip, [sp, #52]
20: e58dc018 str ip, [sp, #24]
24: e59dc038 ldr ip, [sp, #56]
28: e58dc014 str ip, [sp, #20]
2c: e58d1010 str r1, [sp, #16]
30: e58d300c str r3, [sp, #12]
34: e58d2008 str r2, [sp, #8]
38: e58d0004 str r0, [sp, #4]
3c: e28dd030 add sp, sp, #48 ; 0x30
40: e12fff1e bx lr
00000044 <nonleaf_call>:
44: e92d4bf0 push {r4, r5, r6, r7, r8, r9, fp, lr}
48: e28db018 add fp, sp, #24 ; 0x18
4c: e24ddf4a sub sp, sp, #296 ; 0x128
50: e50b001c str r0, [fp, #-28]
54: e50b1020 str r1, [fp, #-32]
58: e50b2024 str r2, [fp, #-36]
5c: e50b3028 str r3, [fp, #-40]
60: e59bc008 ldr ip, [fp, #8]
64: e50bc02c str ip, [fp, #-44]
68: e59bc00c ldr ip, [fp, #12]
6c: e50bc030 str ip, [fp, #-48]
70: e59bc010 ldr ip, [fp, #16]
74: e50bc034 str ip, [fp, #-52]
78: e59bc014 ldr ip, [fp, #20]
7c: e50bc038 str ip, [fp, #-56]
80: e3a0c04c mov ip, #76 ; 0x4c
84: e5cdc02c strb ip, [sp, #44]
88: e51bc020 ldr ip, [fp, #-32]
8c: e51be024 ldr lr, [fp, #-36]
90: e51b4028 ldr r4, [fp, #-40]
94: e51b502c ldr r5, [fp, #-44]
98: e51b6030 ldr r6, [fp, #-48]
9c: e51b7034 ldr r7, [fp, #-52]
a0: e51b8038 ldr r8, [fp, #-56]
a4: e1a0900d mov r9, sp
a8: e5898008 str r8, [r9, #8]
ac: e5897004 str r7, [r9, #4]
b0: e5896000 str r6, [r9]
b4: e58d0028 str r0, [sp, #40]
b8: e1a0000c mov r0, ip
bc: e58d1024 str r1, [sp, #36]
c0: e1a0100e mov r1, lr
c4: e58d2020 str r2, [sp, #32]
c8: e1a02004 mov r2, r4
cc: e58d301c str r3, [sp, #28]
d0: e1a03005 mov r3, r5
d4: ebfffffe bl 0 <leaf_call>
d8: e59d001c ldr r0, [sp, #28]
dc: e59d1020 ldr r1, [sp, #32]
e0: e59d2024 ldr r2, [sp, #36]
e4: e59d3028 ldr r3, [sp, #40]
e8: e58d0018 str r0, [sp, #24]
ec: e58d1014 str r1, [sp, #20]
f0: e58d2010 str r2, [sp, #16]
f4: e58d300c str r3, [sp, #12]
f8: e24bd018 sub sp, fp, #24 ; 0x18
fc: e8bd8bf0 pop {r4, r5, r6, r7, r8, r9, fp, pc}
00000100 <main>:
100: e92d4800 push {fp, lr}
104: e1a0b00d mov fp, sp
108: e24dd018 sub sp, sp, #24 ; 0x18
10c: e3a00000 mov r0, #0 ; 0x0
110: e50b0004 str r0, [fp, #-4]
114: e3a01007 mov r1, #7 ; 0x7
118: e1a0200d mov r2, sp
11c: e582100c str r1, [r2, #12]
120: e3a01006 mov r1, #6 ; 0x6
124: e5821008 str r1, [r2, #8]
128: e3a01005 mov r1, #5 ; 0x5
12c: e5821004 str r1, [r2, #4]
130: e3a01004 mov r1, #4 ; 0x4
134: e5821000 str r1, [r2]
138: e3a01001 mov r1, #1 ; 0x1
13c: e3a02002 mov r2, #2 ; 0x2
140: e3a03003 mov r3, #3 ; 0x3
144: e50b0008 str r0, [fp, #-8]
148: ebfffffe bl 44 <nonleaf_call>
14c: e51b0008 ldr r0, [fp, #-8]
150: e1a0d00b mov sp, fp
154: e8bd8800 pop {fp, pc}
; ---------- structs by value ---------->
;
; struct A { int i, j; long long l; };
;
; void leaf_call(int b, int c, int d, int e, struct A f, int g, int h)
; {
; }
;
; void nonleaf_call(int a, int b, int c, int d, int e, struct A f, int g, int h)
; {
; /* use some local data */
; char l[100] ={ 'L'};
; leaf_call(b, c, d, e, f, g, h);
; }
;
; int main()
; {
; nonleaf_call(0, 1, 2, 3, 4, (struct A){5, 6, 7ll}, 8, 9);
; return 0;
; }
; output from debian-6.0.8-armel w/ gcc 4.4.5
00000000 <leaf_call>:
0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
4: e28db000 add fp, sp, #0
8: e24dd014 sub sp, sp, #20
c: e50b0008 str r0, [fp, #-8]
10: e50b100c str r1, [fp, #-12]
14: e50b2010 str r2, [fp, #-16]
18: e50b3014 str r3, [fp, #-20]
1c: e28bd000 add sp, fp, #0
20: e8bd0800 pop {fp}
24: e12fff1e bx lr
00000028 <nonleaf_call>:
28: e92d4800 push {fp, lr}
2c: e28db004 add fp, sp, #4
30: e24dd090 sub sp, sp, #144 ; 0x90
34: e50b0070 str r0, [fp, #-112] ; 0x70
38: e50b1074 str r1, [fp, #-116] ; 0x74
3c: e50b2078 str r2, [fp, #-120] ; 0x78
40: e50b307c str r3, [fp, #-124] ; 0x7c
44: e24b2068 sub r2, fp, #104 ; 0x68
48: e3a03064 mov r3, #100 ; 0x64
4c: e1a00002 mov r0, r2
50: e3a01000 mov r1, #0
54: e1a02003 mov r2, r3
58: ebfffffe bl 0 <memset>
5c: e3a0304c mov r3, #76 ; 0x4c
60: e54b3068 strb r3, [fp, #-104] ; 0x68
64: e1a0c00d mov ip, sp
68: e28b300c add r3, fp, #12
6c: e893000f ldm r3, {r0, r1, r2, r3}
70: e88c000f stm ip, {r0, r1, r2, r3}
74: e59b301c ldr r3, [fp, #28]
78: e58d3010 str r3, [sp, #16]
7c: e59b3020 ldr r3, [fp, #32]
80: e58d3014 str r3, [sp, #20]
84: e51b0074 ldr r0, [fp, #-116] ; 0x74
88: e51b1078 ldr r1, [fp, #-120] ; 0x78
8c: e51b207c ldr r2, [fp, #-124] ; 0x7c
90: e59b3004 ldr r3, [fp, #4]
94: ebfffffe bl 0 <leaf_call>
98: e24bd004 sub sp, fp, #4
9c: e8bd4800 pop {fp, lr}
a0: e12fff1e bx lr
000000a4 <main>:
a4: e92d4800 push {fp, lr} ;
a8: e28db004 add fp, sp, #4 ;
ac: e24dd030 sub sp, sp, #48 ;
b0: e59f3058 ldr r3, [pc, #88] ;
b4: e24bc014 sub ip, fp, #20 ;
b8: e893000f ldm r3, {r0, r1, r2, r3} ;
bc: e88c000f stm ip, {r0, r1, r2, r3} ;
c0: e3a03004 mov r3, #4 ; arg 4, ...
c4: e58d3000 str r3, [sp] ; ... pushed onto stack
c8: e28dc008 add ip, sp, #8 ; prep arg 5, write ptr ...
cc: e24b3014 sub r3, fp, #20 ; ... read ptr (local area)
d0: e893000f ldm r3, {r0, r1, r2, r3} ; arg 5 (struct A), ...
d4: e88c000f stm ip, {r0, r1, r2, r3} ; ... pushed onto stack (as 4 words)
d8: e3a03008 mov r3, #8 ; arg 6, ...
dc: e58d3018 str r3, [sp, #24] ; ... pushed onto stack
e0: e3a03009 mov r3, #9 ; arg 6, ...
e4: e58d301c str r3, [sp, #28] ; ... pushed onto stack
e8: e3a00000 mov r0, #0 ; arg 0
ec: e3a01001 mov r1, #1 ; arg 1
f0: e3a02002 mov r2, #2 ; arg 2
f4: e3a03003 mov r3, #3 ; arg 3
f8: ebfffffe bl 28 <nonleaf_call> ;
fc: e3a03000 mov r3, #0 ;
100: e1a00003 mov r0, r3 ;
104: e24bd004 sub sp, fp, #4 ;
108: e8bd4800 pop {fp, lr} ;
10c: e12fff1e bx lr ;
110: 00000000 .word 0x00000000
; ---------- structs by value, complex example (multiple structs) ---------->
;
; struct A { int i, j; float f; };
; struct B { double d; long long l; };
;
; void leaf_call(int b, struct A c, struct B d, int e, int f, struct A g, struct B h, int i, int j)
; {
; }
;
; void nonleaf_call(int a, int b, struct A c, struct B d, int e, int f, struct A g, struct B h, int i, int j)
; {
; /* use some local data */
; char l[100] ={ 'L'};
; leaf_call(b, c, d, e, f, g, h, i, j);
; }
;
; int main()
; {
; nonleaf_call(0, 1, (struct A){2, 3, 4.f}, (struct B){5., 6ll}, 7, 8, (struct A){9, 10, 11.f}, (struct B){12., 13ll}, 14, 15);
; return 0;
; }
; output from debian-6.0.8-armel w/ gcc 4.4.5
00000000 <leaf_call>:
0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
4: e28db000 add fp, sp, #0
8: e24dd014 sub sp, sp, #20
c: e50b0008 str r0, [fp, #-8]
10: e24b0014 sub r0, fp, #20
14: e880000e stm r0, {r1, r2, r3}
18: e28bd000 add sp, fp, #0
1c: e8bd0800 pop {fp}
20: e12fff1e bx lr
00000024 <nonleaf_call>:
24: e24dd008 sub sp, sp, #8
28: e92d4800 push {fp, lr}
2c: e28db004 add fp, sp, #4
30: e24dd0b0 sub sp, sp, #176 ; 0xb0
34: e50b0070 str r0, [fp, #-112] ; 0x70
38: e50b1074 str r1, [fp, #-116] ; 0x74
3c: e28b1004 add r1, fp, #4
40: e881000c stm r1, {r2, r3}
44: e24b2068 sub r2, fp, #104 ; 0x68
48: e3a03064 mov r3, #100 ; 0x64
4c: e1a00002 mov r0, r2
50: e3a01000 mov r1, #0
54: e1a02003 mov r2, r3
58: ebfffffe bl 0 <memset>
5c: e3a0304c mov r3, #76 ; 0x4c
60: e54b3068 strb r3, [fp, #-104] ; 0x68
64: e1a0c00d mov ip, sp
68: e28b3014 add r3, fp, #20
6c: e893000f ldm r3, {r0, r1, r2, r3}
70: e88c000f stm ip, {r0, r1, r2, r3}
74: e59b3024 ldr r3, [fp, #36] ; 0x24
78: e58d3010 str r3, [sp, #16]
7c: e59b3028 ldr r3, [fp, #40] ; 0x28
80: e58d3014 str r3, [sp, #20]
84: e28dc018 add ip, sp, #24
88: e28b302c add r3, fp, #44 ; 0x2c
8c: e8930007 ldm r3, {r0, r1, r2}
90: e88c0007 stm ip, {r0, r1, r2}
94: e28dc028 add ip, sp, #40 ; 0x28
98: e28b303c add r3, fp, #60 ; 0x3c
9c: e893000f ldm r3, {r0, r1, r2, r3}
a0: e88c000f stm ip, {r0, r1, r2, r3}
a4: e59b304c ldr r3, [fp, #76] ; 0x4c
a8: e58d3038 str r3, [sp, #56] ; 0x38
ac: e59b3050 ldr r3, [fp, #80] ; 0x50
b0: e58d303c str r3, [sp, #60] ; 0x3c
b4: e51b0074 ldr r0, [fp, #-116] ; 0x74
b8: e28b3004 add r3, fp, #4
bc: e893000e ldm r3, {r1, r2, r3}
c0: ebfffffe bl 0 <leaf_call>
c4: e24bd004 sub sp, fp, #4
c8: e8bd4800 pop {fp, lr}
cc: e28dd008 add sp, sp, #8
d0: e12fff1e bx lr
000000d4 <main>:
d4: e92d4800 push {fp, lr}
d8: e28db004 add fp, sp, #4
dc: e24dd088 sub sp, sp, #136 ; 0x88
e0: e59f20b8 ldr r2, [pc, #184] ; 1a0 <main+0xcc>
e4: e24b3040 sub r3, fp, #64 ; 0x40
e8: e8920007 ldm r2, {r0, r1, r2}
ec: e8830007 stm r3, {r0, r1, r2}
f0: e59f30ac ldr r3, [pc, #172] ; 1a4 <main+0xd0>
f4: e24bc034 sub ip, fp, #52 ; 0x34
f8: e893000f ldm r3, {r0, r1, r2, r3}
fc: e88c000f stm ip, {r0, r1, r2, r3}
100: e59f20a0 ldr r2, [pc, #160] ; 1a8 <main+0xd4>
104: e24b3020 sub r3, fp, #32
108: e8920007 ldm r2, {r0, r1, r2}
10c: e8830007 stm r3, {r0, r1, r2}
110: e59f3094 ldr r3, [pc, #148] ; 1ac <main+0xd8>
114: e24bc014 sub ip, fp, #20
118: e893000f ldm r3, {r0, r1, r2, r3}
11c: e88c000f stm ip, {r0, r1, r2, r3}
120: e28dc008 add ip, sp, #8
124: e24b3034 sub r3, fp, #52 ; 0x34
128: e893000f ldm r3, {r0, r1, r2, r3}
12c: e88c000f stm ip, {r0, r1, r2, r3}
130: e3a03007 mov r3, #7
134: e58d3018 str r3, [sp, #24]
138: e3a03008 mov r3, #8
13c: e58d301c str r3, [sp, #28]
140: e28dc020 add ip, sp, #32
144: e24b3020 sub r3, fp, #32
148: e8930007 ldm r3, {r0, r1, r2}
14c: e88c0007 stm ip, {r0, r1, r2}
150: e28dc030 add ip, sp, #48 ; 0x30
154: e24b3014 sub r3, fp, #20
158: e893000f ldm r3, {r0, r1, r2, r3}
15c: e88c000f stm ip, {r0, r1, r2, r3}
160: e3a0300e mov r3, #14
164: e58d3040 str r3, [sp, #64] ; 0x40
168: e3a0300f mov r3, #15
16c: e58d3044 str r3, [sp, #68] ; 0x44
170: e51b3038 ldr r3, [fp, #-56] ; 0x38
174: e58d3000 str r3, [sp]
178: e24b3040 sub r3, fp, #64 ; 0x40
17c: e893000c ldm r3, {r2, r3}
180: e3a00000 mov r0, #0
184: e3a01001 mov r1, #1
188: ebfffffe bl 24 <nonleaf_call>
18c: e3a03000 mov r3, #0
190: e1a00003 mov r0, r3
194: e24bd004 sub sp, fp, #4
198: e8bd4800 pop {fp, lr}
19c: e12fff1e bx lr
1a0: 00000000 .word 0x00000000
1a4: 00000010 .word 0x00000010
1a8: 00000020 .word 0x00000020
1ac: 00000030 .word 0x00000030
; ---------- returning long long ---------->
;
; long long f()
; {
; return 7171LL;
; }
;
; int main()
; {
; return (int)f();
; }
; output from debian-6.0.8-armel w/ gcc 4.4.5
00000000 <f>:
0: e92d0810 push {r4, fp} ;
4: e28db004 add fp, sp, #4 ;
8: e3a03b07 mov r3, #7168 ;
c: e2833003 add r3, r3, #3 ;
10: e3a04000 mov r4, #0 ;
14: e1a00003 mov r0, r3 ; | retval in two regs
18: e1a01004 mov r1, r4 ; |
1c: e24bd004 sub sp, fp, #4 ;
20: e8bd0810 pop {r4, fp} ;
24: e12fff1e bx lr ;
00000028 <main>:
28: e92d4830 push {r4, r5, fp, lr}
2c: e28db00c add fp, sp, #12
30: ebfffffe bl 0 <f>
34: e1a03000 mov r3, r0
38: e1a04001 mov r4, r1
3c: e1a00003 mov r0, r3
40: e24bd00c sub sp, fp, #12
44: e8bd4830 pop {r4, r5, fp, lr}
48: e12fff1e bx lr
; ---------- passing structs with only fp parts ---------->
;
; struct A { float a; };
; struct B { float a, b; };
; struct C { float a, b, c; };
; struct D { double a; };
; struct E { double a, b; };
; struct F { double a, b, c; };
;
; void leaf_call(struct A a, struct B b, struct C c, struct D d, struct E e, struct F f)
; {
; }
;
; int main()
; {
; leaf_call((struct A){1.f}, (struct B){2.f,3.f}, (struct C){4.f,5.f,6.f}, (struct D){1.}, (struct E){2.,3.}, (struct F){4.,5.,6.});
; return 0;
; }
; output from debian-6.0.8-armel w/ gcc 4.4.5
00000000 <leaf_call>:
0: e24dd008 sub sp, sp, #8
4: e52db004 push {fp} ; (str fp, [sp, #-4]!)
8: e28db000 add fp, sp, #0
c: e24dd014 sub sp, sp, #20
10: e50b0008 str r0, [fp, #-8]
14: e24b0010 sub r0, fp, #16
18: e8800006 stm r0, {r1, r2}
1c: e58b3008 str r3, [fp, #8]
20: e28bd000 add sp, fp, #0
24: e8bd0800 pop {fp}
28: e28dd008 add sp, sp, #8
2c: e12fff1e bx lr
00000030 <main>:
30: e92d4810 push {r4, fp, lr} ;
34: e28db008 add fp, sp, #8 ;
38: e24dd084 sub sp, sp, #132 ;
3c: e59f30d0 ldr r3, [pc, #208] ;
40: e50b3054 str r3, [fp, #-84] ;
44: e59f20cc ldr r2, [pc, #204] ;
48: e24b3050 sub r3, fp, #80 ;
4c: e8920003 ldm r2, {r0, r1} ;
50: e8830003 stm r3, {r0, r1} ;
54: e59f20c0 ldr r2, [pc, #192] ;
58: e24b3048 sub r3, fp, #72 ;
5c: e8920007 ldm r2, {r0, r1, r2} ;
60: e8830007 stm r3, {r0, r1, r2} ;
64: e3a03000 mov r3, #0 ;
68: e3a045ff mov r4, #1069547520 ;
6c: e2844603 add r4, r4, #3145728 ;
70: e50b303c str r3, [fp, #-60] ;
74: e50b4038 str r4, [fp, #-56] ;
78: e59f30a0 ldr r3, [pc, #160] ;
7c: e24bc034 sub ip, fp, #52 ;
80: e893000f ldm r3, {r0, r1, r2, r3} ;
84: e88c000f stm ip, {r0, r1, r2, r3} ;
88: e59f3094 ldr r3, [pc, #148] ;
8c: e24bc024 sub ip, fp, #36 ;
90: e1a0e003 mov lr, r3 ;
94: e8be000f ldm lr!, {r0, r1, r2, r3} ;
98: e8ac000f stmia ip!, {r0, r1, r2, r3} ;
9c: e89e0003 ldm lr, {r0, r1} ;
a0: e88c0003 stm ip, {r0, r1} ;
a4: e24b403c sub r4, fp, #60 ;
a8: e8940018 ldm r4, {r3, r4} ;
ac: e58d3008 str r3, [sp, #8] ;
b0: e58d400c str r4, [sp, #12] ;
b4: e28dc010 add ip, sp, #16 ;
b8: e24b3034 sub r3, fp, #52 ;
bc: e893000f ldm r3, {r0, r1, r2, r3} ;
c0: e88c000f stm ip, {r0, r1, r2, r3} ;
c4: e28de020 add lr, sp, #32 ;
c8: e24bc024 sub ip, fp, #36 ;
cc: e8bc000f ldm ip!, {r0, r1, r2, r3} ;
d0: e8ae000f stmia lr!, {r0, r1, r2, r3} ;
d4: e89c0003 ldm ip, {r0, r1} ;
d8: e88e0003 stm lr, {r0, r1} ;
dc: e1a0300d mov r3, sp ; | write ptr
e0: e24b2044 sub r2, fp, #68 ; | read ptr
e4: e8920003 ldm r2, {r0, r1} ; | arg 3 (struct C), split via |
e8: e8830003 stm r3, {r0, r1} ; | | stack b & c
ec: e51b3048 ldr r3, [fp, #-72] ; | reg a
f0: e51b0054 ldr r0, [fp, #-84] ; arg 0 (struct A), via reg as word a
f4: e24b2050 sub r2, fp, #80 ; |
f8: e8920006 ldm r2, {r1, r2} ; | arg 1 (struct B), via reg as 2 words a & b
fc: ebfffffe bl 0 <leaf_call> ;
100: e3a03000 mov r3, #0 ;
104: e1a00003 mov r0, r3 ;
108: e24bd008 sub sp, fp, #8 ;
10c: e8bd4810 pop {r4, fp, lr} ;
110: e12fff1e bx lr ;
114: 3f800000 .word 0x3f800000
118: 00000000 .word 0x00000000
11c: 00000008 .word 0x00000008
120: 00000018 .word 0x00000018
124: 00000028 .word 0x00000028
; ---------- returning structs by value ---------->
;
; struct Small { char x; };
; struct Big { long long i; long j; }; /* bigger than a word */
;
; struct Small f0()
; {
; struct Small s = { 132 };
; return s;
; }
;
; struct Big f1()
; {
; struct Big b = { 7171LL, 232 };
; return b;
; }
;
; int main()
; {
; struct Small s = f0();
; struct Big b = f1();
; return b.j + s.x;
; }
; output from debian-6.0.8-armel w/ gcc 4.4.5
00000000 <f0>:
0: e52db004 push {fp} ;
4: e28db000 add fp, sp, #0 ;
8: e24dd00c sub sp, sp, #12 ;
c: e3e0307b mvn r3, #123 ;
10: e54b3008 strb r3, [fp, #-8] ;
14: e55b3008 ldrb r3, [fp, #-8] ;
18: e1a00003 mov r0, r3 ; return value (via reg as <= 4b)
1c: e28bd000 add sp, fp, #0 ;
20: e8bd0800 pop {fp} ;
24: e12fff1e bx lr ;
00000028 <f1>:
28: e92d0810 push {r4, fp} ;
2c: e28db004 add fp, sp, #4 ;
30: e24dd010 sub sp, sp, #16 ;
34: e1a0c000 mov ip, r0 ; ptr to retval space, tmp copy
38: e59f3028 ldr r3, [pc, #40] ;
3c: e24b4014 sub r4, fp, #20 ;
40: e893000f ldm r3, {r0, r1, r2, r3} ;
44: e884000f stm r4, {r0, r1, r2, r3} ;
48: e1a0400c mov r4, ip ; write ptr
4c: e24b3014 sub r3, fp, #20 ; read ptr
50: e893000f ldm r3, {r0, r1, r2, r3} ; |
54: e884000f stm r4, {r0, r1, r2, r3} ; | copy struct from local area to retval space
58: e1a0000c mov r0, ip ; return value: ptr to retval space
5c: e24bd004 sub sp, fp, #4 ;
60: e8bd0810 pop {r4, fp} ;
64: e12fff1e bx lr ;
68: 00000000 .word 0x00000000
0000006c <main>:
6c: e92d4800 push {fp, lr}
70: e28db004 add fp, sp, #4
74: e24dd018 sub sp, sp, #24
78: ebfffffe bl 0 <f0>
7c: e1a03000 mov r3, r0
80: e54b3008 strb r3, [fp, #-8]
84: e24b301c sub r3, fp, #28
88: e1a00003 mov r0, r3
8c: ebfffffe bl 28 <f1>
90: e51b2014 ldr r2, [fp, #-20]
94: e55b3008 ldrb r3, [fp, #-8]
98: e0823003 add r3, r2, r3
9c: e1a00003 mov r0, r3
a0: e24bd004 sub sp, fp, #4
a4: e8bd4800 pop {fp, lr}
a8: e12fff1e bx lr
; ---------- single-field structs by values (and small array fields) ---------->
;
; struct C { char c; };
; struct S { short s; };
; struct I { int i; };
; struct F { float f; };
; struct D { double d; };
;
; struct C2 { char c[2]; };
; struct C3 { char c[3]; };
;
; void leaf_call(struct C2 a, struct C b, struct S c, struct I d, struct F e, struct D f, struct C3 g)
; {
; }
;
; int main()
; {
; leaf_call((struct C2){{0,1}}, (struct C){2}, (struct S){3}, (struct I){4}, (struct F){5.f}, (struct D){6.}, (struct C3){{7,8,9}});
; return 0;
; }
; output from debian-6.0.8-armel w/ gcc 4.4.5
00000000 <leaf_call>:
0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
4: e28db000 add fp, sp, #0
8: e24dd014 sub sp, sp, #20
c: e14b00b8 strh r0, [fp, #-8]
10: e54b100c strb r1, [fp, #-12]
14: e14b21b0 strh r2, [fp, #-16]
18: e50b3014 str r3, [fp, #-20]
1c: e28bd000 add sp, fp, #0
20: e8bd0800 pop {fp}
24: e12fff1e bx lr
00000028 <main>:
28: e92d4810 push {r4, fp, lr} ;
2c: e28db008 add fp, sp, #8 ;
30: e24dd044 sub sp, sp, #68 ;
34: e3a03000 mov r3, #0 ;
38: e54b3030 strb r3, [fp, #-48] ;
3c: e3a03001 mov r3, #1 ;
40: e54b302f strb r3, [fp, #-47] ;
44: e3a03002 mov r3, #2 ;
48: e54b302c strb r3, [fp, #-44] ;
4c: e3a03003 mov r3, #3 ;
50: e14b32b8 strh r3, [fp, #-40] ;
54: e3a03004 mov r3, #4 ;
58: e50b3024 str r3, [fp, #-36] ;
5c: e59f308c ldr r3, [pc, #140] ;
60: e50b3020 str r3, [fp, #-32] ;
64: e3a03000 mov r3, #0 ;
68: e3a04101 mov r4, #1073741824 ;
6c: e2844706 add r4, r4, #1572864 ;
70: e50b301c str r3, [fp, #-28] ;
74: e50b4018 str r4, [fp, #-24] ;
78: e59f2074 ldr r2, [pc, #116] ;
7c: e24b3010 sub r3, fp, #16 ;
80: e5922000 ldr r2, [r2] ;
84: e1c320b0 strh r2, [r3] ;
88: e2833002 add r3, r3, #2 ;
8c: e1a02822 lsr r2, r2, #16 ;
90: e5c32000 strb r2, [r3] ;
94: e51b3020 ldr r3, [fp, #-32] ; |
98: e58d3000 str r3, [sp] ; | arg 4 (struct F), via stack as word
9c: e24b401c sub r4, fp, #28 ;
a0: e8940018 ldm r4, {r3, r4} ;
a4: e58d3008 str r3, [sp, #8] ; |
a8: e58d400c str r4, [sp, #12] ; | arg 5 (struct D), via stack as 2 words (aligned to 8, b/c double?)
ac: e28d3010 add r3, sp, #16 ;
b0: e24b2010 sub r2, fp, #16 ;
b4: e5922000 ldr r2, [r2] ; |
b8: e1c320b0 strh r2, [r3] ; |
bc: e2833002 add r3, r3, #2 ; | arg 6 (struct C3), via stack as 3 bytes in word slot
c0: e1a02822 lsr r2, r2, #16 ; |
c4: e5c32000 strb r2, [r3] ; |
c8: e51b0030 ldr r0, [fp, #-48] ; arg 0 (struct C2), via reg as word
cc: e55b102c ldrb r1, [fp, #-44] ; arg 1 (struct C), via reg as word
d0: e15b22b8 ldrh r2, [fp, #-40] ; arg 2 (struct S), via reg as word
d4: e51b3024 ldr r3, [fp, #-36] ; arg 3 (struct I), via reg as word
d8: ebfffffe bl 0 <leaf_call> ;
dc: e3a03000 mov r3, #0 ;
e0: e1a00003 mov r0, r3 ;
e4: e24bd008 sub sp, fp, #8 ;
e8: e8bd4810 pop {r4, fp, lr} ;
ec: e12fff1e bx lr ;
f0: 40a00000 .word 0x40a00000
f4: 00000000 .word 0x00000000
; ---------- C++ trivial and non-trivial aggrs passed to C funcs ---------->
;
; struct Trivial { int a; };
; struct NonTrivial { int a; NonTrivial() : a(0) {} NonTrivial(const NonTrivial& rhs) : a(rhs.a) { } };
;
; extern "C" {
;
; void f1(struct Trivial s) { }
; void f2(struct NonTrivial s) { }
;
; void f()
; {
; struct Trivial t;
; struct NonTrivial n;
; int a=1;
; a += 123;
; f1(t);
; a -= 123;
; f2(n);
; a -= 12;
; }
; }
; output from debian-6.0.8-armel w/ gcc 4.4.5
00000000 <f1>:
0: e52db004 push {fp}
4: e28db000 add fp, sp, #0
8: e24dd00c sub sp, sp, #12
c: e50b0008 str r0, [fp, #-8]
10: e28bd000 add sp, fp, #0
14: e8bd0800 pop {fp}
18: e12fff1e bx lr
0000001c <f2>:
1c: e52db004 push {fp}
20: e28db000 add fp, sp, #0
24: e24dd00c sub sp, sp, #12
28: e50b0008 str r0, [fp, #-8]
2c: e28bd000 add sp, fp, #0
30: e8bd0800 pop {fp}
34: e12fff1e bx lr
00000038 <f>:
38: e92d4800 push {fp, lr} ; |
3c: e28db004 add fp, sp, #4 ; | prolog
40: e24dd010 sub sp, sp, #16 ; /
44: e24b3014 sub r3, fp, #20 ; \
48: e1a00003 mov r0, r3 ; | this ptr (ptr to n's (NonTrivial) space)
4c: ebfffffe bl 0 <_ZN10NonTrivialC1Ev> ; | NonTrivial::NonTrivial() / ctor
50: e3a03001 mov r3, #1 ; a = 1
54: e50b3008 str r3, [fp, #-8] ; |
58: e51b3008 ldr r3, [fp, #-8] ; | a += 123
5c: e283307b add r3, r3, #123 ; |
60: e50b3008 str r3, [fp, #-8] ; |
64: e51b0010 ldr r0, [fp, #-16] ; f1 arg 0 (struct Trivial), via reg as small struct
68: ebfffffe bl 0 <f1> ; call f1(struct Trivial)
6c: e51b3008 ldr r3, [fp, #-8] ; |
70: e243307b sub r3, r3, #123 ; | a -= 123
74: e50b3008 str r3, [fp, #-8] ; /
78: e24b200c sub r2, fp, #12 ; \
7c: e24b3014 sub r3, fp, #20 ; |
80: e1a00002 mov r0, r2 ; | ptr to dest of copy of n
84: e1a01003 mov r1, r3 ; | copy n ptr to n
88: ebfffffe bl 0 <_ZN10NonTrivialC1ERKS_> ; / NonTrivial::NonTrivial(const NonTrivial&) / copy ctor
8c: e24b300c sub r3, fp, #12 ; \
90: e1a00003 mov r0, r3 ; | f2 arg 0 (ptr to copy of struct NonTrivial), via ptr as non-trivial
94: ebfffffe bl 1c <f2> ; call f2(struct NonTrivial)
98: e51b3008 ldr r3, [fp, #-8] ; |
9c: e243300c sub r3, r3, #12 ; | a -= 12
a0: e50b3008 str r3, [fp, #-8] ; /
a4: e24bd004 sub sp, fp, #4 ; \
a8: e8bd4800 pop {fp, lr} ; | epilog
ac: e12fff1e bx lr ; |
; ... snip, removed code of ctor and copy ctor ...
; ---------- C++ trivial and non-trivial aggrs as return values ---------->
;
; struct Trivial { int a; };
; struct NonTrivial { int a; NonTrivial() : a(0) {} NonTrivial(const NonTrivial& rhs) : a(rhs.a) { } };
;
; extern "C" {
; struct Trivial f1() { return Trivial(); }
; }
;
; struct NonTrivial f2() { return NonTrivial(); }
;
; extern "C" {
; void f()
; {
; int a=1;
; a += 123;
; struct Trivial t = f1();
; a -= 123;
; struct NonTrivial n = f2();
; a -= 12;
; }
; }
; output from debian-6.0.8-armel w/ gcc 4.4.5
00000000 <f1>:
0: e52db004 push {fp}
4: e28db000 add fp, sp, #0
8: e3a03000 mov r3, #0
c: e1a00003 mov r0, r3
10: e28bd000 add sp, fp, #0
14: e8bd0800 pop {fp}
18: e12fff1e bx lr
0000001c <_Z2f2v>:
1c: e92d4830 push {r4, r5, fp, lr}
20: e28db00c add fp, sp, #12
24: e1a04000 mov r4, r0
28: e1a03004 mov r3, r4
2c: e1a00003 mov r0, r3
30: ebfffffe bl 0 ; ctor
34: e1a00004 mov r0, r4 ; ptr to retval space -> r0
38: e1a00004 mov r0, r4
3c: e24bd00c sub sp, fp, #12
40: e8bd4830 pop {r4, r5, fp, lr}
44: e12fff1e bx lr
00000048 <f>:
48: e92d4800 push {fp, lr} ;
4c: e28db004 add fp, sp, #4 ;
50: e24dd010 sub sp, sp, #16 ;
54: e3a03001 mov r3, #1 ;
58: e50b3008 str r3, [fp, #-8] ;
5c: e51b3008 ldr r3, [fp, #-8] ;
60: e283307b add r3, r3, #123 ;
64: e50b3008 str r3, [fp, #-8] ;
68: ebfffffe bl 0 <f1> ; call f1()
6c: e1a03000 mov r3, r0 ; retval via r0, as small struct
70: e50b300c str r3, [fp, #-12] ;
74: e51b3008 ldr r3, [fp, #-8] ;
78: e243307b sub r3, r3, #123 ;
7c: e50b3008 str r3, [fp, #-8] ;
80: e24b3010 sub r3, fp, #16 ; space to hold non-triv retval -> eax ...
84: e1a00003 mov r0, r3 ; ... as hidden first arg (r0)
88: ebfffffe bl 1c <_Z2f2v> ; call f2()
8c: e51b3008 ldr r3, [fp, #-8] ;
90: e243300c sub r3, r3, #12 ;
94: e50b3008 str r3, [fp, #-8] ;
98: e24bd004 sub sp, fp, #4 ;
9c: e8bd4800 pop {fp, lr} ;
a0: e12fff1e bx lr ;
; vim: ft=asm68k