Mercurial > pub > dyncall > dyncall
view doc/disas_examples/arm.armhf.disas @ 619:c754150fe87f
- x64 win disas example fix and addition
author | Tassilo Philipp |
---|---|
date | Mon, 03 Oct 2022 13:49:19 +0200 |
parents | fc614cb865c6 |
children |
line wrap: on
line source
; #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 raspbian-wheezy_20120715-raspberrypi w/ gcc 4.6.3 ; note: this is arm mode, -mthumb says "sorry, unimplemented: Thumb-1 hard-float VFP ABI" (however, -msoft-float -mthumb is supported) ; not sure about thumb-2 as there is no flag for it, but I don't think this exists if using the VFP 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>: ;spill here, if needed: push {r0, r1, r2, r3} ; | just for ref, if present this would change below offsets 28: e92d4800 push {fp, lr} ; | 2c: e28db004 add fp, sp, #4 ; | prolog 30: e24dd020 sub sp, sp, #32 ; | 34: e50b0008 str r0, [fp, #-8] ; in arg 0 -> temp space in local area 38: e50b100c str r1, [fp, #-12] ; in arg 1 -> temp space in local area 3c: e50b2010 str r2, [fp, #-16] ; in arg 2 -> temp space in local area 40: e50b3014 str r3, [fp, #-20] ; in arg 3 -> temp space in local area 44: e24dd0e8 sub sp, sp, #232 ; alloca(220) - with padding to guarantee alignment 48: e28d3010 add r3, sp, #16 ; | 4c: e2833007 add r3, r3, #7 ; | 50: e1a031a3 lsr r3, r3, #3 ; | start of (aligned) alloca()'d memory -> r3, leaving room at top of stack for param area 54: e1a03183 lsl r3, r3, #3 ; | 58: e3a0204c mov r2, #76 ; 'L' -> r2, and ... 5c: e5c32000 strb r2, [r3] ; ... store in local area (of alloca()'d space) 60: e59b3008 ldr r3, [fp, #8] ; arg 4 (fetched from prev frame's param area), and ... 64: e58d3000 str r3, [sp] ; ... "pushed" onto stack 68: e59b300c ldr r3, [fp, #12] ; arg 5 (fetched from prev frame's param area), and ... 6c: e58d3004 str r3, [sp, #4] ; ... "pushed" onto stack 70: e59b3010 ldr r3, [fp, #16] ; arg 6 (fetched from prev frame's param area), and ... 74: e58d3008 str r3, [sp, #8] ; ... "pushed" onto stack 78: e51b000c ldr r0, [fp, #-12] ; arg 0 7c: e51b1010 ldr r1, [fp, #-16] ; arg 1 80: e51b2014 ldr r2, [fp, #-20] ; arg 2 84: e59b3004 ldr r3, [fp, #4] ; arg 3 (fetched from prev frame's param area) 88: ebfffffe bl 0 <leaf_call> ; return address -> r14/lr, and call 8c: e24bd004 sub sp, fp, #4 ; | 90: e8bd8800 pop {fp, pc} ; | epilog 00000094 <main>: 94: e92d4800 push {fp, lr} ; | 98: e28db004 add fp, sp, #4 ; | prolog 9c: e24dd010 sub sp, sp, #16 ; | a0: e3a03004 mov r3, #4 ; arg 4, and ... a4: e58d3000 str r3, [sp] ; ... "pushed" onto stack a8: e3a03005 mov r3, #5 ; arg 5, and ... ac: e58d3004 str r3, [sp, #4] ; ... "pushed" onto stack b0: e3a03006 mov r3, #6 ; arg 6, and ... b4: e58d3008 str r3, [sp, #8] ; ... "pushed" onto stack b8: e3a03007 mov r3, #7 ; arg 7, and ... bc: e58d300c str r3, [sp, #12] ; ... "pushed" onto stack c0: e3a00000 mov r0, #0 ; arg 0 c4: e3a01001 mov r1, #1 ; arg 1 c8: e3a02002 mov r2, #2 ; arg 2 cc: e3a03003 mov r3, #3 ; arg 3 d0: ebfffffe bl 28 <nonleaf_call> ; return address -> r14/lr, and call d4: e3a03000 mov r3, #0 ; return value (0) via r3 ... (a bit unoptimal) d8: e1a00003 mov r0, r3 ; ... to r0 dc: e24bd004 sub sp, fp, #4 ; | e0: e8bd8800 pop {fp, pc} ; | epilog ; ---------- 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 raspbian-11-armelhf w/ gcc 10.2.1 00000000 <leaf_call>: 0: e52db004 push {fp} 4: e28db000 add fp, sp, #0 8: e24dd034 sub sp, sp, #52 c: ed0b0a02 vstr s0, [fp, #-8] 10: ed0b3b09 vstr d3, [fp, #-36] 14: eeb06b44 vmov.f64 d6, d4 18: eeb07b45 vmov.f64 d7, d5 1c: ed4b0a04 vstr s1, [fp, #-16] 20: ed0b1a03 vstr s2, [fp, #-12] 24: ed4b1a07 vstr s3, [fp, #-28] 28: ed0b2a06 vstr s4, [fp, #-24] 2c: ed4b2a05 vstr s5, [fp, #-20] 30: ed0b6b0d vstr d6, [fp, #-52] 34: ed0b7b0b vstr d7, [fp, #-44] 38: e1a00000 nop 3c: e28bd000 add sp, fp, #0 40: e49db004 pop {fp} 44: e12fff1e bx lr 00000048 <main>: 48: e92d4800 push {fp, lr} ; 4c: e28db004 add fp, sp, #4 ; 50: e24dd058 sub sp, sp, #88 ; 54: ed9f0a29 vldr s0, [pc, #164] ; arg 0 (struct A), fetch from data below: (pc:=0x54+0x8)+164=0x100 58: e59f20a4 ldr r2, [pc, #164] ; 5c: e24b300c sub r3, fp, #12 ; 60: e8920003 ldm r2, {r0, r1} ; 64: e8830003 stm r3, {r0, r1} ; 68: e59f2098 ldr r2, [pc, #152] ; 6c: e24b3018 sub r3, fp, #24 ; 70: e8920007 ldm r2, {r0, r1, r2} ; 74: e8830007 stm r3, {r0, r1, r2} ; 78: ed9f3b1e vldr d3, [pc, #120] ; arg 3 (struct D), via fregs, fetch from data below: (pc:=0x78+0x8)+120=0xf8 7c: e59f3088 ldr r3, [pc, #136] ; 80: e24bc02c sub ip, fp, #44 ; 84: e893000f ldm r3, {r0, r1, r2, r3} ; 88: e88c000f stm ip, {r0, r1, r2, r3} ; 8c: e59f307c ldr r3, [pc, #124] ; 90: e24bc044 sub ip, fp, #68 ; 94: e1a0e003 mov lr, r3 ; 98: e8be000f ldm lr!, {r0, r1, r2, r3} ; 9c: e8ac000f stmia ip!, {r0, r1, r2, r3} ; a0: e89e0003 ldm lr, {r0, r1} ; a4: e88c0003 stm ip, {r0, r1} ; a8: ed1b6b0b vldr d6, [fp, #-44] ; \ prep arg 5 (struct E) ac: ed1b7b09 vldr d7, [fp, #-36] ; / b b0: ed5b1a06 vldr s3, [fp, #-24] ; \ a b4: ed1b2a05 vldr s4, [fp, #-20] ; | arg 2 (struct C), via fregs b b8: ed5b2a04 vldr s5, [fp, #-16] ; / c bc: ed5b0a03 vldr s1, [fp, #-12] ; \ a c0: ed1b1a02 vldr s2, [fp, #-8] ; / arg 1 (struct B), via fregs b c4: e1a0e00d mov lr, sp ; \ write ptr (to stack top) c8: e24bc044 sub ip, fp, #68 ; | read ptr cc: e8bc000f ldm ip!, {r0, r1, r2, r3} ; | arg 6 (struct F), entirely via stack (not split) d0: e8ae000f stmia lr!, {r0, r1, r2, r3} ; | d4: e89c0003 ldm ip, {r0, r1} ; | d8: e88e0003 stm lr, {r0, r1} ; / dc: eeb04b46 vmov.f64 d4, d6 ; \ arg 5 (struct E), via fregs a e0: eeb05b47 vmov.f64 d5, d7 ; / b e4: ebfffffe bl 0 <leaf_call> ; return address -> r14/lr, and call e8: e3a03000 mov r3, #0 ; return value (0) via r3 ... (a bit unoptimal) ec: e1a00003 mov r0, r3 ; ... to r0 f0: e24bd004 sub sp, fp, #4 ; | epilog f4: e8bd8800 pop {fp, pc} ; / f8: 00000000 .word 0x00000000 ; \ | fc: 3ff00000 .word 0x3ff00000 ; | | 1.0 100: 3f800000 .word 0x3f800000 ; | 1.f 104: 00000000 .word 0x00000000 ; | data 108: 00000008 .word 0x00000008 ; | 10c: 00000018 .word 0x00000018 ; | 110: 00000028 .word 0x00000028 ; | ; ---------- passing structs with mixed fp/int parts ----------> ; ; struct A { float a; char b; }; ; struct B { int a; double b; }; ; struct C { double a, b; int c; }; ; struct D { double a, b, c; long long d; }; ; ; void leaf_call(struct A a, struct B b, struct C c, struct D d) ; { ; } ; ; int main() ; { ; leaf_call((struct A){1.f,2}, (struct B){2,3.}, (struct C){4.,5.,6}, (struct D){7.,8.,9.,10}); ; return 0; ; } ; output from raspbian-11-armelhf w/ gcc 10.2.1 00000000 <leaf_call>: 0: e24dd008 sub sp, sp, #8 ; 4: e52db004 push {fp} ; 8: e28db000 add fp, sp, #0 ; c: e24dd00c sub sp, sp, #12 ; 10: e24bc00c sub ip, fp, #12 ; 14: e88c0003 stm ip, {r0, r1} ; 18: e28b1004 add r1, fp, #4 ; 1c: e881000c stm r1, {r2, r3} ; 20: e1a00000 nop ; 24: e28bd000 add sp, fp, #0 ; 28: e49db004 pop {fp} ; 2c: e28dd008 add sp, sp, #8 ; 30: e12fff1e bx lr ; 00000034 <main>: 34: e92d4800 push {fp, lr} ; | 38: e28db004 add fp, sp, #4 ; | prolog 3c: e24dd090 sub sp, sp, #144 ; / 40: e59f20b4 ldr r2, [pc, #180] ; \ read ptr to data after func 44: e24b300c sub r3, fp, #12 ; | write ptr to local area 48: e8920003 ldm r2, {r0, r1} ; | struct A -> local area 4c: e8830003 stm r3, {r0, r1} ; / 50: e59f30a8 ldr r3, [pc, #168] ; \ read ptr to data after func 54: e24bc01c sub ip, fp, #28 ; | write ptr 58: e893000f ldm r3, {r0, r1, r2, r3} ; | struct B -> local area 5c: e88c000f stm ip, {r0, r1, r2, r3} ; / 60: e59f309c ldr r3, [pc, #156] ; \ read ptr to data after func 64: e24bc034 sub ip, fp, #52 ; | write ptr 68: e1a0e003 mov lr, r3 ; | 6c: e8be000f ldm lr!, {r0, r1, r2, r3} ; | struct C -> local area 70: e8ac000f stmia ip!, {r0, r1, r2, r3} ; | 74: e89e0003 ldm lr, {r0, r1} ; | 78: e88c0003 stm ip, {r0, r1} ; / 7c: e59f3084 ldr r3, [pc, #132] ; \ read ptr to data after func 80: e24bc054 sub ip, fp, #84 ; | write ptr 84: e1a0e003 mov lr, r3 ; | 88: e8be000f ldm lr!, {r0, r1, r2, r3} ; | 8c: e8ac000f stmia ip!, {r0, r1, r2, r3} ; | 90: e89e000f ldm lr, {r0, r1, r2, r3} ; | 94: e88c000f stm ip, {r0, r1, r2, r3} ; | struct D -> local area 98: e28de020 add lr, sp, #32 ; | 9c: e24bc054 sub ip, fp, #84 ; | a0: e8bc000f ldm ip!, {r0, r1, r2, r3} ; | a4: e8ae000f stmia lr!, {r0, r1, r2, r3} ; | a8: e89c000f ldm ip, {r0, r1, r2, r3} ; | ac: e88e000f stm lr, {r0, r1, r2, r3} ; / b0: e28de008 add lr, sp, #8 ; \ b4: e24bc034 sub ip, fp, #52 ; | b8: e8bc000f ldm ip!, {r0, r1, r2, r3} ; | bc: e8ae000f stmia lr!, {r0, r1, r2, r3} ; | arg 2 (struct C) c0: e89c0003 ldm ip, {r0, r1} ; | c4: e88e0003 stm lr, {r0, r1} ; / c8: e1a0200d mov r2, sp ; \ | cc: e24b3014 sub r3, fp, #20 ; | | via stack (second half) d0: e8930003 ldm r3, {r0, r1} ; | | d4: e8820003 stm r2, {r0, r1} ; | arg 1 (struct B), split via regs and stack as 2 words each d8: e24b301c sub r3, fp, #28 ; | dc: e893000c ldm r3, {r2, r3} ; / via regs (first half) e0: e24b100c sub r1, fp, #12 ; \ e4: e8910003 ldm r1, {r0, r1} ; | arg 0 (struct A), via regs as 2 words e8: ebfffffe bl 0 <leaf_call> ; return address -> r14/lr, and call ec: e3a03000 mov r3, #0 ; return value (0) via r3 ... (a bit unoptimal) f0: e1a00003 mov r0, r3 ; ... to r0 f4: e24bd004 sub sp, fp, #4 ; | f8: e8bd8800 pop {fp, pc} ; | epilog fc: 00000000 .word 0x00000000 ; 0 100: 00000008 .word 0x00000008 ; 8 104: 00000018 .word 0x00000018 ; 24 108: 00000030 .word 0x00000030 ; 48 ; ---------- passing 3-field fp-only struct (HVA) which is bigger than 16b ----------> ; ; struct A { double a, b, c; }; /* bigger than 16b */ ; ; void leaf_call(struct A a) ; { ; } ; ; int main() ; { ; leaf_call((struct A){1.,2.,3.}); ; return 0; ; } ; output from raspbian-11-armelhf w/ gcc 10.2.1 00000000 <leaf_call>: 0: e52db004 push {fp} ; 4: e28db000 add fp, sp, #0 ; 8: e24dd01c sub sp, sp, #28 ; c: eeb05b40 vmov.f64 d5, d0 ; 10: eeb06b41 vmov.f64 d6, d1 ; 14: eeb07b42 vmov.f64 d7, d2 ; 18: ed0b5b07 vstr d5, [fp, #-28] ; 1c: ed0b6b05 vstr d6, [fp, #-20] ; 20: ed0b7b03 vstr d7, [fp, #-12] ; 24: e1a00000 nop ; 28: e28bd000 add sp, fp, #0 ; 2c: e49db004 pop {fp} ; 30: e12fff1e bx lr ; 00000034 <main>: 34: e92d4800 push {fp, lr} ; 38: e28db004 add fp, sp, #4 ; 3c: e24dd018 sub sp, sp, #24 ; 40: e59f3040 ldr r3, [pc, #64] ; 44: e24bc01c sub ip, fp, #28 ; 48: e1a0e003 mov lr, r3 ; 4c: e8be000f ldm lr!, {r0, r1, r2, r3} ; 50: e8ac000f stmia ip!, {r0, r1, r2, r3} ; 54: e89e0003 ldm lr, {r0, r1} ; 58: e88c0003 stm ip, {r0, r1} ; 5c: ed1b5b07 vldr d5, [fp, #-28] ; 60: ed1b6b05 vldr d6, [fp, #-20] ; 64: ed1b7b03 vldr d7, [fp, #-12] ; 68: eeb00b45 vmov.f64 d0, d5 ; | 6c: eeb01b46 vmov.f64 d1, d6 ; | arg 0, via fpregs 70: eeb02b47 vmov.f64 d2, d7 ; | 74: ebfffffe bl 0 <leaf_call> ; 78: e3a03000 mov r3, #0 ; 7c: e1a00003 mov r0, r3 ; 80: e24bd004 sub sp, fp, #4 ; 84: e8bd8800 pop {fp, pc} ; 88: 00000000 .word 0x00000000 ; ; ---------- passing 5-field fp-only struct (HVA) ----------> ; ; struct A { double a, b, c, d, e; }; ; ; void leaf_call(struct A a) ; { ; } ; ; int main() ; { ; leaf_call((struct A){1.,2.,3.,4.,5.}); ; return 0; ; } ; output from raspbian-11-armelhf w/ gcc 10.2.1 00000000 <leaf_call>: 0: e24dd010 sub sp, sp, #16 4: e52db004 push {fp} 8: e28db000 add fp, sp, #0 c: e28bc004 add ip, fp, #4 10: e88c000f stm ip, {r0, r1, r2, r3} 14: e1a00000 nop 18: e28bd000 add sp, fp, #0 1c: e49db004 pop {fp} 20: e28dd010 add sp, sp, #16 24: e12fff1e bx lr 00000028 <main>: 28: e92d4800 push {fp, lr} ; 2c: e28db004 add fp, sp, #4 ; 30: e24dd040 sub sp, sp, #64 ; 34: e59f3050 ldr r3, [pc, #80] ; 38: e24bc02c sub ip, fp, #44 ; 3c: e1a0e003 mov lr, r3 ; 40: e8be000f ldm lr!, {r0, r1, r2, r3} ; 44: e8ac000f stmia ip!, {r0, r1, r2, r3} ; 48: e8be000f ldm lr!, {r0, r1, r2, r3} ; 4c: e8ac000f stmia ip!, {r0, r1, r2, r3} ; 50: e89e0003 ldm lr, {r0, r1} ; 54: e88c0003 stm ip, {r0, r1} ; 58: e1a0e00d mov lr, sp ; 5c: e24bc01c sub ip, fp, #28 ; 60: e8bc000f ldm ip!, {r0, r1, r2, r3} ; 64: e8ae000f stmia lr!, {r0, r1, r2, r3} ; 68: e89c0003 ldm ip, {r0, r1} ; 6c: e88e0003 stm lr, {r0, r1} ; 70: e24b302c sub r3, fp, #44 ; 74: e893000f ldm r3, {r0, r1, r2, r3} ; arg 0's a and b passed in int regs, as more than 4 fields, and splitting is allowed 78: ebfffffe bl 0 <leaf_call> ; 7c: e3a03000 mov r3, #0 ; 80: e1a00003 mov r0, r3 ; 84: e24bd004 sub sp, fp, #4 ; 88: e8bd8800 pop {fp, pc} ; 8c: 00000000 .word 0x00000000 ; ; ---------- returning struct with 4 only-fp fields (HVA) by value ----------> ; ; struct A { double a, b, c, d; }; ; ; struct A leaf_call() ; { ; return (struct A){1.,2.,3.,4.}; ; } ; ; int main() ; { ; leaf_call(); ; return 0; ; } ; output from raspbian-11-armelhf w/ gcc 10.2.1 00000000 <leaf_call>: 0: e92d48f0 push {r4, r5, r6, r7, fp, lr} ; 4: e28db014 add fp, sp, #20 ; 8: e24dd060 sub sp, sp, #96 ; c: e59f304c ldr r3, [pc, #76] ; 10: e24bc034 sub ip, fp, #52 ; 14: e1a0e003 mov lr, r3 ; 18: e8be000f ldm lr!, {r0, r1, r2, r3} ; 1c: e8ac000f stmia ip!, {r0, r1, r2, r3} ; 20: e89e000f ldm lr, {r0, r1, r2, r3} ; 24: e88c000f stm ip, {r0, r1, r2, r3} ; 28: e14b63d4 ldrd r6, [fp, #-52] ; 2c: e14b42dc ldrd r4, [fp, #-44] ; 30: e14b02d4 ldrd r0, [fp, #-36] ; 34: e14b21dc ldrd r2, [fp, #-28] ; 38: ec476b14 vmov d4, r6, r7 ; 3c: ec454b15 vmov d5, r4, r5 ; 40: ec410b16 vmov d6, r0, r1 ; 44: ec432b17 vmov d7, r2, r3 ; 48: eeb00b44 vmov.f64 d0, d4 ; | 4c: eeb01b45 vmov.f64 d1, d5 ; | 50: eeb02b46 vmov.f64 d2, d6 ; | return value via regs 54: eeb03b47 vmov.f64 d3, d7 ; | 58: e24bd014 sub sp, fp, #20 ; 5c: e8bd88f0 pop {r4, r5, r6, r7, fp, pc} ; 60: 00000000 .word 0x00000000 ; 00000064 <main>: 64: e92d4800 push {fp, lr} 68: e28db004 add fp, sp, #4 6c: ebfffffe bl 0 <leaf_call> 70: e3a03000 mov r3, #0 74: e1a00003 mov r0, r3 78: e8bd8800 pop {fp, pc} ; ---------- returning struct with 5 only-fp fields (HVA) by value, not returned via regs ----------> ; ; struct A { double a, b, c, d, e; }; ; ; struct A leaf_call() ; { ; return (struct A){1.,2.,3.,4.,5.}; ; } ; ; int main() ; { ; leaf_call(); ; return 0; ; } ; output from raspbian-11-armelhf w/ gcc 10.2.1 00000000 <leaf_call>: 0: e92d4800 push {fp, lr} ; 4: e28db004 add fp, sp, #4 ; 8: e24dd030 sub sp, sp, #48 ; c: e50b0030 str r0, [fp, #-48] ; 10: e51b3030 ldr r3, [fp, #-48] ; 14: e59f2028 ldr r2, [pc, #40] ; 18: e1a0c003 mov ip, r3 ; 1c: e1a0e002 mov lr, r2 ; 20: e8be000f ldm lr!, {r0, r1, r2, r3} ; 24: e8ac000f stmia ip!, {r0, r1, r2, r3} ; 28: e8be000f ldm lr!, {r0, r1, r2, r3} ; 2c: e8ac000f stmia ip!, {r0, r1, r2, r3} ; 30: e89e0003 ldm lr, {r0, r1} ; 34: e88c0003 stm ip, {r0, r1} ; 38: e51b0030 ldr r0, [fp, #-48] ; hidden arg ptr returned in r0 3c: e24bd004 sub sp, fp, #4 ; 40: e8bd8800 pop {fp, pc} ; 44: 00000000 .word 0x00000000 ; 00000048 <main>: 48: e92d4800 push {fp, lr} ; 4c: e28db004 add fp, sp, #4 ; 50: e24dd028 sub sp, sp, #40 ; 54: e24b302c sub r3, fp, #44 ; 58: e1a00003 mov r0, r3 ; hidden first arg, ptr to retval struct data 5c: ebfffffe bl 0 <leaf_call> ; 60: e3a03000 mov r3, #0 ; 64: e1a00003 mov r0, r3 ; 68: e24bd004 sub sp, fp, #4 ; 6c: e8bd8800 pop {fp, pc} ; ; ---------- returning struct of 4b via reg ----------> ; ; ; struct A { short a, b; }; ; ; struct A leaf_call() ; { ; return (struct A){1,2}; ; } ; ; int main() ; { ; leaf_call(); ; return 0; ; } ; output from raspbian-11-armelhf w/ gcc 10.2.1 00000000 <leaf_call>: 0: e52db004 push {fp} 4: e28db000 add fp, sp, #0 8: e24dd00c sub sp, sp, #12 c: e59f3040 ldr r3, [pc, #64] 10: e5933000 ldr r3, [r3] 14: e50b3008 str r3, [fp, #-8] 18: e3a03000 mov r3, #0 1c: e15b20b8 ldrh r2, [fp, #-8] 20: e1a02802 lsl r2, r2, #16 24: e1a03823 lsr r3, r3, #16 28: e1833002 orr r3, r3, r2 2c: e1a03863 ror r3, r3, #16 30: e15b20b6 ldrh r2, [fp, #-6] 34: e1a02802 lsl r2, r2, #16 38: e1a03803 lsl r3, r3, #16 3c: e1a03823 lsr r3, r3, #16 40: e1833002 orr r3, r3, r2 44: e1a00003 mov r0, r3 48: e28bd000 add sp, fp, #0 4c: e49db004 pop {fp} 50: e12fff1e bx lr 54: 00000000 .word 0x00000000 00000058 <main>: 58: e92d4800 push {fp, lr} 5c: e28db004 add fp, sp, #4 60: ebfffffe bl 0 <leaf_call> 64: e3a03000 mov r3, #0 68: e1a00003 mov r0, r3 6c: e8bd8800 pop {fp, pc} ; ---------- returning struct of > 4b indirectly via hidden pointer arg ----------> ; ; struct A { short a, b, c; }; ; ; struct A leaf_call() ; { ; return (struct A){1,2,3}; ; } ; ; int main() ; { ; leaf_call(); ; return 0; ; } ; output from raspbian-11-armelhf w/ gcc 10.2.1 00000000 <leaf_call>: 0: e52db004 push {fp} 4: e28db000 add fp, sp, #0 8: e24dd014 sub sp, sp, #20 c: e50b0010 str r0, [fp, #-16] 10: e51b3010 ldr r3, [fp, #-16] 14: e59f201c ldr r2, [pc, #28] 18: e5920000 ldr r0, [r2] 1c: e5830000 str r0, [r3] 20: e1d220b4 ldrh r2, [r2, #4] 24: e1c320b4 strh r2, [r3, #4] 28: e51b0010 ldr r0, [fp, #-16] 2c: e28bd000 add sp, fp, #0 30: e49db004 pop {fp} 34: e12fff1e bx lr 38: 00000000 .word 0x00000000 0000003c <main>: 3c: e92d4800 push {fp, lr} 40: e28db004 add fp, sp, #4 44: e24dd008 sub sp, sp, #8 48: e24b300c sub r3, fp, #12 4c: e1a00003 mov r0, r3 50: ebfffffe bl 0 <leaf_call> 54: e3a03000 mov r3, #0 58: e1a00003 mov r0, r3 5c: e24bd004 sub sp, fp, #4 60: e8bd8800 pop {fp, pc} ; ---------- 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 raspbian-11-armelhf w/ gcc 10.2.1 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: e1a00000 nop 14: e28bd000 add sp, fp, #0 18: e49db004 pop {fp} 1c: e12fff1e bx lr 00000020 <f2>: 20: e52db004 push {fp} 24: e28db000 add fp, sp, #0 28: e24dd00c sub sp, sp, #12 2c: e50b0008 str r0, [fp, #-8] 30: e1a00000 nop 34: e28bd000 add sp, fp, #0 38: e49db004 pop {fp} 3c: e12fff1e bx lr 00000040 <f>: 40: e92d4800 push {fp, lr} ; | 44: e28db004 add fp, sp, #4 ; | prolog 48: e24dd010 sub sp, sp, #16 ; / 4c: e24b3014 sub r3, fp, #20 ; \ 50: e1a00003 mov r0, r3 ; | this ptr (ptr to n's (NonTrivial) space) 54: ebfffffe bl 0 <_ZN10NonTrivialC1Ev> ; | NonTrivial::NonTrivial() / ctor 58: e3a03001 mov r3, #1 ; a = 1 5c: e50b3008 str r3, [fp, #-8] ; | 60: e51b3008 ldr r3, [fp, #-8] ; | a += 123 64: e283307b add r3, r3, #123 ; | 68: e50b3008 str r3, [fp, #-8] ; | 6c: e51b0010 ldr r0, [fp, #-16] ; f1 arg 0 (struct Trivial), via reg as small struct 70: ebfffffe bl 0 <f1> ; call f1(struct Trivial) 74: e51b3008 ldr r3, [fp, #-8] ; | 78: e243307b sub r3, r3, #123 ; | a -= 123 7c: e50b3008 str r3, [fp, #-8] ; / 80: e24b2014 sub r2, fp, #20 ; \ 84: e24b300c sub r3, fp, #12 ; | 88: e1a01002 mov r1, r2 ; | ptr to n 8c: e1a00003 mov r0, r3 ; | copy n ptr to dest of copy of n 90: ebfffffe bl 0 <_ZN10NonTrivialC1ERKS_> ; / NonTrivial::NonTrivial(const NonTrivial&) / copy ctor 94: e24b300c sub r3, fp, #12 ; \ 98: e1a00003 mov r0, r3 ; | f2 arg 0 (ptr to copy of struct NonTrivial), via ptr as non-trivial 9c: ebfffffe bl 20 <f2> ; call f2(struct NonTrivial) a0: e51b3008 ldr r3, [fp, #-8] ; | a4: e243300c sub r3, r3, #12 ; | a -= 12 a8: e50b3008 str r3, [fp, #-8] ; / ac: e1a00000 nop ; \ b0: e24bd004 sub sp, fp, #4 ; | epilog b4: e8bd8800 pop {fp, pc} ; | ; ... 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 raspbian-11-armelhf w/ gcc 10.2.1 000103d0 <f1>: 103d0: e52db004 push {fp} 103d4: e28db000 add fp, sp, #0 103d8: e3a03000 mov r3, #0 103dc: e1a00003 mov r0, r3 103e0: e28bd000 add sp, fp, #0 103e4: e49db004 pop {fp} 103e8: e12fff1e bx lr 000103ec <_Z2f2v>: 103ec: e92d4800 push {fp, lr} 103f0: e28db004 add fp, sp, #4 103f4: e24dd008 sub sp, sp, #8 103f8: e50b0008 str r0, [fp, #-8] 103fc: e51b0008 ldr r0, [fp, #-8] 10400: eb00001f bl 10484 <_ZN10NonTrivialC1Ev> 10404: e51b0008 ldr r0, [fp, #-8] ; ptr to retval space -> r0 10408: e24bd004 sub sp, fp, #4 1040c: e8bd8800 pop {fp, pc} 00010410 <f>: 10410: e92d4800 push {fp, lr} ; | 10414: e28db004 add fp, sp, #4 ; | prolog 10418: e24dd010 sub sp, sp, #16 ; / 1041c: e3a03001 mov r3, #1 ; \ a = 1 10420: e50b3008 str r3, [fp, #-8] ; / 10424: e51b3008 ldr r3, [fp, #-8] ; \ 10428: e283307b add r3, r3, #123 ; | a += 123 1042c: e50b3008 str r3, [fp, #-8] ; | 10430: ebffffe6 bl 103d0 <f1> ; call f1() 10434: e1a03000 mov r3, r0 ; | retval via r0, as small struct 10438: e50b300c str r3, [fp, #-12] ; / 1043c: e51b3008 ldr r3, [fp, #-8] ; \ 10440: e243307b sub r3, r3, #123 ; | a -= 123 10444: e50b3008 str r3, [fp, #-8] ; | 10448: e24b3010 sub r3, fp, #16 ; space to hold non-triv retval -> eax ... 1044c: e1a00003 mov r0, r3 ; ... as hidden first arg (r0) 10450: ebffffe5 bl 103ec <_Z2f2v> ; call f2() 10454: e51b3008 ldr r3, [fp, #-8] ; | 10458: e243300c sub r3, r3, #12 ; | a -= 12 1045c: e50b3008 str r3, [fp, #-8] ; / 10460: e1a00000 nop ; \ 10464: e24bd004 sub sp, fp, #4 ; | epilog 10468: e8bd8800 pop {fp, pc} ; | ; vim: ft=asm68k