view release on metacpan or search on metacpan
modifying or distributing the Package, you accept this license. Do not
use, modify, or distribute the Package, if you do not accept this
license.
(11) If your Modified Version has been derived from a Modified
Version made by someone other than you, you are nevertheless required
to ensure that your Modified Version complies with the requirements of
this license.
(12) This license does not grant you the right to use any trademark,
service mark, tradename, or logo of the Copyright Holder.
(13) This license includes the non-exclusive, worldwide,
free-of-charge patent license to make, have made, use, offer to sell,
sell, import and otherwise transfer the Package with respect to any
patent claims licensable by the Copyright Holder that are necessarily
infringed by the Package. If you institute patent litigation
(including a cross-claim or counterclaim) against any party alleging
that the Package constitutes direct or contributory patent
infringement, then this Artistic License to you shall terminate on the
date that such litigation is filed.
dyncall/autovar/autovar_ARCH.h
dyncall/autovar/autovar_CC.h
dyncall/autovar/autovar_OS.h
dyncall/autovar/autovar_OSFAMILY.h
dyncall/buildsys/cmake/Modules/FindDynCall.cmake
dyncall/buildsys/cmake/Modules/FindDynCallback.cmake
dyncall/buildsys/cmake/Modules/FindDynLoad.cmake
dyncall/buildsys/cmake/Modules/UseLATEX.cmake
dyncall/buildsys/mk/app.mk
dyncall/buildsys/mk/dirs.mk
dyncall/buildsys/mk/epilog.mk
dyncall/buildsys/mk/lib.mk
dyncall/buildsys/mk/pcc.mk
dyncall/buildsys/mk/prolog.mk
dyncall/buildsys/nmake/common.nmake
dyncall/buildsys/nmake/epilog.nmake
dyncall/buildsys/nmake/prolog.nmake
dyncall/buildsys/nmake/tool_clang.nmake
dyncall/buildsys/nmake/tool_gcc.nmake
dyncall/buildsys/nmake/tool_msvc.nmake
dyncall/buildsys/scripts/batch-build-linux.sh
dyncall/buildsys/scripts/batch-build-minix.sh
dyncall/buildsys/scripts/batch-build-psp.sh
dyncall/buildsys/scripts/conf-nds.bat
dyncall/buildsys/scripts/elf-to-psp-eboot.sh
dyncall/buildsys/scripts/setenv-cross-ios.sh
dyncall/buildsys/scripts/setenv-sdk-ios.sh
dyncall/doc/manual/callconvs/callconv_arm32.tex
dyncall/doc/manual/callconvs/callconv_arm64.tex
dyncall/doc/manual/callconvs/callconv_mips32.tex
dyncall/doc/manual/callconvs/callconv_mips64.tex
dyncall/doc/manual/callconvs/callconv_ppc32.tex
dyncall/doc/manual/callconvs/callconv_ppc64.tex
dyncall/doc/manual/callconvs/callconv_sparc32.tex
dyncall/doc/manual/callconvs/callconv_sparc64.tex
dyncall/doc/manual/callconvs/callconv_x64.tex
dyncall/doc/manual/callconvs/callconv_x86.tex
dyncall/doc/manual/dyncall_logo.eps
dyncall/doc/manual/dyncall_logo.pdf
dyncall/doc/manual/dyncall_logo.svg
dyncall/doc/manual/dyncall_watermark.eps
dyncall/doc/manual/dyncall_watermark.pdf
dyncall/doc/manual/dyncall_watermark.svg
dyncall/doc/manual/manual.tex
dyncall/doc/manual/manual_bindings.tex
dyncall/doc/manual/manual_build.tex
dyncall/doc/manual/manual_cc.tex
dyncall/doc/manual/manual_design.tex
dyncall/doc/manual/manual_devel.tex
dyncall/doc/manual/manual_dyncall_api.tex
dyncall/doc/manual/manual_dyncallback_api.tex
dyncall/doc/manual/manual_dynload_api.tex
dyncall/doc/manual/manual_epilog.tex
dyncall/doc/manual/manual_literature.tex
dyncall/doc/manual/manual_motivation.tex
dyncall/doc/manual/manual_overview.tex
dyncall/doc/manual/manual_tex4ht.cfg
dyncall/doc/manual/manual_title.tex
dyncall/dyncall/CMakeLists.txt
dyncall/dyncall/DynCallConfig.cmake
dyncall/dyncall/Makefile.embedded
dyncall/dyncall/Makefile.generic
dyncall/dyncall/Nmakefile
dyncall/test/hacking-mips/README.txt
dyncall/test/hacking-mips/call.c
dyncall/test/hacking-mips/calls.c
dyncall/test/hacking-mips/common.h
dyncall/test/hacking-mips/dispatch.c
dyncall/test/hacking-mips/f.c
dyncall/test/hacking-mips/f0.c
dyncall/test/hacking-mips/funs.c
dyncall/test/hacking-mips/main.c
dyncall/test/hacking-mips/node.c
dyncall/test/hacking-mips/prolog.c
dyncall/test/hacking-mips/retn.c
dyncall/test/malloc_wx/CMakeLists.txt
dyncall/test/malloc_wx/Makefile.embedded
dyncall/test/malloc_wx/Makefile.generic
dyncall/test/malloc_wx/Nmakefile
dyncall/test/malloc_wx/mkfile
dyncall/test/malloc_wx/test_wx.c
dyncall/test/mkfile
dyncall/test/nm/CMakeLists.txt
dyncall/test/nm/Makefile.embedded
builder/Affix.pm view on Meta::CPAN
next if $destfile->is_dir;
next
if $destfile->is_file &&
stat( $destfile->absolute->stringify )->mtime < $header->{Time};
warn $destfile;
$destfile->parent->mkpath;
my $raw = '';
while ( ( $status = $u->read( my $buff ) ) > 0 ) { $raw .= $buff }
$destfile->spew_raw($raw);
$destfile->touch;
$retval = $destfile->parent if $destfile =~ 'build.log';
}
return $retval;
}
1;
dyncall/ChangeLog view on Meta::CPAN
o added zero-config (BSD,GNU,SUN) make files (Makefile.embedded)
o added in/out-of-source configure2 w/ (BSD,GNU) make files (Makefile.generic)
o added bootstrap lua script (download/build)
o Nmakefile: more tests included (resolve_self)
o improved cross-compilation for iOS (upgrade to 4.3 sdk)
o darwin 8.0 support
o added 'install' support for Makefile.embedded
buildsys/gmake updates:
o added support for msvc/x64 tool-chain
o default settings for build-dir changed to '.'
o cleanup: removed top-level Make{Prolog,Epilog,Rules} files and updated all sub-projects and tests
o added support for DESTDIR staging installation
o added support for manual page installation
buildsys/cmake updates:
o updated find module scripts (see cmake/Modules)
o added support for using dyncall as sub-project (via *Config.cmake files)
see details in README.CMake
o fixes for msvc and ml
o fixes for CPack
o fixes for universal builds on Mac OS X
o supports SunPro with *.S files.
dyncall/Nmakefile view on Meta::CPAN
#///////////////////////////////////////////////////
#
# nmake makefile
# Nmakefile
#
#///////////////////////////////////////////////////
TOP = .
!INCLUDE $(TOP)\buildsys\nmake\prolog.nmake
DIRS = dyncall dynload dyncallback
tests: dummy
!echo Building tests ... && cd test && $(MAKE) /NOLOGO /F Nmakefile && cd ..
doc: dummy
!echo Building documentation ... && cd $@/manual && $(MAKE) /NOLOGO /F Nmakefile && cd ..
# Pseudo-targets are always out of date...
dummy:
!INCLUDE $(TOP)\buildsys\nmake\epilog.nmake
dyncall/ToDo view on Meta::CPAN
1.5:
----
- test atpcs thumb on arm and verify if ellipsis and C++ thiscalls work, if so adapt doc appendix
- test eabi thumb on arm and verify if ellipsis and C++ thiscalls work, if so adapt doc appendix
- new platform matrix
* check dark green cells and validate in general
- test/thunk win/x64 doesn't output anything decent for stack test (neither sigsegv nor output), which can create a problem for test log file as it'll mess with the subsequent test's output)
- remove test/gen-masm alltogether
- test code: add sparc tests for when out of register windows, meaning multiple layers deep in the call stack
- support platforms without shared libraries so they can be built by just typing `./configure;make` (e.g. minix < 3.2.1)
* also make sure minix with shared library support builds and works in general (>= 3.2.1) as well as ELF on Minix (>= 3.2.0) to begin with (as that's the base, and we only test on 3.1.8 so far)
- dyncallback's "stack_cleanup" can be removed from non x86 impls... test if they still work
- the CallVM-free functions are per VTable, however the latter can be changed out
at runtime... which basically changes potentially the deallocator...
same goes for functions setting the mode. think about how to make this safer - currently
we have a higher flexibility and we need to potentially clean up from the mode we are in,
however, this is open to misuse
dyncall/ToDo view on Meta::CPAN
--------
- dyncall sparc v7/v8: -xO3 on SunPro segfaults in tests (observed years ago)
- callbacks and use of CC signature characters (only x86 has any support for different CCs for callbacks):
* support for arm (arm/thumb on same platform)
* check if ellipsis support is needed (is there any need for calling back into an ellipse function?)
* check if syscalls support is needed (is there any need for calling back into a syscall?)
- think about using 'inline' for all/most dyncall_api.c functions?
- support for where syscalls originate from on OpenBSD: http://undeadly.org/cgi?action=article;sid=20191202105849
- merge arm32_thumb_{gas/apple} and include thumb support for portasm
- x64 verification: return values are passed via RAX and RDX, and XMM0 and XMM1.
- find big endian arm box (also hardfloat), e.g. cubietruck: http://blog.netbsd.org/tnf/entry/working_arm_multiprocessor_support
- test if armhf/thumb is actually working... pulls in arm mode code in dyncall_callvm.c
- dyncall_call_mips_n32.h and dyncall_call_mips_n64.h are pretty much the same, share code
- support for return values: aggregate return values on non-x64
- support for argument values: aggregates on non-x64, vector types, long double (c89)
* make sure that struct support for ellipsis calls are not forgotten (copy everything by value)
- support for argument values: _Complex (c99)
- support for argument values: Fixed-width integer types (c99) - could be just aliases but would help abstracting it away from library users
- other syscalls
- test MIPS32 eabi big endian (current port works on psp, which is little endian)
- implement MIPS64 N32 (gcc -mabi=n32); both, little and big-endian (looks like NetNBSD on and
EdgeRouter lite uses this: https://blog.netbsd.org/tnf/entry/hands_on_experience_with_edgerouter)
- MIPS64 n32 softfloat support (-msoft-float)
- implement MIPS64 EABI (gcc -mabi=eabi); both, little and big-endian
- support for Minix/arm
- improve ellipsis test:
* test not just with one fixed arg, to also simulate alignment problems
* test return values
* convert from c++ to c, to have it also on plan9, and more portability
dynload:
--------
dyncall/ToDo view on Meta::CPAN
dynload_syms_elf.c:165: error: `DT_HASH' undeclared (first use in this function)
make: *** [dynload_syms.o] Error 1
dyncallback:
------------
- callback_plain's return value not correct anymore on NDS (maybe just broken testcode?),
see above under 1.1 items
* check other platforms also, if asm stub initializes retval space, correctly
- test MIPS32 eabi big endian (current port works on psp, which is little endian)
- implement MIPS64 N32 (gcc -mabi=n32); both, little and big-endian (looks like NetNBSD on and
EdgeRouter lite uses this: https://blog.netbsd.org/tnf/entry/hands_on_experience_with_edgerouter)
- MIPS64 n32 softfloat support (-msoft-float)
- implement MIPS64 EABI (gcc -mabi=eabi); both, little and big-endian
- support for Minix/arm
bindings:
---------
- release bindings as standalone packages (already done for rbdc as a gem and rdyncall on cran)
* add note to documentation, where bindings are
- add rdoc documentation to ruby gem
- add pydoc for python
dyncall/buildsys/cmake/Modules/UseLATEX.cmake view on Meta::CPAN
istfile ${istfile_line}
)
FOREACH(newglossary ${newglossary_lines})
STRING(REGEX REPLACE
"@newglossary[ \t]*{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}"
"\\1" glossary_name ${newglossary}
)
STRING(REGEX REPLACE
"@newglossary[ \t]*{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}"
"${LATEX_TARGET}.\\2" glossary_log ${newglossary}
)
STRING(REGEX REPLACE
"@newglossary[ \t]*{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}"
"${LATEX_TARGET}.\\3" glossary_out ${newglossary}
)
STRING(REGEX REPLACE
"@newglossary[ \t]*{([^}]*)}{([^}]*)}{([^}]*)}{([^}]*)}"
"${LATEX_TARGET}.\\4" glossary_in ${newglossary}
)
MESSAGE("${MAKEINDEX_COMPILER} ${MAKEGLOSSARIES_COMPILER_FLAGS} -s ${istfile} -t ${glossary_log} -o ${glossary_out} ${glossary_in}")
EXEC_PROGRAM(${MAKEINDEX_COMPILER} ARGS ${MAKEGLOSSARIES_COMPILER_FLAGS}
-s ${istfile} -t ${glossary_log} -o ${glossary_out} ${glossary_in}
)
ENDFOREACH(newglossary)
ENDMACRO(LATEX_MAKEGLOSSARIES)
#############################################################################
# Helper macros for establishing LaTeX build.
#############################################################################
MACRO(LATEX_NEEDIT VAR NAME)
IF (NOT ${VAR})
dyncall/buildsys/nmake/epilog.nmake view on Meta::CPAN
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
#//////////////////////////////////////////////////////////////////////////////
#///////////////////////////////////////////////////
#
# nmake rules
# epilog.nmake
#
#///////////////////////////////////////////////////
!INCLUDE common.nmake
dyncall/buildsys/nmake/prolog.nmake view on Meta::CPAN
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
#//////////////////////////////////////////////////////////////////////////////
#///////////////////////////////////////////////////
#
# nmake rules
# prolog.nmake
#
#///////////////////////////////////////////////////
.SILENT:
# Default "build all" target.
all: configure build
dyncall/buildsys/nmake/tool_msvc.nmake view on Meta::CPAN
CC =cl
CXX =cl
AR =lib
!IF "$(BUILD_ARCH)" == "x64"
AS =ml64
!ELSE IF "$(BUILD_ARCH)" == "x86"
AS =ml
!ENDIF
LD =link
ASFLAGS = /c /nologo
!IF "$(BUILD_CONFIG)" == "debug"
CFLAGS = /EHsc /GR- /GS- /Od /c /nologo /I$(TOP)\dyncall /I$(TOP)\dyncallback /DEBUG /Z7
LDFLAGS = /NOLOGO /DEBUG
ARFLAGS = /NOLOGO /DEBUG
!ELSE
CFLAGS = /EHsc /GR- /GS- /Ox /c /nologo /I$(TOP)\dyncall /I$(TOP)\dyncallback
LDFLAGS = /OPT:REF /OPT:ICF /NOLOGO
ARFLAGS = /NOLOGO
!ENDIF
CXXFLAGS = $(CFLAGS)
.SUFFIXES:
.SUFFIXES: .obj .exe .dll .lib .pdf .c .cpp .asm .tex .cc
dyncall/doc/disas_examples/arm.armhf.disas view on Meta::CPAN
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 ; |
dyncall/doc/disas_examples/arm.armhf.disas view on Meta::CPAN
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; };
dyncall/doc/disas_examples/arm.armhf.disas view on Meta::CPAN
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 ; |
dyncall/doc/disas_examples/arm.armhf.disas view on Meta::CPAN
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
dyncall/doc/disas_examples/arm.armhf.disas view on Meta::CPAN
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 */
dyncall/doc/disas_examples/arm.armhf.disas view on Meta::CPAN
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
dyncall/doc/disas_examples/arm.armhf.disas view on Meta::CPAN
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) { } };
dyncall/doc/disas_examples/arm.armhf.disas view on Meta::CPAN
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
dyncall/doc/disas_examples/arm.atpcs_arm.disas view on Meta::CPAN
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
dyncall/doc/disas_examples/arm.atpcs_arm.disas view on Meta::CPAN
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]
dyncall/doc/disas_examples/arm.atpcs_arm.disas view on Meta::CPAN
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
dyncall/doc/disas_examples/arm.atpcs_arm.disas view on Meta::CPAN
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) { } };
dyncall/doc/disas_examples/arm.darwin_arm.disas view on Meta::CPAN
20: 0c 20 07 e5 str r2, [r7, #-12]
24: 0c 30 8d e5 str r3, [sp, #12]
28: 08 e0 8d e5 str lr, [sp, #8]
2c: 04 c0 8d e5 str r12, [sp, #4]
30: 00 90 8d e5 str r9, [sp]
34: 07 d0 a0 e1 mov sp, r7
38: 80 80 bd e8 pop {r7, pc}
_nonleaf_call:
3c: b0 40 2d e9 push {r4, r5, r7, lr} ; |
40: 08 70 8d e2 add r7, sp, #8 ; | prolog
44: 30 d0 4d e2 sub sp, sp, #48 ; /
48: 14 90 97 e5 ldr r9, [r7, #20] ; \
4c: 10 c0 97 e5 ldr r12, [r7, #16] ; |
50: 0c e0 97 e5 ldr lr, [r7, #12] ; | in args 4,5,6,7 from prev frame's param area -> regs ...
54: 08 40 97 e5 ldr r4, [r7, #8] ; |
58: 4c 50 00 e3 movw r5, #76 ; 'L' -> r5
5c: 0c 00 07 e5 str r0, [r7, #-12] ; in arg 0 -> temp space in local area
60: 10 10 07 e5 str r1, [r7, #-16] ; in arg 1 -> temp space in local area
64: 14 20 07 e5 str r2, [r7, #-20] ; in arg 2 -> temp space in local area
68: 18 30 07 e5 str r3, [r7, #-24] ; in arg 3 -> temp space in local area
dyncall/doc/disas_examples/arm.darwin_arm.disas view on Meta::CPAN
88: 18 20 17 e5 ldr r2, [r7, #-24] ; arg 2
8c: 1c 30 9d e5 ldr r3, [sp, #28] ; arg 3 (fetched from local area previously copied to)
90: 18 90 9d e5 ldr r9, [sp, #24] ; |
94: 14 c0 9d e5 ldr r12, [sp, #20] ; | args 4,5,6 (fetched from local area previously copied to) -> regs, and ...
98: 10 e0 9d e5 ldr lr, [sp, #16] ; /
9c: 00 90 8d e5 str r9, [sp] ; \
a0: 04 c0 8d e5 str r12, [sp, #4] ; | ... "pushed" onto stack
a4: 08 e0 8d e5 str lr, [sp, #8] ; |
a8: d4 ff ff eb bl #-176 <_leaf_call> ; return address -> r14/lr, and call
ac: 08 d0 47 e2 sub sp, r7, #8 ; |
b0: b0 80 bd e8 pop {r4, r5, r7, pc} ; | epilog
_main:
b4: 90 40 2d e9 push {r4, r7, lr} ; |
b8: 04 70 8d e2 add r7, sp, #4 ; | prolog
bc: 14 d0 4d e2 sub sp, sp, #20 ; |
c0: 00 00 00 e3 movw r0, #0 ; arg 0
c4: 01 10 00 e3 movw r1, #1 ; arg 1
c8: 02 20 00 e3 movw r2, #2 ; arg 2
cc: 03 30 00 e3 movw r3, #3 ; arg 3
d0: 04 90 00 e3 movw r9, #4 ; |
d4: 05 c0 00 e3 movw r12, #5 ; |
d8: 06 e0 00 e3 movw lr, #6 ; | args 4,5,6,7 in regs ...
dc: 07 40 00 e3 movw r4, #7 ; |
e0: 08 00 07 e5 str r0, [r7, #-8] ; unsure... why place arg 0 in local area? @@@
e4: 00 90 8d e5 str r9, [sp] ; |
e8: 04 c0 8d e5 str r12, [sp, #4] ; |
ec: 08 e0 8d e5 str lr, [sp, #8] ; | ... "push" args 4,5,6,7 onto stack
f0: 0c 40 8d e5 str r4, [sp, #12] ; |
f4: d0 ff ff eb bl #-192 <_nonleaf_call> ; return address -> r14/lr, and call
f8: 00 00 00 e3 movw r0, #0 ; return value
fc: 04 d0 47 e2 sub sp, r7, #4 ; |
100: 90 80 bd e8 pop {r4, r7, pc} ; | epilog
; ----------------- with spilling ------------->
; #include <stdarg.h>
;
; void leaf_call(int b, int c, int d, int e, int f, int g, int h)
; {
; }
dyncall/doc/disas_examples/arm.darwin_thumb.disas view on Meta::CPAN
1a: cd f8 08 e0 str.w lr, [sp, #8]
1e: cd f8 04 c0 str.w r12, [sp, #4]
22: cd f8 00 90 str.w r9, [sp]
26: 07 b0 add sp, #28
28: 80 bd pop {r7, pc}
_nonleaf_call:
2a: 83 b0 sub sp, #12 ; | space for spill area (b/c pushing was apparently too easy)
2c: 80 b5 push {r7, lr} ; |
2e: 6f 46 mov r7, sp ; |
30: 8d b0 sub sp, #52 ; | prolog
32: 3b 61 str r3, [r7, #16] ; | |
34: fa 60 str r2, [r7, #12] ; | | spill (before reg save area)
36: b9 60 str r1, [r7, #8] ; | |
38: 4c 21 movs r1, #76
3a: 0b aa add r2, sp, #44
3c: 0c 90 str r0, [sp, #48]
3e: 07 f1 08 00 add.w r0, r7, #8
42: 10 60 str r0, [r2]
44: 0b 98 ldr r0, [sp, #44]
46: 02 1d adds r2, r0, #4
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
10: e3 13 00 b9 str w3, [sp, #16]
14: e4 0f 00 b9 str w4, [sp, #12]
18: e5 0b 00 b9 str w5, [sp, #8]
1c: e6 07 00 b9 str w6, [sp, #4]
20: ff 83 00 91 add sp, sp, #32
24: c0 03 5f d6 ret
nonleaf_call:
28: ff 83 04 d1 sub sp, sp, #288 ; | includes alloca()'d static space, already
2c: fc 83 00 f9 str x28, [sp, #256] ; | (unsure why r28 is preserved @@@)
30: fd 7b 11 a9 stp x29, x30, [sp, #272] ; | prolog
34: fd 43 04 91 add x29, sp, #272 ; | adjust/set frame pointer (since sp was modified first)
38: 88 09 80 52 mov w8, #76 ; 'L' -> w8
3c: a0 c3 1e b8 stur w0, [x29, #-20] ; in arg 0 -> local area (as temp store)
40: a1 83 1e b8 stur w1, [x29, #-24] ; in arg 1 -> local area (as temp store)
44: a2 43 1e b8 stur w2, [x29, #-28] ; in arg 2 -> local area (as temp store)
48: a3 03 1e b8 stur w3, [x29, #-32] ; in arg 3 -> local area (as temp store)
4c: a4 c3 1d b8 stur w4, [x29, #-36] ; in arg 4 -> local area (as temp store)
50: a5 83 1d b8 stur w5, [x29, #-40] ; in arg 5 -> local area (as temp store)
54: a6 43 1d b8 stur w6, [x29, #-44] ; in arg 6 -> local area (as temp store)
58: a7 03 1d b8 stur w7, [x29, #-48] ; in arg 7 -> local area (as temp store)
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
60: a0 83 5e b8 ldur w0, [x29, #-24] ; arg 0
64: a1 43 5e b8 ldur w1, [x29, #-28] ; arg 1
68: a2 03 5e b8 ldur w2, [x29, #-32] ; arg 2
6c: a3 c3 5d b8 ldur w3, [x29, #-36] ; arg 3
70: a4 83 5d b8 ldur w4, [x29, #-40] ; arg 4
74: a5 43 5d b8 ldur w5, [x29, #-44] ; arg 5
78: a6 03 5d b8 ldur w6, [x29, #-48] ; arg 6
7c: e1 ff ff 97 bl #-124 ; return address -> r30/lr, and call
80: fd 7b 51 a9 ldp x29, x30, [sp, #272] ; |
84: fc 83 40 f9 ldr x28, [sp, #256] ; |
88: ff 83 04 91 add sp, sp, #288 ; | epilog
8c: c0 03 5f d6 ret ; |
main:
90: ff 83 00 d1 sub sp, sp, #32 ; |
94: fd 7b 01 a9 stp x29, x30, [sp, #16] ; | prolog
98: fd 43 00 91 add x29, sp, #16 ; |
9c: 08 00 80 52 mov w8, #0 ; clearing r8 (indirect result location pointer)
a0: e1 03 00 32 orr w1, wzr, #0x1 ; arg 1
a4: e2 03 1f 32 orr w2, wzr, #0x2 ; arg 2
a8: e3 07 00 32 orr w3, wzr, #0x3 ; arg 3
ac: e4 03 1e 32 orr w4, wzr, #0x4 ; arg 4
b0: a5 00 80 52 mov w5, #5 ; arg 5
b4: e6 07 1f 32 orr w6, wzr, #0x6 ; arg 6
b8: e7 0b 00 32 orr w7, wzr, #0x7 ; arg 7
bc: bf c3 1f b8 stur wzr, [x29, #-4] ; unsure... store a zero in local area@@@
c0: e0 03 08 2a mov w0, w8 ; arg 0 (= 0 set in w8, above)
c4: e8 0b 00 b9 str w8, [sp, #8] ; temp storing 0 in local area
c8: d8 ff ff 97 bl #-160 ; return address -> r30/lr, and call
cc: e0 0b 40 b9 ldr w0, [sp, #8] ; return value (unsure why not just using immediate @@@)
d0: fd 7b 41 a9 ldp x29, x30, [sp, #16] ; |
d4: ff 83 00 91 add sp, sp, #32 ; | epilog
d8: c0 03 5f d6 ret ; |
; ---------- same with more args so stack is also used ---------->
; #include <stdlib.h>
;
; void leaf_call(int b, int c, int d, int e, int f, int g, int h, int i, int j)
; {
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
1c: e5 1b 00 b9 str w5, [sp, #24]
20: e6 17 00 b9 str w6, [sp, #20]
24: e7 13 00 b9 str w7, [sp, #16]
28: e8 0f 00 b9 str w8, [sp, #12]
2c: ff c3 00 91 add sp, sp, #48
30: c0 03 5f d6 ret
0000000000000034 nonleaf_call:
34: ff 03 05 d1 sub sp, sp, #320 ; | includes alloca()'d static space, already
38: fc 93 00 f9 str x28, [sp, #288] ; | (unsure why r28 is preserved @@@)
3c: fd 7b 13 a9 stp x29, x30, [sp, #304] ; | prolog
40: fd c3 04 91 add x29, sp, #304 ; / adjust/set frame pointer (since sp was modified first)
44: a8 13 40 b9 ldr w8, [x29, #16] ; \
48: a9 1b 40 b9 ldr w9, [x29, #24] ; | in args 8,9 from prev frame's param area -> regs, no we have args 0-9 all in r0-r9
4c: 8a 09 80 52 mov w10, #76 ; 'L' -> w10
50: a0 c3 1e b8 stur w0, [x29, #-20] ; |
54: a1 83 1e b8 stur w1, [x29, #-24] ; |
58: a2 43 1e b8 stur w2, [x29, #-28] ; |
5c: a3 03 1e b8 stur w3, [x29, #-32] ; |
60: a4 c3 1d b8 stur w4, [x29, #-36] ; | ... in args 0,1,2,3,4,5,6,7,8,9 -> temp space in local area ...
64: a5 83 1d b8 stur w5, [x29, #-40] ; |
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
8c: a4 83 5d b8 ldur w4, [x29, #-40] ; arg 4
90: a5 43 5d b8 ldur w5, [x29, #-44] ; arg 5
94: a6 03 5d b8 ldur w6, [x29, #-48] ; arg 6
98: a7 c3 5c b8 ldur w7, [x29, #-52] ; arg 7
9c: a8 83 5c b8 ldur w8, [x29, #-56] ; arg 8 -> w8, and ...
a0: eb 03 00 91 mov x11, sp ; ... with help of x11 (why?) ...
a4: 68 01 00 b9 str w8, [x11] ; ... "pushed" onto to of stack
a8: d6 ff ff 97 bl #-168 <leaf_call> ; return address -> r30/lr, and call
ac: fd 7b 53 a9 ldp x29, x30, [sp, #304] ; |
b0: fc 93 40 f9 ldr x28, [sp, #288] ; |
b4: ff 03 05 91 add sp, sp, #320 ; | epilog
b8: c0 03 5f d6 ret ; |
00000000000000bc main:
bc: ff c3 00 d1 sub sp, sp, #48 ; |
c0: fd 7b 02 a9 stp x29, x30, [sp, #32] ; | prolog
c4: fd 83 00 91 add x29, sp, #32 ; |
c8: 08 00 80 52 mov w8, #0 ; clearing r8 (indirect result location pointer)
cc: e1 03 00 32 orr w1, wzr, #0x1 ; arg 1
d0: e2 03 1f 32 orr w2, wzr, #0x2 ; arg 2
d4: e3 07 00 32 orr w3, wzr, #0x3 ; arg 3
d8: e4 03 1e 32 orr w4, wzr, #0x4 ; arg 4
dc: a5 00 80 52 mov w5, #5 ; arg 5
e0: e6 07 1f 32 orr w6, wzr, #0x6 ; arg 6
e4: e7 0b 00 32 orr w7, wzr, #0x7 ; arg 7
e8: e9 03 1d 32 orr w9, wzr, #0x8 ; arg 8 -> r9
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
f0: bf c3 1f b8 stur wzr, [x29, #-4] ; unsure... store a zero in local area@@@
f4: e0 03 08 2a mov w0, w8 ; arg 0 (= 0 set in w8, above)
f8: eb 03 00 91 mov x11, sp ; use sp in x11 (why?), to ...
fc: 69 01 00 b9 str w9, [x11] ; ... place arg 8 on top of stack
100: eb 03 00 91 mov x11, sp ; use sp in x11 (why?), to ... (set again, pointlessly)
104: 6a 09 00 b9 str w10, [x11, #8] ; ... place arg 9 on stack (next to arg 8)
108: a8 83 1f b8 stur w8, [x29, #-8] ; temp storing 0 in local area @@@ why?
10c: ca ff ff 97 bl #-216 <nonleaf_call> ; return address -> r30/lr, and call
110: a0 83 5f b8 ldur w0, [x29, #-8] ; |
114: fd 7b 42 a9 ldp x29, x30, [sp, #32] ; |
118: ff c3 00 91 add sp, sp, #48 ; | epilog
11c: c0 03 5f d6 ret ; |
; ---------- for spilling ---------->
; #include <stdlib.h>
; #include <stdarg.h>
;
; void leaf_call(int b, int c, int d, int e, int f, int g, int h, int i, int j)
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
1c: e5 1b 00 b9 str w5, [sp, #24]
20: e6 17 00 b9 str w6, [sp, #20]
24: e7 13 00 b9 str w7, [sp, #16]
28: e8 0f 00 b9 str w8, [sp, #12]
2c: ff c3 00 91 add sp, sp, #48
30: c0 03 5f d6 ret
0000000000000034 nonleaf_call:
34: fc 4f be a9 stp x28, x19, [sp, #-32]! ; |
38: fd 7b 01 a9 stp x29, x30, [sp, #16] ; |
3c: fd 43 00 91 add x29, sp, #16 ; | prolog
40: ff 83 07 d1 sub sp, sp, #480 ; |
44: f3 03 00 91 mov x19, sp
48: 67 56 80 3d str q7, [x19, #336] ; |
4c: 66 52 80 3d str q6, [x19, #320] ; |
50: 65 4e 80 3d str q5, [x19, #304] ; |
54: 64 4a 80 3d str q4, [x19, #288] ; |
58: 63 46 80 3d str q3, [x19, #272] ; | spill all flot regs (on top of spilled integers, below
5c: 62 42 80 3d str q2, [x19, #256] ; |
60: 61 3e 80 3d str q1, [x19, #240] ; |
64: 60 3a 80 3d str q0, [x19, #224] ; /
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
ac: ac 03 5f f8 ldur x12, [x29, #-16]
b0: a5 83 5f f8 ldur x5, [x29, #-8]
b4: e4 03 0c aa mov x4, x12
b8: d2 ff ff 97 bl #-184 <leaf_call>
bc: fd 7b 4a a9 ldp x29, x30, [sp, #160]
c0: ff c3 02 91 add sp, sp, #176
c4: c0 03 5f d6 ret
00000000000000c8 main:
c8: ff 03 01 d1 sub sp, sp, #64 ; |
cc: fd 7b 03 a9 stp x29, x30, [sp, #48] ; | prolog
d0: fd c3 00 91 add x29, sp, #48 ; |
d4: 08 00 80 52 mov w8, #0 ; prep arg 0
d8: a9 00 80 52 mov w9, #5 ; | i
dc: ea 07 1f 32 orr w10, wzr, #0x6 ; | prep local struct A's data j
e0: eb 0b 40 b2 orr x11, xzr, #0x7 ; | l
e4: e1 03 00 32 orr w1, wzr, #0x1 ; arg 1
e8: e2 03 1f 32 orr w2, wzr, #0x2 ; arg 2
ec: e3 07 00 32 orr w3, wzr, #0x3 ; arg 3
f0: e4 03 1e 32 orr w4, wzr, #0x4 ; arg 4
f4: e7 03 1d 32 orr w7, wzr, #0x8 ; arg 6
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
114: ed 13 40 f9 ldr x13, [sp, #32] ; 2nd dword of struct A -> x13
118: e0 03 08 2a mov w0, w8 ; arg 0
11c: e5 03 0b aa mov x5, x11 ; |
120: e6 03 0d aa mov x6, x13 ; / arg 5 (struct A), passed in regs as 2 dwords
124: eb 03 00 91 mov x11, sp ; \
128: 6c 01 00 b9 str w12, [x11] ; | arg 7, pushed onto stack
12c: e8 17 00 b9 str w8, [sp, #20] ; prep return value, temp store on stack local area
130: bf ff ff 97 bl #-260 <nonleaf_call> ; return address -> r30/lr, and call
134: e0 17 40 b9 ldr w0, [sp, #20] ; return value (unsure why not just using immediate @@@)
138: fd 7b 43 a9 ldp x29, x30, [sp, #48] ; |
13c: ff 03 01 91 add sp, sp, #64 ; | epilog
140: c0 03 5f d6 ret ; |
; output from godbolt compiler explorer w/ msvc 19.14
|leaf_call| PROC
|$LN3|
sub sp,sp,#0x30
str w0,[sp]
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
bl __security_pop_cookie
ldp fp,lr,[sp],#0x10
ret
ENDP ; |nonleaf_call|
|main| PROC
|$LN3|
stp fp,lr,[sp,#-0x10]! ; |
mov fp,sp ; |
bl __security_push_cookie ; | prolog
sub sp,sp,#0x20 ; /
mov w8,#5 ; \
str w8,[sp,#0x10] ; | i
mov w8,#6 ; |
str w8,[sp,#0x14] ; | write struct A to local area j
mov x8,#7 ; |
str x8,[sp,#0x18] ; / l
mov w8,#9 ; \
str w8,[sp] ; | arg 7, pushed onto stack
mov w7,#8 ; arg 6
ldr x6,[sp,#0x18] ; | l
ldr x5,[sp,#0x10] ; | arg 5 (struct A), passed in regs as 2 dwords i, j
mov w4,#4 ; arg 4
mov w3,#3 ; arg 3
mov w2,#2 ; arg 2
mov w1,#1 ; arg 1
mov w0,#0 ; arg 0
bl nonleaf_call ; return address -> r30/lr, and call
mov w0,#0 ; return value
add sp,sp,#0x20 ; |
bl __security_pop_cookie ; | epilog
ldp fp,lr,[sp],#0x10 ; |
ret ; |
ENDP ; |main|
; ---------- structs by value, complex example (multiple structs) ---------->
;
; struct A { int i, j; float f; };
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
34: f3 13 00 fd str d19, [sp, #32]
38: f2 0f 00 fd str d18, [sp, #24]
3c: f1 0b 00 fd str d17, [sp, #16]
40: f0 07 00 fd str d16, [sp, #8]
44: e7 03 00 fd str d7, [sp]
48: ff 43 01 91 add sp, sp, #80
4c: c0 03 5f d6 ret
0000000000000050 main:
50: ff 43 02 d1 sub sp, sp, #144 ; |
54: fd 7b 08 a9 stp x29, x30, [sp, #128] ; | prolog
58: fd 03 02 91 add x29, sp, #128 ; /
5c: e8 03 1f 2a mov w8, wzr ; \ | |
60: a8 c3 1f b8 stur w8, [x29, #-4] ; | | | zero 4 bytes in local area @@@ struct padding?
64: e9 1b 09 32 orr w9, wzr, #0x3f800000 ; | struct A 1.f |
68: a9 83 1f b8 stur w9, [x29, #-8] ; / |
6c: e9 03 02 32 orr w9, wzr, #0x40000000 ; \ 2.f |
70: a9 03 1f b8 stur w9, [x29, #-16] ; | |
74: 09 08 a8 52 mov w9, #1077936128 ; | struct B 3.f |
78: a9 43 1f b8 stur w9, [x29, #-12] ; / |
7c: 09 10 a8 52 mov w9, #1082130432 ; \ 4.f |
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
f4: ea 03 00 91 mov x10, sp ; sp in x10, for below indirections (a bit pointless)
f8: 53 11 00 fd str d19, [x10, #32] ; \
fc: 52 0d 00 fd str d18, [x10, #24] ; | arg 5 (struct F), via stack
100: 51 09 00 fd str d17, [x10, #16] ; /
104: 50 05 00 fd str d16, [x10, #8] ; \ arg 4 (struct E), via stack (not split across regs and stack)
108: 47 01 00 fd str d7, [x10] ; |
10c: e8 2f 00 b9 str w8, [sp, #44] ; prep return value, temp store on stack local area
110: bc ff ff 97 bl #-272 <leaf_call> ; return address -> r30/lr, and call
114: e0 2f 40 b9 ldr w0, [sp, #44] ; return value (unsure why not just using immediate @@@)
118: fd 7b 48 a9 ldp x29, x30, [sp, #128] ; |
11c: ff 43 02 91 add sp, sp, #144 ; | epilog
120: c0 03 5f d6 ret ; |
; output from godbolt compiler explorer w/ msvc 19.14
|leaf_call| PROC
|$LN3|
sub sp,sp,#0x30
str s0,[sp]
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
str s5,[sp,#0x20]
str d6,[sp,#0x10]
add sp,sp,#0x30
ret
ENDP ; |leaf_call|
|main| PROC
|$LN3|
stp fp,lr,[sp,#-0x60]! ; |
mov fp,sp ; | prolog
sub sp,sp,#0x30 ; /
fmov s16,#1 ; \ struct A 1.f |
str s16,[sp,#0x40] ; / |
fmov s16,#2 ; \ 2.f |
str s16,[sp,#0x48] ; | |
fmov s16,#3 ; | struct B 3.f |
str s16,[sp,#0x4C] ; / |
fmov s16,#4 ; \ 4.f |
str s16,[sp,#0x58] ; | |
fmov s16,#5 ; | 5.f |
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
ldr d6,[sp,#0x50] ; arg 3 (struct D), via reg
ldr s5,[sp,#0x60] ; \
ldr s4,[sp,#0x5C] ; | arg 2 (struct C), via reg
ldr s3,[sp,#0x58] ; /
ldr s2,[sp,#0x4C] ; \
ldr s1,[sp,#0x48] ; / arg 1 (struct B), via reg
ldr s0,[sp,#0x40] ; arg 0 (struct A), via reg
bl leaf_call ; return address -> r30/lr, and call
mov w0,#0 ; return value
add sp,sp,#0x30 ; |
ldp fp,lr,[sp],#0x60 ; | epilog
ret ; |
ENDP ; |main|
; ---------- returning structs by value ---------->
;
; struct Small { char x; };
; struct Big { long long i,j,k,l; long m; }; /* bigger than 16b */
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
; struct Big b = f1();
; return b.j + b.k + b.m + s.x;
; }
; output from freebsd-13.0_r348764-arm64 w/ clang 8.0.0
0000000000000000 f0:
0: ff 83 00 d1 sub sp, sp, #32 ; |
4: fe 0b 00 f9 str x30, [sp, #16] ; | prolog
8: 08 00 00 90 adrp x8, #0 ; compute addr to storage map (probably to #132)
c: 08 01 00 91 add x8, x8, #0 ; addr offset (pointless)
10: e2 03 40 b2 orr x2, xzr, #0x1 ; @@@ unsure, #1 -> x2
14: e9 3f 00 91 add x9, sp, #15 ; addr to #132 -> x9 @@@?
18: e0 03 09 aa mov x0, x9 ; @@@ unsure
1c: e1 03 08 aa mov x1, x8 ; @@@ unsure
20: e9 03 00 f9 str x9, [sp] ; store addr to #132 to top of stack
24: 00 00 00 94 bl #0 <f0+0x24> ; @@@unsure
28: e8 03 40 f9 ldr x8, [sp] ; *sp -> x8
2c: 0a 01 40 39 ldrb w10, [x8] ; *x8 -> w10
30: e9 03 0a 2a mov w9, w10 ; w10 -> w9
34: 20 1d 40 d3 ubfx x0, x9, #0, #8 ; return value ("Unsigned Bit Field Extract", copy 8 bits from x9's LSBits starting at bit 0 to x0, and zero extend; = struct in reg)
38: fe 0b 40 f9 ldr x30, [sp, #16] ; |
3c: ff 83 00 91 add sp, sp, #32 ; | epilog
40: c0 03 5f d6 ret ; |
0000000000000044 f1:
44: ff 03 01 d1 sub sp, sp, #64 ; |
48: fe 1b 00 f9 str x30, [sp, #48] ; | prolog
4c: 09 00 80 52 mov w9, #0 ; @@@ unsure
50: 02 05 80 d2 mov x2, #40 ; @@@ unsure
54: 6a 80 83 d2 mov x10, #7171 ; | i
58: 6b 0c 80 d2 mov x11, #99 ; | j
5c: 4c 0c 80 92 mov x12, #-99 ; | prep local struct Big's data k
60: ad 83 81 92 mov x13, #-3102 ; | l
64: ee 03 7b b2 orr x14, xzr, #0x20 ; | m
68: e0 03 08 aa mov x0, x8 ; retval: ptr to retval -> x0
6c: e1 03 09 2a mov w1, w9 ; @@@ unsure
70: e8 17 00 f9 str x8, [sp, #40] ; ptr to retval -> local area as temp copy
dyncall/doc/disas_examples/arm64.aapcs.disas view on Meta::CPAN
94: 48 01 00 f9 str x8, [x10] ; | i
98: eb 0f 40 f9 ldr x11, [sp, #24] ; | | j
9c: 4b 05 00 f9 str x11, [x10, #8] ; | /
a0: ec 0b 40 f9 ldr x12, [sp, #16] ; | write retval data \ k
a4: 4c 09 00 f9 str x12, [x10, #16] ; | /
a8: ed 07 40 f9 ldr x13, [sp, #8] ; | \ l
ac: 4d 0d 00 f9 str x13, [x10, #24] ; | /
b0: ee 03 40 f9 ldr x14, [sp] ; | \ m
b4: 4e 11 00 f9 str x14, [x10, #32] ; / /
b8: fe 1b 40 f9 ldr x30, [sp, #48] ; \
bc: ff 03 01 91 add sp, sp, #64 ; | epilog
c0: c0 03 5f d6 ret ; |
00000000000000c4 main:
c4: ff 43 01 d1 sub sp, sp, #80 ;
c8: fd 7b 04 a9 stp x29, x30, [sp, #64] ;
cc: fd 03 01 91 add x29, sp, #64 ;
d0: a8 17 00 d1 sub x8, x29, #5 ;
d4: e9 43 00 91 add x9, sp, #16 ;
d8: bf c3 1f b8 stur wzr, [x29, #-4] ;
dc: e8 07 00 f9 str x8, [sp, #8] ;
dyncall/doc/disas_examples/mips.eabi.disas view on Meta::CPAN
24: afca0018 sw t2,24(s8)
28: 03c0e821 move sp,s8
2c: 8fbe0024 lw s8,36(sp)
30: 27bd0028 addiu sp,sp,40
34: 03e00008 jr ra
38: 00000000 nop
0000003c <nonleaf_call>:
3c: 27bdffd8 addiu sp,sp,-40 ; |
40: afbf0024 sw ra,36(sp) ; |
44: afbe0020 sw s8,32(sp) ; | prolog
48: 03a0f021 move s8,sp ; / frame pointer (note: with offset to frame start, but static compared to sp)
4c: afc40000 sw a0,0(s8) ; \
50: afc50004 sw a1,4(s8) ; |
54: afc60008 sw a2,8(s8) ; |
58: afc7000c sw a3,12(s8) ; |
5c: afc80010 sw t0,16(s8) ; | in args 0,1,2,3,4,5,6,7 -> temp space in local area
60: afc90014 sw t1,20(s8) ; |
64: afca0018 sw t2,24(s8) ; |
68: afcb001c sw t3,28(s8) ; |
6c: 27bdff18 addiu sp,sp,-232 ; alloca(220) - with padding to guarantee alignment
dyncall/doc/disas_examples/mips.eabi.disas view on Meta::CPAN
94: 8fc6000c lw a2,12(s8) ; |
98: 8fc70010 lw a3,16(s8) ; | arg 0,1,2,3,4,5,6 (fetched from local area stored to above)
9c: 8fc80014 lw t0,20(s8) ; | (t0 = a4)
a0: 8fc90018 lw t1,24(s8) ; | (t1 = a5)
a4: 8fca001c lw t2,28(s8) ; | (t2 = a6)
a8: 0c000000 jal 0 <leaf_call> ; call and ret addr -> ra
ac: 00000000 nop ; branch delay slot
b0: 03c0e821 move sp,s8 ; |
b4: 8fbf0024 lw ra,36(sp) ; |
b8: 8fbe0020 lw s8,32(sp) ; |
bc: 27bd0028 addiu sp,sp,40 ; | epilog
c0: 03e00008 jr ra ; |
c4: 00000000 nop ; | branch delay slot
000000c8 <main>:
c8: 27bdfff8 addiu sp,sp,-8 ; |
cc: afbf0004 sw ra,4(sp) ; |
d0: afbe0000 sw s8,0(sp) ; | prolog
d4: 03a0f021 move s8,sp ; | frame pointer (note: with offset to frame start, but static compared to sp)
d8: 00002021 move a0,zero ; arg 0
dc: 24050001 li a1,1 ; arg 1
e0: 24060002 li a2,2 ; arg 2
e4: 24070003 li a3,3 ; arg 3
e8: 24080004 li t0,4 ; arg 4 (t0 = a4)
ec: 24090005 li t1,5 ; arg 5 (t1 = a5)
f0: 240a0006 li t2,6 ; arg 6 (t2 = a6)
f4: 240b0007 li t3,7 ; arg 7 (t3 = a7)
f8: 0c000000 jal 0 <leaf_call> ; call and ret addr -> ra
fc: 00000000 nop ; branch delay slot
100: 00001021 move v0,zero ; return value
104: 03c0e821 move sp,s8 ; |
108: 8fbf0004 lw ra,4(sp) ; |
10c: 8fbe0000 lw s8,0(sp) ; |
110: 27bd0008 addiu sp,sp,8 ; | epilog
114: 03e00008 jr ra ; |
118: 00000000 nop ; | branch delay slot
; ------------- as above but more args to use stack params ----------->
; #include <stdlib.h>
;
; void leaf_call(int b, int c, int d, int e, int f, int g, int h, int i, int j)
dyncall/doc/disas_examples/mips.eabi.disas view on Meta::CPAN
28: afcb001c sw t3,28(s8)
2c: 03c0e821 move sp,s8
30: 8fbe0024 lw s8,36(sp)
34: 27bd0028 addiu sp,sp,40
38: 03e00008 jr ra
3c: 00000000 nop
00000040 <nonleaf_call>:
40: 27bdffd0 addiu sp,sp,-48 ; |
44: afbf002c sw ra,44(sp) ; |
48: afbe0028 sw s8,40(sp) ; | prolog
4c: 03a0f021 move s8,sp ; / frame pointer (note: with offset to frame start, but static compared to sp)
50: afc40008 sw a0,8(s8) ; \
54: afc5000c sw a1,12(s8) ; |
58: afc60010 sw a2,16(s8) ; |
5c: afc70014 sw a3,20(s8) ; |
60: afc80018 sw t0,24(s8) ; | in args 0,1,2,3,4,5,6,7 -> temp space in local area
64: afc9001c sw t1,28(s8) ; |
68: afca0020 sw t2,32(s8) ; |
6c: afcb0024 sw t3,36(s8) ; |
70: 27bdff18 addiu sp,sp,-232 ; alloca(220) - with padding to guarantee alignment
dyncall/doc/disas_examples/mips.eabi.disas view on Meta::CPAN
a4: 8fc70018 lw a3,24(s8) ; | arg 0,1,2,3,4,5,6 (fetched from local area stored to above)
a8: 8fc8001c lw t0,28(s8) ; | (t0 = a4)
ac: 8fc90020 lw t1,32(s8) ; | (t1 = a5)
b0: 8fca0024 lw t2,36(s8) ; | (t2 = a6)
b4: 8fcb0030 lw t3,48(s8) ; | (t3 = a7)
b8: 0c000000 jal 0 <leaf_call> ; call and ret addr -> ra
bc: 00000000 nop ; branch delay slot
c0: 03c0e821 move sp,s8 ; |
c4: 8fbf002c lw ra,44(sp) ; |
c8: 8fbe0028 lw s8,40(sp) ; |
cc: 27bd0030 addiu sp,sp,48 ; | epilog
d0: 03e00008 jr ra ; |
d4: 00000000 nop ; | branch delay slot
000000d8 <main>:
d8: 27bdfff0 addiu sp,sp,-16 ; |
dc: afbf000c sw ra,12(sp) ; |
e0: afbe0008 sw s8,8(sp) ; | prolog
e4: 03a0f021 move s8,sp ; | frame pointer (note: with offset to frame start, but static compared to sp)
e8: 24020008 li v0,8 ; arg 8
ec: afa20000 sw v0,0(sp) ; ... "pushed" onto stack
f0: 24020009 li v0,9 ; arg 9
f4: afa20004 sw v0,4(sp) ; ... "pushed" onto stack
f8: 00002021 move a0,zero ; arg 0
fc: 24050001 li a1,1 ; arg 1
100: 24060002 li a2,2 ; arg 2
104: 24070003 li a3,3 ; arg 3
108: 24080004 li t0,4 ; arg 4 (t0 = a4)
10c: 24090005 li t1,5 ; arg 5 (t1 = a5)
110: 240a0006 li t2,6 ; arg 6 (t2 = a6)
114: 240b0007 li t3,7 ; arg 7 (t3 = a7)
118: 0c000000 jal 0 <leaf_call> ; call and ret addr -> ra
11c: 00000000 nop ; branch delay slot
120: 00001021 move v0,zero ; return value
124: 03c0e821 move sp,s8 ; |
128: 8fbf000c lw ra,12(sp) ; |
12c: 8fbe0008 lw s8,8(sp) ; |
130: 27bd0010 addiu sp,sp,16 ; | epilog
134: 03e00008 jr ra ; |
138: 00000000 nop ; | branch delay slot
; ------------- with var args to see spilling ----------->
; #include <stdlib.h>
; #include <stdarg.h>
;
dyncall/doc/disas_examples/mips.eabi.disas view on Meta::CPAN
28: afcb001c sw t3,28(s8)
2c: 03c0e821 move sp,s8
30: 8fbe0024 lw s8,36(sp)
34: 27bd0028 addiu sp,sp,40
38: 03e00008 jr ra
3c: 00000000 nop
00000040 <nonleaf_call>:
40: 27bdffa0 addiu sp,sp,-96 ; | leaving 32b extra space adjacent to prev frame's param area for spilling
44: afbf003c sw ra,60(sp) ; |
48: afbe0038 sw s8,56(sp) ; | prolog
4c: 03a0f021 move s8,sp ; / frame pointer (note: with offset to frame start, but static compared to sp)
50: afc50044 sw a1,68(s8) ; \
54: afc60048 sw a2,72(s8) ; |
58: afc7004c sw a3,76(s8) ; |
5c: afc80050 sw t0,80(s8) ; | in args 1,2,3,4,5,6,7 -> spill area in current frame (adjacent to prev frame's param area)
60: afc90054 sw t1,84(s8) ; |
64: afca0058 sw t2,88(s8) ; |
68: afcb005c sw t3,92(s8) ; |
6c: afc40030 sw a0,48(s8) ; in arg 0 -> temp space in local area
70: 27c20060 addiu v0,s8,96 ; v0 initialized to point ...
dyncall/doc/disas_examples/mips.eabi.disas view on Meta::CPAN
164: 8fc70014 lw a3,20(s8) ; | arg 0,1,2,3,4,5,6 (fetched from local area stored to above)
168: 8fc80018 lw t0,24(s8) ; | (t0 = a4)
16c: 8fc9001c lw t1,28(s8) ; | (t1 = a5)
170: 8fca0020 lw t2,32(s8) ; | (t2 = a6)
174: 8fcb0024 lw t3,36(s8) ; | (t3 = a7)
178: 0c000000 jal 0 <leaf_call> ; call and ret addr -> ra
17c: 00000000 nop ; branch delay slot
180: 03c0e821 move sp,s8 ; |
184: 8fbf003c lw ra,60(sp) ; |
188: 8fbe0038 lw s8,56(sp) ; |
18c: 27bd0060 addiu sp,sp,96 ; | epilog
190: 03e00008 jr ra ; |
194: 00000000 nop | branch delay slot
00000198 <main>:
198: 27bdfff0 addiu sp,sp,-16 ; |
19c: afbf000c sw ra,12(sp) ; |
1a0: afbe0008 sw s8,8(sp) ; | prolog
1a4: 03a0f021 move s8,sp ; | frame pointer (note: with offset to frame start, but static compared to sp)
1a8: 24020008 li v0,8 ; arg 8
1ac: afa20000 sw v0,0(sp) ; ... "pushed" onto stack
1b0: 24020009 li v0,9 ; arg 9
1b4: afa20004 sw v0,4(sp) ; ... "pushed" onto stack
1b8: 00002021 move a0,zero ; arg 0
1bc: 24050001 li a1,1 ; arg 1
1c0: 24060002 li a2,2 ; arg 2
1c4: 24070003 li a3,3 ; arg 3
1c8: 24080004 li t0,4 ; arg 4 (t0 = a4)
1cc: 24090005 li t1,5 ; arg 5 (t1 = a5)
1d0: 240a0006 li t2,6 ; arg 6 (t2 = a6)
1d4: 240b0007 li t3,7 ; arg 7 (t3 = a7)
1d8: 0c000000 jal 0 <leaf_call> ; call and ret addr -> ra
1dc: 00000000 nop ; branch delay slot
1e0: 00001021 move v0,zero ; return value
1e4: 03c0e821 move sp,s8 ; |
1e8: 8fbf000c lw ra,12(sp) ; |
1ec: 8fbe0008 lw s8,8(sp) ; |
1f0: 27bd0010 addiu sp,sp,16 ; | epilog
1f4: 03e00008 jr ra ; |
1f8: 00000000 nop ; | branch delay slot
; ------------- var args with ints and floats to see spilling (which remains only a?-a7 regs), b/c doubles are passed via them and floats are promoted to doubles in (...) ----------->
; #include <stdlib.h>
; #include <stdarg.h>
;
dyncall/doc/disas_examples/mips.eabi.disas view on Meta::CPAN
2c: e7ce0020 swc1 $f14,32(s8)
30: 03c0e821 move sp,s8
34: 8fbe002c lw s8,44(sp)
38: 27bd0030 addiu sp,sp,48
3c: 03e00008 jr ra
40: 00000000 nop
00000044 <nonleaf_call>:
44: 27bdffa8 addiu sp,sp,-88 ; | leaving 32b extra space adjacent to prev frame's param area for spilling
48: afbf0034 sw ra,52(sp) ; |
4c: afbe0030 sw s8,48(sp) ; | prolog
50: 03a0f021 move s8,sp ; / frame pointer (note: with offset to frame start, but static compared to sp)
54: afc5003c sw a1,60(s8) ; \
58: afc60040 sw a2,64(s8) ; |
5c: afc70044 sw a3,68(s8) ; |
60: afc80048 sw t0,72(s8) ; | in args 1,2,3,4,5 (spread out over 7 param regs) -> spill area in current frame (adjacent to prev frame's param area)
64: afc9004c sw t1,76(s8) ; | this one is just padding
68: afca0050 sw t2,80(s8) ; | |
6c: afcb0054 sw t3,84(s8) ; | | this is arg 5, passed as a double, spilled like integers
70: afc40028 sw a0,40(s8) ; in arg 0 -> temp space in local area
74: 27c20058 addiu v0,s8,88 ; v0 initialized to point ...
dyncall/doc/disas_examples/mips.eabi.disas view on Meta::CPAN
1c4: c7cc0010 lwc1 $f12,16(s8) ; arg 4 (float, fetched from local area stored to above)
1c8: c7cd0014 lwc1 $f13,20(s8) ; arg 5 (float, fetched from local area stored to above)
1cc: 8fc80018 lw t0,24(s8) ; arg 6 (int, fetched from local area stored to above, t0 = a4)
1d0: 8fc9001c lw t1,28(s8) ; arg 7 (int, fetched from local area stored to above, t1 = a5)
1d4: c7ce0020 lwc1 $f14,32(s8) ; arg 9 (float, fetched from local area stored to above)
1d8: 0c000000 jal 0 <leaf_call> ; call and ret addr -> ra
1dc: 00000000 nop ; branch delay slot
1e0: 03c0e821 move sp,s8 ; |
1e4: 8fbf0034 lw ra,52(sp) ; |
1e8: 8fbe0030 lw s8,48(sp) ; |
1ec: 27bd0058 addiu sp,sp,88 ; | epilog
1f0: 03e00008 jr ra ; |
1f4: 00000000 nop ; | branch delay slot
000001f8 <main>:
1f8: 27bdffe0 addiu sp,sp,-32 ; |
1fc: afbf001c sw ra,28(sp) ; |
200: afbe0018 sw s8,24(sp) ; | prolog
204: 03a0f021 move s8,sp ; / frame pointer (note: with offset to frame start, but static compared to sp)
208: 8f8a0000 lw t2,0(gp) ; \
20c: 8f8b0004 lw t3,4(gp) ; / arg 5 (t1,t2 = a4,a5), as double b/c of vararg, effectively skipping t1 (=a5)
210: 8f820008 lw v0,8(gp) ; \
214: 8f83000c lw v1,12(gp) ; | arg 6, as double b/c of vararg, via v0 and v1 ...
218: afa20000 sw v0,0(sp) ; |
21c: afa30004 sw v1,4(sp) ; | ... "pushed" onto stack
220: 24020007 li v0,7 ; arg 7
224: afa20008 sw v0,8(sp) ; ... "pushed" onto stack
228: 24020008 li v0,8 ; arg 8
dyncall/doc/disas_examples/mips.eabi.disas view on Meta::CPAN
244: 24050001 li a1,1 ; arg 1
248: 24060002 li a2,2 ; arg 2
24c: 24070003 li a3,3 ; arg 3
250: 24080004 li t0,4 ; arg 4 (t0 = a4)
254: 0c000000 jal 0 <leaf_call> ; call and ret addr -> ra
258: 00000000 nop ; branch delay slot
25c: 00001021 move v0,zero ; return value
260: 03c0e821 move sp,s8 ; |
264: 8fbf001c lw ra,28(sp) ; |
268: 8fbe0018 lw s8,24(sp) ; |
26c: 27bd0020 addiu sp,sp,32 ; | epilog
270: 03e00008 jr ra ; |
274: 00000000 nop ; | branch delay slot
; --------------------- further notes ------------------->
; when passing less arguments than stack params, involving an ellipsis, spill area still spills all registers,
; excluding named ones, e.g.:
;
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
24: afc70014 sw a3,20(s8)
28: 03c0e821 move sp,s8
2c: 8fbe0000 lw s8,0(sp)
30: 03e00008 jr ra
34: 27bd0008 addiu sp,sp,8
00000038 <nonleaf_call>:
38: 3c1c0000 lui gp,0x0 ; |
3c: 279c0000 addiu gp,gp,0 ; |
40: 0399e021 addu gp,gp,t9 ; |
44: 27bdffc8 addiu sp,sp,-56 ; | prolog
48: afbf0034 sw ra,52(sp) ; |
4c: afbe0030 sw s8,48(sp) ; |
50: 03a0f021 move s8,sp ; | frame pointer (note: with offset to frame start, but static compared to sp)
54: afbc0020 sw gp,32(sp) ; /
58: afc40038 sw a0,56(s8) ; \
5c: afc5003c sw a1,60(s8) ; |
60: afc60040 sw a2,64(s8) ; | spill first 4 args into prev frame's reserved spill space in param area (although not actually needing to spill, here but just do a temp copy, but space is reserved for them anyways)
64: afc70044 sw a3,68(s8) ; |
68: 27bdff18 addiu sp,sp,-232 ; alloca(220) - with padding to guarantee alignment
6c: 27a20020 addiu v0,sp,32 ; |
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
ac: 8fc4003c lw a0,60(s8) ; arg 0 (fetched from spill area of prev frame)
b0: 8fc50040 lw a1,64(s8) ; arg 1 (fetched from spill area of prev frame)
b4: 8fc60044 lw a2,68(s8) ; arg 2 (fetched from spill area of prev frame)
b8: 8fc70048 lw a3,72(s8) ; arg 3 (fetched from prev frame's param area)
bc: 8f990000 lw t9,0(gp) ; func to call -> t9
c0: 0320f809 jalr t9 ; call and ret addr -> ra
c4: 00000000 nop ; branch delay slot
c8: 8fdc0020 lw gp,32(s8) ; |
cc: 03c0e821 move sp,s8 ; |
d0: 8fbf0034 lw ra,52(sp) ; |
d4: 8fbe0030 lw s8,48(sp) ; | epilog
d8: 03e00008 jr ra ; |
dc: 27bd0038 addiu sp,sp,56 ; |
000000e0 <main>:
e0: 3c1c0000 lui gp,0x0 ; |
e4: 279c0000 addiu gp,gp,0 ; |
e8: 0399e021 addu gp,gp,t9 ; |
ec: 27bdffd0 addiu sp,sp,-48 ; | prolog
f0: afbf002c sw ra,44(sp) ; |
f4: afbe0028 sw s8,40(sp) ; |
f8: 03a0f021 move s8,sp ; | frame pointer (note: with offset to frame start, but static compared to sp)
fc: afbc0020 sw gp,32(sp) ; |
100: 24020004 li v0,4 ; arg 4, and ...
104: afa20010 sw v0,16(sp) ; ... "pushed" onto stack
108: 24020005 li v0,5 ; arg 5, and ...
10c: afa20014 sw v0,20(sp) ; ... "pushed" onto stack
110: 24020006 li v0,6 ; arg 6, and ...
114: afa20018 sw v0,24(sp) ; ... "pushed" onto stack
118: 24020007 li v0,7 ; arg 7, and ...
11c: afa2001c sw v0,28(sp) ; ... "pushed" onto stack
120: 00002021 move a0,zero ; arg 0
124: 24050001 li a1,1 ; arg 1
128: 24060002 li a2,2 ; arg 2
12c: 24070003 li a3,3 ; arg 3
130: 8f990000 lw t9,0(gp) ; func to call -> t9
134: 0320f809 jalr t9 ; call and ret addr -> ra
138: 00000000 nop ; branch delay slot
13c: 8fdc0020 lw gp,32(s8) ; |
140: 00001021 move v0,zero ; : return value: not part of epilog, but unordered (branch delay slot style)
144: 03c0e821 move sp,s8 ; |
148: 8fbf002c lw ra,44(sp) ; | epilog
14c: 8fbe0028 lw s8,40(sp) ; |
150: 03e00008 jr ra ; |
154: 27bd0030 addiu sp,sp,48 ; |
; output from netbsd-5.0.2-pmax_mipsel_o32 w/ gcc 4.1.3 ----->
; nearly the same, equivalent to above except non-optimal use of branch delay slots and $gp preserving in leaf call
00000000 <leaf_call>:
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
e4: 03c0e821 move sp,s8
e8: 8fbf009c lw ra,156(sp)
ec: 8fbe0098 lw s8,152(sp)
f0: 03e00008 jr ra
f4: 27bd00a0 addiu sp,sp,160
000000f8 <main>:
f8: 3c1c0000 lui gp,0x0 ; |
fc: 279c0000 addiu gp,gp,0 ; |
100: 0399e021 addu gp,gp,t9 ; |
104: 27bdffb0 addiu sp,sp,-80 ; | prolog
108: afbf004c sw ra,76(sp) ; |
10c: afbe0048 sw s8,72(sp) ; |
110: 03a0f021 move s8,sp ; | frame pointer (note: with offset to frame start, but static compared to sp)
114: afbc0030 sw gp,48(sp) ; /
118: 8f820000 lw v0,0(gp) ; \ \
11c: 24420000 addiu v0,v0,0 ; | | field j -> v0
120: 8c420000 lw v0,0(v0) ; | /
124: 8f830000 lw v1,0(gp) ; | \
128: 24630000 addiu v1,v1,0 ; | | field j -> v1
12c: 8c630004 lw v1,4(v1) ; | prep local struct A data ... /
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
188: 24020009 li v0,9 ; push arg 7 ...
18c: afa2002c sw v0,44(sp) ; ... onto stack
190: 00002021 move a0,zero ; arg 0
194: 24050001 li a1,1 ; arg 1
198: 24060002 li a2,2 ; arg 2
19c: 24070003 li a3,3 ; arg 3
1a0: 8f990000 lw t9,0(gp) ; func to call -> t9
1a4: 0320f809 jalr t9 ; call and ret addr -> ra
1a8: 00000000 nop ; branch delay slot
1ac: 8fdc0030 lw gp,48(s8) ; |
1b0: 00001021 move v0,zero ; : return value: not part of epilog, but unordered (branch delay slot style)
1b4: 03c0e821 move sp,s8 ; |
1b8: 8fbf004c lw ra,76(sp) ; | epilog
1bc: 8fbe0048 lw s8,72(sp) ; |
1c0: 03e00008 jr ra ; |
1c4: 27bd0050 addiu sp,sp,80 ; |
...
; output from freebsd-12.0_r333647-malta_mipsebhf w/ gcc 4.2.1 *and* -mhard-float ----->
00000000 <leaf_call>:
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
e4: 03c0e821 move sp,s8
e8: 8fbf009c lw ra,156(sp)
ec: 8fbe0098 lw s8,152(sp)
f0: 03e00008 jr ra
f4: 27bd00a0 addiu sp,sp,160
000000f8 <main>:
f8: 3c1c0000 lui gp,0x0 ; |
fc: 279c0000 addiu gp,gp,0 ; |
100: 0399e021 addu gp,gp,t9 ; |
104: 27bdffb0 addiu sp,sp,-80 ; | prolog
108: afbf004c sw ra,76(sp) ; |
10c: afbe0048 sw s8,72(sp) ; |
110: 03a0f021 move s8,sp ; | frame pointer (note: with offset to frame start, but static compared to sp)
114: afbc0030 sw gp,48(sp) ; /
118: 8f820000 lw v0,0(gp) ; \ \
11c: 24420000 addiu v0,v0,0 ; | | field j -> v0
120: 8c420000 lw v0,0(v0) ; | /
124: 8f830000 lw v1,0(gp) ; | \
128: 24630000 addiu v1,v1,0 ; | | field j -> v1
12c: 8c630004 lw v1,4(v1) ; | prep local struct A data ... /
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
188: 24020009 li v0,9 ; push arg 7 ...
18c: afa2002c sw v0,44(sp) ; ... onto stack
190: 00002021 move a0,zero ; arg 0
194: 24050001 li a1,1 ; arg 1
198: 24060002 li a2,2 ; arg 2
19c: 24070003 li a3,3 ; arg 3
1a0: 8f990000 lw t9,0(gp) ; func to call -> t9
1a4: 0320f809 jalr t9 ; call and ret addr -> ra
1a8: 00000000 nop ; branch delay slot
1ac: 8fdc0030 lw gp,48(s8) ; |
1b0: 00001021 move v0,zero ; : return value: not part of epilog, but unordered (branch delay slot style)
1b4: 03c0e821 move sp,s8 ; |
1b8: 8fbf004c lw ra,76(sp) ; | epilog
1bc: 8fbe0048 lw s8,72(sp) ; |
1c0: 03e00008 jr ra ; |
1c4: 27bd0050 addiu sp,sp,80 ; |
...
; ---------- structs by value, complex example (multiple structs) ---------->
;
; struct A { int i, j; float f; };
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
12c: 03c0e821 move sp,s8
130: 8fbf00c4 lw ra,196(sp)
134: 8fbe00c0 lw s8,192(sp)
138: 03e00008 jr ra
13c: 27bd00c8 addiu sp,sp,200
00000140 <main>:
140: 3c1c0000 lui gp,0x0 ; |
144: 279c0000 addiu gp,gp,0 ; |
148: 0399e021 addu gp,gp,t9 ; |
14c: 27bdff58 addiu sp,sp,-168 ; | prolog
150: afbf00a4 sw ra,164(sp) ; |
154: afbe00a0 sw s8,160(sp) ; |
158: 03a0f021 move s8,sp ; | frame pointer (note: with offset to frame start, but static compared to sp)
15c: afbc0058 sw gp,88(sp) ; /
160: 8f820000 lw v0,0(gp) ; \ |
164: 24420030 addiu v0,v0,48 ; | | field j -> v0
168: 8c420000 lw v0,0(v0) ; | /
16c: 8f830000 lw v1,0(gp) ; | prep (first) local struct A data ... \
170: 24630030 addiu v1,v1,48 ; | | field j -> v1
174: 8c630004 lw v1,4(v1) ; | /
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
2b8: 8fc20098 lw v0,152(s8) ; | | f (via stack, first slot after save area)
2bc: afa20010 sw v0,16(sp) ; | | note that 20(sp) isn't used, so sizeof(struct A) is probably a padded 16
2c0: 8fc60090 lw a2,144(s8) ; | arg 2 (first struct A) i (via reg)
2c4: 8fc70094 lw a3,148(s8) ; | j (via reg)
2c8: 00002021 move a0,zero ; arg 0
2cc: 24050001 li a1,1 ; arg 1
2d0: 8f990000 lw t9,0(gp) ; func to call -> t9
2d4: 0320f809 jalr t9 ; call and ret addr -> ra
2d8: 00000000 nop ; branch delay slot
2dc: 8fdc0058 lw gp,88(s8) ; |
2e0: 00001021 move v0,zero ; : return value: not part of epilog, but unordered (branch delay slot style)
2e4: 03c0e821 move sp,s8 ; |
2e8: 8fbf00a4 lw ra,164(sp) ; | epilog
2ec: 8fbe00a0 lw s8,160(sp) ; |
2f0: 03e00008 jr ra ; |
2f4: 27bd00a8 addiu sp,sp,168 ; |
...
; output from freebsd-12.0_r333647-malta_mipsebhf w/ gcc 4.2.1 *and* -mhard-float ----->
00000000 <leaf_call>:
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
12c: 03c0e821 move sp,s8
130: 8fbf00c4 lw ra,196(sp)
134: 8fbe00c0 lw s8,192(sp)
138: 03e00008 jr ra
13c: 27bd00c8 addiu sp,sp,200
00000140 <main>:
140: 3c1c0000 lui gp,0x0 ; |
144: 279c0000 addiu gp,gp,0 ; |
148: 0399e021 addu gp,gp,t9 ; |
14c: 27bdff58 addiu sp,sp,-168 ; | prolog
150: afbf00a4 sw ra,164(sp) ; |
154: afbe00a0 sw s8,160(sp) ; |
158: 03a0f021 move s8,sp ; | frame pointer (note: with offset to frame start, but static compared to sp)
15c: afbc0058 sw gp,88(sp) ; /
160: 8f820000 lw v0,0(gp) ; \ |
164: 24420030 addiu v0,v0,48 ; | | field j -> v0
168: 8c420000 lw v0,0(v0) ; | /
16c: 8f830000 lw v1,0(gp) ; | prep (first) local struct A data ... \
170: 24630030 addiu v1,v1,48 ; | | field j -> v1
174: 8c630004 lw v1,4(v1) ; | /
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
2b8: 8fc20098 lw v0,152(s8) ; | | f (via stack, first slot after save area)
2bc: afa20010 sw v0,16(sp) ; | | note that 20(sp) isn't used, so sizeof(struct A) is probably a padded 16
2c0: 8fc60090 lw a2,144(s8) ; | arg 2 (first struct A) i (via reg)
2c4: 8fc70094 lw a3,148(s8) ; | j (via reg)
2c8: 00002021 move a0,zero ; arg 0
2cc: 24050001 li a1,1 ; arg 1
2d0: 8f990000 lw t9,0(gp) ; func to call -> t9
2d4: 0320f809 jalr t9 ; call and ret addr -> ra
2d8: 00000000 nop ; branch delay slot
2dc: 8fdc0058 lw gp,88(s8) ; |
2e0: 00001021 move v0,zero ; : return value: not part of epilog, but unordered (branch delay slot style)
2e4: 03c0e821 move sp,s8 ; |
2e8: 8fbf00a4 lw ra,164(sp) ; | epilog
2ec: 8fbe00a0 lw s8,160(sp) ; |
2f0: 03e00008 jr ra ; |
2f4: 27bd00a8 addiu sp,sp,168 ; |
...
; ---------- returning structs by value ---------->
;
; struct Small { char x; };
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
; return b.j + b.k + b.m + s.x;
; }
; output from freebsd-12.0_r333647-malta_mipsebhf w/ gcc 4.2.1 ----->
00000000 <f0>:
0: 3c1c0000 lui gp,0x0 ; |
4: 279c0000 addiu gp,gp,0 ; |
8: 0399e021 addu gp,gp,t9 ; | prolog
c: 27bdffe8 addiu sp,sp,-24 ; |
10: afbe0010 sw s8,16(sp) ; |
14: 03a0f021 move s8,sp ; |
18: 00801021 move v0,a0 ; hidden first arg (ptr to struct ret) -> v0
1c: 2403ff84 li v1,-124 ; | put together local struct
20: a3c30008 sb v1,8(s8) ; /
24: 93c30008 lbu v1,8(s8) ; read struct data from local area ...
28: a0430000 sb v1,0(v0) ; ... and write to return value area
2c: 03c0e821 move sp,s8 ; \
30: 8fbe0010 lw s8,16(sp) ; |
34: 03e00008 jr ra ; | epilog
38: 27bd0018 addiu sp,sp,24 ; |
0000003c <f1>:
3c: 3c1c0000 lui gp,0x0 ; |
40: 279c0000 addiu gp,gp,0 ; |
44: 0399e021 addu gp,gp,t9 ; |
48: 27bdffb0 addiu sp,sp,-80 ; |
4c: afbf0048 sw ra,72(sp) ; | prolog
50: afbe0044 sw s8,68(sp) ; |
54: afb00040 sw s0,64(sp) ; |
58: 03a0f021 move s8,sp ; |
5c: afbc0010 sw gp,16(sp) ; |
60: 00808021 move s0,a0 ; hidden first arg (ptr to struct ret) -> s0
64: 27c20018 addiu v0,s8,24 ;
68: 8f830000 lw v1,0(gp) ;
6c: 24630000 addiu v1,v1,0 ;
70: 24060028 li a2,40 ;
74: 00402021 move a0,v0 ;
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
88: 8fdc0010 lw gp,16(s8) ;
8c: 02001021 move v0,s0 ;
90: 27c30018 addiu v1,s8,24 ;
94: 24060028 li a2,40 ;
98: 00402021 move a0,v0 ;
9c: 00602821 move a1,v1 ;
a0: 8f990000 lw t9,0(gp) ;
a4: 0320f809 jalr t9 ;
a8: 00000000 nop ;
ac: 8fdc0010 lw gp,16(s8) ; |
b0: 02001021 move v0,s0 ; : return value (hidden ptr): not part of epilog, but unordered (branch delay slot style)
b4: 03c0e821 move sp,s8 ; |
b8: 8fbf0048 lw ra,72(sp) ; |
bc: 8fbe0044 lw s8,68(sp) ; | epilog
c0: 8fb00040 lw s0,64(sp) ; |
c4: 03e00008 jr ra ; |
c8: 27bd0050 addiu sp,sp,80 ; |
000000cc <main>:
cc: 3c1c0000 lui gp,0x0 ; |
d0: 279c0000 addiu gp,gp,0 ; |
d4: 0399e021 addu gp,gp,t9 ; |
d8: 27bdffb0 addiu sp,sp,-80 ; |
dc: afbf004c sw ra,76(sp) ; | prolog
e0: afbe0048 sw s8,72(sp) ; |
e4: 03a0f021 move s8,sp ; |
e8: afbc0010 sw gp,16(sp) ; /
ec: 27c20018 addiu v0,s8,24 ; \
f0: 00402021 move a0,v0 ; | hidden first arg (ptr to space for ret val)
f4: 8f990000 lw t9,0(gp) ; func to call (f0) -> t9
f8: 0320f809 jalr t9 ; call and ret addr -> ra
fc: 00000000 nop ; branch delay slot
100: 8fdc0010 lw gp,16(s8) ; restore gp @@@ unsure why?
104: 27c20020 addiu v0,s8,32 ; |
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
128: 8fc30034 lw v1,52(s8) ; | |
12c: 8fc20030 lw v0,48(s8) ; | | b.j -> v0 & v1
130: 00601021 move v0,v1 ; | return value v0 = (int)b.k
134: 00821821 addu v1,a0,v0 ; | (int)b.j + (int)b.k -> v1
138: 8fc20040 lw v0,64(s8) ; | b.m -> v0
13c: 00621821 addu v1,v1,v0 ; | ((int)b.j + (int)b.k) + b.m -> v1
140: 83c20018 lb v0,24(s8) ; | s.x -> v0
144: 00621021 addu v0,v1,v0 ; / (((int)b.j + (int)b.k) + b.m) + s.x -> v0
148: 03c0e821 move sp,s8 ; \
14c: 8fbf004c lw ra,76(sp) ; |
150: 8fbe0048 lw s8,72(sp) ; | epilog
154: 03e00008 jr ra ; |
158: 27bd0050 addiu sp,sp,80 ; |
15c: 00000000 nop ; |
; output from freebsd-12.0_r333647-malta_mipsebhf w/ gcc 4.2.1 *and* -mhard-float ----->
00000000 <f0>:
0: 3c1c0000 lui gp,0x0
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
24: afc70014 sw a3,20(s8)
28: 03c0e821 move sp,s8
2c: 8fbe0000 lw s8,0(sp)
30: 03e00008 jr ra
34: 27bd0008 addiu sp,sp,8
00000038 <main>:
38: 3c1c0000 lui gp,0x0 ; |
3c: 279c0000 addiu gp,gp,0 ; |
40: 0399e021 addu gp,gp,t9 ; |
44: 27bdff60 addiu sp,sp,-160 ; | prolog
48: afbf009c sw ra,156(sp) ; |
4c: afbe0098 sw s8,152(sp) ; |
50: 03a0f021 move s8,sp ; | frame pointer (note: with offset to frame start, but static compared to sp)
54: afbc0048 sw gp,72(sp) ; /
58: 8f820000 lw v0,0(gp) ; \
5c: 24420044 addiu v0,v0,68 ; | prep local struct A data ...
60: 8c420000 lw v0,0(v0) ; /
64: afc20094 sw v0,148(s8) ; ... and write to local area
68: 8f820000 lw v0,0(gp) ; \
6c: 2442003c addiu v0,v0,60 ; |
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
1e0: afa20010 sw v0,16(sp) ; | arg 2 (struct C) b (via stack)
1e4: afa30014 sw v1,20(sp) ; | c (via stack)
1e8: 8fc70080 lw a3,128(s8) ; | a (via reg)
1ec: 8fc40094 lw a0,148(s8) ; arg 0 (struct A, via reg)
1f0: 8fc5008c lw a1,140(s8) ; | arg 1 (struct B, via regs) a
1f4: 8fc60090 lw a2,144(s8) ; | b
1f8: 8f990000 lw t9,0(gp) ; func to call -> t9
1fc: 0320f809 jalr t9 ; call and ret addr -> ra
200: 00000000 nop ; branch delay slot
204: 8fdc0048 lw gp,72(s8) ; |
208: 00001021 move v0,zero ; : return value: not part of epilog, but unordered (branch delay slot style)
20c: 03c0e821 move sp,s8 ; |
210: 8fbf009c lw ra,156(sp) ; | epilog
214: 8fbe0098 lw s8,152(sp) ; |
218: 03e00008 jr ra ; |
21c: 27bd00a0 addiu sp,sp,160 ; |
; output from freebsd-12.0_r333647-malta_mipsebhf w/ gcc 4.2.1 *and* -mhard-float ----->
00000000 <leaf_call>:
0: 3c1c0000 lui gp,0x0
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
24: afc70014 sw a3,20(s8)
28: 03c0e821 move sp,s8
2c: 8fbe0000 lw s8,0(sp)
30: 03e00008 jr ra
34: 27bd0008 addiu sp,sp,8
00000038 <main>:
38: 3c1c0000 lui gp,0x0 ; |
3c: 279c0000 addiu gp,gp,0 ; |
40: 0399e021 addu gp,gp,t9 ; |
44: 27bdff60 addiu sp,sp,-160 ; | prolog
48: afbf009c sw ra,156(sp) ; |
4c: afbe0098 sw s8,152(sp) ; |
50: 03a0f021 move s8,sp ; | frame pointer (note: with offset to frame start, but static compared to sp)
54: afbc0048 sw gp,72(sp) ; /
58: 8f810000 lw at,0(gp) ; \
5c: 24210044 addiu at,at,68 ; | prep local struct A (single float field) data ...
60: c4200000 lwc1 $f0,0(at) ; /
64: e7c00094 swc1 $f0,148(s8) ; ... and write to local area
68: 8f820000 lw v0,0(gp) ; \
6c: 2442003c addiu v0,v0,60 ; |
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
1c8: afa20010 sw v0,16(sp) ; | arg 2 (struct C) b (via stack)
1cc: afa30014 sw v1,20(sp) ; | c (via stack)
1d0: 8fc70080 lw a3,128(s8) ; | a (via reg)
1d4: 8fc40094 lw a0,148(s8) ; arg 0 (struct A, via reg)
1d8: 8fc5008c lw a1,140(s8) ; | arg 1 (struct B, via regs) a
1dc: 8fc60090 lw a2,144(s8) ; | b
1e0: 8f990000 lw t9,0(gp) ; func to call -> t9
1e4: 0320f809 jalr t9 ; call and ret addr -> ra
1e8: 00000000 nop ; branch delay slot
1ec: 8fdc0048 lw gp,72(s8) ; |
1f0: 00001021 move v0,zero ; : return value: not part of epilog, but unordered (branch delay slot style)
1f4: 03c0e821 move sp,s8 ; |
1f8: 8fbf009c lw ra,156(sp) ; | epilog
1fc: 8fbe0098 lw s8,152(sp) ; |
200: 03e00008 jr ra ; |
204: 27bd00a0 addiu sp,sp,160 ; |
...
; ---------- single-field structs by values (and small array fields) ---------->
;
; struct C { char c; };
dyncall/doc/disas_examples/mips.o32.disas view on Meta::CPAN
4008cc: ac400000 sw zero,0(v0) ; return val
4008d0: 03c0e821 move sp,s8
4008d4: 8fbe0000 lw s8,0(sp)
4008d8: 03e00008 jr ra
4008dc: 27bd0008 addiu sp,sp,8
004008e0 <_Z2f2v>:
4008e0: 3c1c0002 lui gp,0x2 ; |
4008e4: 279c82e0 addiu gp,gp,-32032 ; |
4008e8: 0399e021 addu gp,gp,t9 ; |
4008ec: 27bdffd8 addiu sp,sp,-40 ; | prolog
4008f0: afbf0020 sw ra,32(sp) ; |
4008f4: afbe001c sw s8,28(sp) ; |
4008f8: afb00018 sw s0,24(sp) ; |
4008fc: 03a0f021 move s8,sp ; | frame pointer (note: with offset to frame start, but static compared to sp)
400900: afbc0010 sw gp,16(sp) ;
400904: 00808021 move s0,a0 ;
400908: 02001021 move v0,s0 ;
40090c: 00402021 move a0,v0 ;
400910: 8f998060 lw t9,-32672(gp) ;
400914: 0320f809 jalr t9 ;
400918: 00000000 nop ;
40091c: 8fdc0010 lw gp,16(s8) ;
400920: 02001021 move v0,s0 ; ptr to retval space -> v0
400924: 03c0e821 move sp,s8 ; |
400928: 8fbf0020 lw ra,32(sp) ; |
40092c: 8fbe001c lw s8,28(sp) ; |
400930: 8fb00018 lw s0,24(sp) ; | epilog
400934: 03e00008 jr ra ; |
400938: 27bd0028 addiu sp,sp,40 ; |
0040093c <f>:
40093c: 3c1c0002 lui gp,0x2 ;
400940: 279c8284 addiu gp,gp,-32124 ;
400944: 0399e021 addu gp,gp,t9 ;
400948: 27bdffd0 addiu sp,sp,-48 ;
40094c: afbf002c sw ra,44(sp) ;
400950: afbe0028 sw s8,40(sp) ;
dyncall/doc/disas_examples/mips64.n64.disas view on Meta::CPAN
70: 03c0e82d move sp,s8
74: dfbe0028 ld s8,40(sp)
78: dfbc0020 ld gp,32(sp)
7c: 03e00008 jr ra
80: 67bd0030 daddiu sp,sp,48
84: 00000000 nop
0000000000000088 <nonleaf_call>:
88: 67bdff90 daddiu sp,sp,-112 ; |
8c: ffbf0060 sd ra,96(sp) ; |
90: ffbe0058 sd s8,88(sp) ; | prolog
94: ffbc0050 sd gp,80(sp) ; |
98: 03a0f02d move s8,sp ; |
9c: 3c1c0000 lui gp,0x0 ; @@@ unsure
a0: 0399e02d daddu gp,gp,t9 ; @@@ unsure
a4: 679c0000 daddiu gp,gp,0 ; @@@ unsure
a8: 0080102d move v0,a0 ; |
ac: 00a0182d move v1,a1 ; |
b0: 00c0202d move a0,a2 ; | pointlessly (?) moving a{0,1} to v{0,1} respectively,
b4: 00e0282d move a1,a3 ; | and all last 6 a? registers two regs down, freeing up
b8: 0100302d move a2,a4 ; | a{6,7}, which aren't used for anything though
dyncall/doc/disas_examples/mips64.n64.disas view on Meta::CPAN
144: 8fc90018 lw a5,24(s8) ; arg 5
148: 8fca001c lw a6,28(s8) ; arg 6
14c: 0040202d move a0,v0 ; arg 0
150: 0060282d move a1,v1 ; arg 1
154: df990000 ld t9,0(gp) ; addr of callee -> t9
158: 0320f809 jalr t9 ; return address -> ra, and call
15c: 00000000 nop ; branch delay slot
160: 03c0e82d move sp,s8 ; |
164: dfbf0060 ld ra,96(sp) ; |
168: dfbe0058 ld s8,88(sp) ; |
16c: dfbc0050 ld gp,80(sp) ; | epilog
170: 03e00008 jr ra ; |
174: 67bd0070 daddiu sp,sp,112 ; | branch delay slot style
0000000000000178 <main>:
178: 67bdffe0 daddiu sp,sp,-32 ; |
17c: ffbf0010 sd ra,16(sp) ; |
180: ffbe0008 sd s8,8(sp) ; | prolog
184: ffbc0000 sd gp,0(sp) ; |
188: 03a0f02d move s8,sp ; |
18c: 3c1c0000 lui gp,0x0 ; @@@ unsure
190: 0399e02d daddu gp,gp,t9 ; @@@ unsure
194: 679c0000 daddiu gp,gp,0 ; @@@ unsure
198: 0000202d move a0,zero ; arg 0
19c: 24050001 li a1,1 ; arg 1
1a0: 24060002 li a2,2 ; arg 2
1a4: 24070003 li a3,3 ; arg 3
1a8: 24080004 li a4,4 ; arg 4
1ac: 24090005 li a5,5 ; arg 5
1b0: 240a0006 li a6,6 ; arg 6
1b4: 240b0007 li a7,7 ; arg 7
1b8: df990000 ld t9,0(gp) ; address of callee -> t9
1bc: 0320f809 jalr t9 ; return address -> ra, and call
1c0: 00000000 nop ; branch delay slot
1c4: 0000102d move v0,zero ; return value
1c8: 03c0e82d move sp,s8 ; |
1cc: dfbf0010 ld ra,16(sp) ; |
1d0: dfbe0008 ld s8,8(sp) ; |
1d4: dfbc0000 ld gp,0(sp) ; | epilog
1d8: 03e00008 jr ra ; |
1dc: 67bd0020 daddiu sp,sp,32 ; | branch delay slot style
; output from debian-sid_20150616-malta_mips64el_n64 w/ gcc 4.9.2
0000000000000000 <leaf_call>:
0: 67bdffd0 daddiu sp,sp,-48
4: ffbe0028 sd s8,40(sp)
dyncall/doc/disas_examples/mips64.n64.disas view on Meta::CPAN
58: afc20018 sw v0,24(s8)
5c: 03c0e82d move sp,s8
60: dfbe0028 ld s8,40(sp)
64: 67bd0030 daddiu sp,sp,48
68: 03e00008 jr ra
6c: 00200825 move at,at
0000000000000070 <nonleaf_call>:
70: 67bdffc0 daddiu sp,sp,-64 ; |
74: ffbf0038 sd ra,56(sp) ; |
78: ffbe0030 sd s8,48(sp) ; | prolog
7c: ffbc0028 sd gp,40(sp) ; |
80: 03a0f02d move s8,sp ; |
84: 3c1c0000 lui gp,0x0 ; @@@ unsure
88: 0399e02d daddu gp,gp,t9 ; @@@ unsure
8c: 679c0000 daddiu gp,gp,0 ; @@@ unsure
90: 0080702d move t2,a0 ; |
94: 00a0682d move t1,a1 ; |
98: 00c0602d move t0,a2 ; | pointlessly (?) moving regs around, freeing effectively
9c: 00e0302d move a2,a3 ; | some registers for use below, still unnecessary though
a0: 0100282d move a1,a4 ; | with different code below
dyncall/doc/disas_examples/mips64.n64.disas view on Meta::CPAN
128: 8fc2001c lw v0,28(s8) ; prep arg 5 (pointlessly) to move to a5 below
12c: 0060482d move a5,v1 ; arg 5
130: 0040502d move a6,v0 ; arg 6
134: df820000 ld v0,0(gp) ; addr of callee ...
138: 0040c82d move t9,v0 ; ... -> t9
13c: 0320f809 jalr t9 ; return address -> ra, and call
140: 00200825 move at,at ; branch delay slot (effectively nop)
144: 03c0e82d move sp,s8 ; |
148: dfbf0038 ld ra,56(sp) ; |
14c: dfbe0030 ld s8,48(sp) ; |
150: dfbc0028 ld gp,40(sp) ; | epilog
154: 67bd0040 daddiu sp,sp,64 ; |
158: 03e00008 jr ra ; |
15c: 00200825 move at,at ; | branch delay slot (effectively nop)
0000000000000160 <main>:
160: 67bdffe0 daddiu sp,sp,-32 ; |
164: ffbf0018 sd ra,24(sp) ; |
168: ffbe0010 sd s8,16(sp) ; | prolog
16c: ffbc0008 sd gp,8(sp) ; |
170: 03a0f02d move s8,sp ; |
174: 3c1c0000 lui gp,0x0 ; @@@ unsure
178: 0399e02d daddu gp,gp,t9 ; @@@ unsure
17c: 679c0000 daddiu gp,gp,0 ; @@@ unsure
180: 0000202d move a0,zero ; arg 0
184: 24050001 li a1,1 ; arg 1
188: 24060002 li a2,2 ; arg 2
18c: 24070003 li a3,3 ; arg 3
190: 24080004 li a4,4 ; arg 4
dyncall/doc/disas_examples/mips64.n64.disas view on Meta::CPAN
198: 240a0006 li a6,6 ; arg 6
19c: 240b0007 li a7,7 ; arg 7
1a0: df820000 ld v0,0(gp) ; address of callee, to ...
1a4: 0040c82d move t9,v0 ; ... t9
1a8: 0320f809 jalr t9 ; return address -> ra, and call
1ac: 00200825 move at,at ; branch delay slot (effectively nop)
1b0: 0000102d move v0,zero ; return value
1b4: 03c0e82d move sp,s8 ; |
1b8: dfbf0018 ld ra,24(sp) ; |
1bc: dfbe0010 ld s8,16(sp) ; |
1c0: dfbc0008 ld gp,8(sp) ; | epilog
1c4: 67bd0020 daddiu sp,sp,32 ; |
1c8: 03e00008 jr ra ; |
1cc: 00200825 move at,at ; | branch delay slot (effectively nop)
; ------------- var args with ints and floats to see spilling (which remains only a?-a7 regs), b/c doubles are passed via them and floats are promoted to doubles in (...) ----------->
; #include <stdlib.h>
; #include <stdarg.h>
dyncall/doc/disas_examples/mips64.n64.disas view on Meta::CPAN
58: afc2001c sw v0,28(s8)
5c: 03c0e82d move sp,s8
60: dfbe0028 ld s8,40(sp)
64: 67bd0030 daddiu sp,sp,48
68: 03e00008 jr ra
6c: 00200825 move at,at
0000000000000070 <nonleaf_call>:
70: 67bdff50 daddiu sp,sp,-176 ; | leaving 64b extra space adjacent to prev frame's param area for spilling
74: ffbf0068 sd ra,104(sp) ; |
78: ffbe0060 sd s8,96(sp) ; | prolog
7c: ffbc0058 sd gp,88(sp) ; |
80: 03a0f02d move s8,sp ; |
84: 3c1c0000 lui gp,0x0 ; @@@ unsure
88: 0399e02d daddu gp,gp,t9 ; @@@ unsure
8c: 679c0000 daddiu gp,gp,0 ; @@@ unsure
90: ffc50078 sd a1,120(s8) ; |
94: ffc60080 sd a2,128(s8) ; |
98: ffc70088 sd a3,136(s8) ; |
9c: ffc80090 sd a4,144(s8) ; | in args 1,2,3,4,5,6,7 -> spill area in current frame (adjacent to prev frame's param area)
a0: ffc90098 sd a5,152(s8) ; |
dyncall/doc/disas_examples/mips64.n64.disas view on Meta::CPAN
1e0: c7d10024 lwc1 $f17,36(s8) ; arg 5 (so skipping f12-f15)
1e4: 0100502d move a6,a4 ; arg 6 (from a4 used as temp reg, pointlessly)
1e8: 0060582d move a7,v1 ; arg 7
1ec: df820000 ld v0,0(gp) ; address of callee, to ...
1f0: 0040c82d move t9,v0 ; ... t9
1f4: 0320f809 jalr t9 ; return address -> ra, and call
1f8: 00200825 move at,at ; branch delay slot (effectively nop)
1fc: 03c0e82d move sp,s8 ; |
200: dfbf0068 ld ra,104(sp) ; |
204: dfbe0060 ld s8,96(sp) ; |
208: dfbc0058 ld gp,88(sp) ; | epilog
20c: 67bd00b0 daddiu sp,sp,176 ; |
210: 03e00008 jr ra ; |
214: 00200825 move at,at ; | branch delay slot (effectively nop)
0000000000000218 <main>:
218: 67bdffd0 daddiu sp,sp,-48 ; |
21c: ffbf0028 sd ra,40(sp) ; |
220: ffbe0020 sd s8,32(sp) ; | prolog
224: ffbc0018 sd gp,24(sp) ; |
228: 03a0f02d move s8,sp ; |
22c: 3c1c0000 lui gp,0x0 ; unsure@@@
230: 0399e02d daddu gp,gp,t9 ; unsure@@@
234: 679c0000 daddiu gp,gp,0 ; unsure@@@
238: df820000 ld v0,0(gp) ; arg 6 (float promoted to double), from static data (0 b/c objdmp is from .o, not final linked exec), ...
23c: d4410000 ldc1 $f1,0(v0) ; ... to f1
240: df820000 ld v0,0(gp) ; arg 5 (float promoted to double), from static data (0 b/c objdmp is from .o, not final linked exec), ...
244: d4400000 ldc1 $f0,0(v0) ; ... to f0
248: 24020008 li v0,8 ; arg 8, ...
dyncall/doc/disas_examples/mips64.n64.disas view on Meta::CPAN
274: 442a0000 dmfc1 a6,$f0 ; arg 6 (note: passed in a6 b/c vararg)
278: 240b0007 li a7,7 ; arg 7
27c: df820000 ld v0,0(gp) ; address of callee, to ...
280: 0040c82d move t9,v0 ; ... t9
284: 0320f809 jalr t9 ; return address -> ra, and call
288: 00200825 move at,at ; branch delay slot (effectively nop)
28c: 03c0e82d move sp,s8 ; |
290: dfbf0028 ld ra,40(sp) ; |
294: dfbe0020 ld s8,32(sp) ; |
298: dfbc0018 ld gp,24(sp) ; |
29c: 67bd0030 daddiu sp,sp,48 ; | epilog
2a0: 03e00008 jr ra ; |
2a4: 00200825 move at,at ; | branch delay slot (effectively nop)
2a8: 00200825 move at,at ; | ? @@@
2ac: 00200825 move at,at ; | ? @@@
; ---------- simple float arg (uses fp regs on hard-float) ---------->
;
; float f(float f) { return f; }
dyncall/doc/disas_examples/ppc.darwin.disas view on Meta::CPAN
1c: 90 fe 00 58 stw 7, 88(30)
20: 91 1e 00 5c stw 8, 92(30)
24: 91 3e 00 60 stw 9, 96(30)
28: 80 21 00 00 lwz 1, 0(1)
2c: bb c1 ff f8 lmw 30, -8(1)
30: 4e 80 00 20 blr
_nonleaf_call:
34: 7c 08 02 a6 mflr 0 ; | lr -> gpr0
38: bf c1 ff f8 stmw 30, -8(1) ; | store gpr{30,31}
3c: 90 01 00 08 stw 0, 8(1) ; | prolog store lr
40: 94 21 ff b0 stwu 1, -80(1) ; | open frame and store sp at top of stack
44: 7c 3e 0b 78 mr 30, 1 ; / sp -> gpr30, latter used for some fixed addressing below
48: 90 7e 00 68 stw 3, 104(30) ; \
4c: 90 9e 00 6c stw 4, 108(30) ; |
50: 90 be 00 70 stw 5, 112(30) ; |
54: 90 de 00 74 stw 6, 116(30) ; |
58: 90 fe 00 78 stw 7, 120(30) ; | all in args -> spill area in prev frame
5c: 91 1e 00 7c stw 8, 124(30) ; |
60: 91 3e 00 80 stw 9, 128(30) ; |
64: 91 5e 00 84 stw 10, 132(30) ; |
68: 80 01 00 00 lwz 0, 0(1) ; fetch back-chain ptr (parent frame's sp) from stack of top by prolog -> gpr0, and ...
6c: 94 01 ff 10 stwu 0, -240(1) ; ... update it further up the stack for alloca(220) - with padding to guarantee alignment
70: 38 41 00 40 addi 2, 1, 64 ; |
74: 38 02 00 0f addi 0, 2, 15 ; | start of alloca()'d memory -> gpr2, by ...
78: 54 00 e1 3e srwi 0, 0, 4 ; | ... using gpr0 as helper to align to 16b, leaving at least 64b at top of stack
7c: 54 02 20 36 slwi 2, 0, 4 ; |
80: 38 00 00 4c li 0, 76 ; 'L' -> gpr0, and ...
84: 98 02 00 00 stb 0, 0(2) ; ... store in local area (of alloca()'d space)
88: 80 7e 00 6c lwz 3, 108(30) ; |
8c: 80 9e 00 70 lwz 4, 112(30) ; |
90: 80 be 00 74 lwz 5, 116(30) ; |
94: 80 de 00 78 lwz 6, 120(30) ; | arg 0,1,2,3,4,5,6 (fetched from spill area from prev frame)
98: 80 fe 00 7c lwz 7, 124(30) ; |
9c: 81 1e 00 80 lwz 8, 128(30) ; |
a0: 81 3e 00 84 lwz 9, 132(30) ; |
a4: 4b ff ff 5d bl .+67108700 ; call and put return address -> lr
a8: 80 21 00 00 lwz 1, 0(1) ; |
ac: 80 01 00 08 lwz 0, 8(1) ; |
b0: 7c 08 03 a6 mtlr 0 ; | epilog
b4: bb c1 ff f8 lmw 30, -8(1) ; |
b8: 4e 80 00 20 blr ; |
_main:
bc: 7c 08 02 a6 mflr 0 ; |
c0: bf c1 ff f8 stmw 30, -8(1) ; |
c4: 90 01 00 08 stw 0, 8(1) ; | prolog
c8: 94 21 ff b0 stwu 1, -80(1) ; |
cc: 7c 3e 0b 78 mr 30, 1 ; |
d0: 38 60 00 00 li 3, 0 ; arg 0
d4: 38 80 00 01 li 4, 1 ; arg 1
d8: 38 a0 00 02 li 5, 2 ; arg 2
dc: 38 c0 00 03 li 6, 3 ; arg 3
e0: 38 e0 00 04 li 7, 4 ; arg 4
e4: 39 00 00 05 li 8, 5 ; arg 5
e8: 39 20 00 06 li 9, 6 ; arg 6
ec: 39 40 00 07 li 10, 7 ; arg 7
f0: 4b ff ff 45 bl .+67108676 ; call and put return address -> lr
f4: 38 00 00 00 li 0, 0 ; return value (pointlessly) via gpr0 ...
f8: 7c 03 03 78 mr 3, 0 ; ... to gpr3
fc: 80 21 00 00 lwz 1, 0(1) ; |
100: 80 01 00 08 lwz 0, 8(1) ; |
104: 7c 08 03 a6 mtlr 0 ; | epilog
108: bb c1 ff f8 lmw 30, -8(1) ; |
10c: 4e 80 00 20 blr ; |
; ------------- more than 8 int args ----------->
; #include <stdlib.h>
;
; void leaf_call(int b, int c, int d, int e, int f, int g, int h, int i, int j)
dyncall/doc/disas_examples/ppc.darwin.disas view on Meta::CPAN
20: 91 1e 00 5c stw 8, 92(30)
24: 91 3e 00 60 stw 9, 96(30)
28: 91 5e 00 64 stw 10, 100(30)
2c: 80 21 00 00 lwz 1, 0(1)
30: bb c1 ff f8 lmw 30, -8(1)
34: 4e 80 00 20 blr
_nonleaf_call:
38: 7c 08 02 a6 mflr 0 ; |
3c: bf c1 ff f8 stmw 30, -8(1) ; |
40: 90 01 00 08 stw 0, 8(1) ; | prolog
44: 94 21 ff a0 stwu 1, -96(1) ; |
48: 7c 3e 0b 78 mr 30, 1 ; /
4c: 90 7e 00 78 stw 3, 120(30) ; \
50: 90 9e 00 7c stw 4, 124(30) ; |
54: 90 be 00 80 stw 5, 128(30) ; |
58: 90 de 00 84 stw 6, 132(30) ; |
5c: 90 fe 00 88 stw 7, 136(30) ; | in args 0,1,2,3,4,5,6,7 -> spill area in prev frame
60: 91 1e 00 8c stw 8, 140(30) ; |
64: 91 3e 00 90 stw 9, 144(30) ; |
68: 91 5e 00 94 stw 10, 148(30) ; |
6c: 80 01 00 00 lwz 0, 0(1) ; fetch back-chain ptr (parent frame's sp) from stack of top by prolog -> gpr0, and ...
70: 94 01 ff 10 stwu 0, -240(1) ; ... update it further up the stack for alloca(220) - with padding to guarantee alignment
74: 38 41 00 50 addi 2, 1, 80 ; |
78: 38 02 00 0f addi 0, 2, 15 ; | start of alloca()'d memory -> gpr2, by ...
7c: 54 00 e1 3e srwi 0, 0, 4 ; | ... using gpr0 as helper to align to 16b, leaving at least 64b at top of stack
80: 54 02 20 36 slwi 2, 0, 4 ; |
84: 38 00 00 4c li 0, 76 ; 'L' -> gpr0, and ...
88: 98 02 00 00 stb 0, 0(2) ; ... store in local area (of alloca()'d space)
8c: 80 1e 00 9c lwz 0, 156(30) ; arg 7 (fetched from stack param area from prev frame), and ...
90: 90 01 00 38 stw 0, 56(1) ; ... "pushed" onto stack
94: 80 7e 00 7c lwz 3, 124(30) ; |
98: 80 9e 00 80 lwz 4, 128(30) ; |
9c: 80 be 00 84 lwz 5, 132(30) ; |
a0: 80 de 00 88 lwz 6, 136(30) ; | arg 0,1,2,3,4,5,6 (fetched from spill area from prev frame)
a4: 80 fe 00 8c lwz 7, 140(30) ; |
a8: 81 1e 00 90 lwz 8, 144(30) ; |
ac: 81 3e 00 94 lwz 9, 148(30) ; |
b0: 81 5e 00 98 lwz 10, 152(30) ; arg 7 (fetched from stack param area from prev frame)
b4: 4b ff ff 4d bl .+67108684 ; call and put return address -> lr
b8: 80 21 00 00 lwz 1, 0(1) ; |
bc: 80 01 00 08 lwz 0, 8(1) ; |
c0: 7c 08 03 a6 mtlr 0 ; | epilog
c4: bb c1 ff f8 lmw 30, -8(1) ; |
c8: 4e 80 00 20 blr ; |
_main:
cc: 7c 08 02 a6 mflr 0 ; |
d0: bf c1 ff f8 stmw 30, -8(1) ; |
d4: 90 01 00 08 stw 0, 8(1) ; | prolog
d8: 94 21 ff a0 stwu 1, -96(1) ; |
dc: 7c 3e 0b 78 mr 30, 1 ; |
e0: 38 00 00 08 li 0, 8 ; arg 8, ...
e4: 90 01 00 38 stw 0, 56(1) ; ... "pushed" onto stack
e8: 38 00 00 09 li 0, 9 ; arg 9, ...
ec: 90 01 00 3c stw 0, 60(1) ; ... "pushed" onto stack
f0: 38 60 00 00 li 3, 0 ; arg 0
f4: 38 80 00 01 li 4, 1 ; arg 1
f8: 38 a0 00 02 li 5, 2 ; arg 2
fc: 38 c0 00 03 li 6, 3 ; arg 3
100: 38 e0 00 04 li 7, 4 ; arg 4
104: 39 00 00 05 li 8, 5 ; arg 5
108: 39 20 00 06 li 9, 6 ; arg 6
10c: 39 40 00 07 li 10, 7 ; arg 7
110: 4b ff ff 29 bl .+67108648 ; call and put return address -> lr
114: 38 00 00 00 li 0, 0 ; return value (pointlessly) via gpr0 ...
118: 7c 03 03 78 mr 3, 0 ; ... to gpr3
11c: 80 21 00 00 lwz 1, 0(1) ; |
120: 80 01 00 08 lwz 0, 8(1) ; |
124: 7c 08 03 a6 mtlr 0 ; | epilog
128: bb c1 ff f8 lmw 30, -8(1) ; |
12c: 4e 80 00 20 blr ; |
; ------------- var args with ints and floats to see spilling (which remains only int regs), b/c doubles are passed via them and floats are promoted to doubles in (...) ----------->
; #include <stdlib.h>
; #include <stdarg.h>
;
dyncall/doc/disas_examples/ppc.darwin.disas view on Meta::CPAN
24: 91 3e 00 60 stw 9, 96(30)
28: 91 5e 00 64 stw 10, 100(30)
2c: d0 7e 00 68 stfs 3, 104(30)
30: 80 21 00 00 lwz 1, 0(1)
34: bb c1 ff f8 lmw 30, -8(1)
38: 4e 80 00 20 blr
_nonleaf_call:
3c: 7c 08 02 a6 mflr 0 ; |
40: bf c1 ff f8 stmw 30, -8(1) ; |
44: 90 01 00 08 stw 0, 8(1) ; | prolog
48: 94 21 ff 70 stwu 1, -144(1) ; |
4c: 7c 3e 0b 78 mr 30, 1 ; /
50: 90 9e 00 ac stw 4, 172(30) ; \
54: 90 be 00 b0 stw 5, 176(30) ; |
58: 90 de 00 b4 stw 6, 180(30) ; |
5c: 90 fe 00 b8 stw 7, 184(30) ; |
60: 91 1e 00 bc stw 8, 188(30) ; | in args ,1,2,3,4,5,6,7 -> spill area in prev frame
64: 91 3e 00 c0 stw 9, 192(30) ; |
68: 91 5e 00 c4 stw 10, 196(30) ; |
6c: 90 7e 00 a8 stw 3, 168(30) ; | <- this is in arg 0, the only named arg
dyncall/doc/disas_examples/ppc.darwin.disas view on Meta::CPAN
134: 90 1e 00 74 stw 0, 116(30) ; | in arg 8
138: 80 09 00 00 lwz 0, 0(9) ; |
13c: 90 1e 00 64 stw 0, 100(30) ; /
140: 81 3e 00 74 lwz 9, 116(30) ; \
144: 80 5e 00 74 lwz 2, 116(30) ; |
148: 38 02 00 08 addi 0, 2, 8 ; |
14c: 90 1e 00 74 stw 0, 116(30) ; | in arg 9 (float, promoted to double)
150: c8 09 00 00 lfd 0, 0(9) ; |
154: fc 00 00 18 frsp 0, 0 ; |
158: d0 1e 00 70 stfs 0, 112(30) ; /
15c: 80 01 00 00 lwz 0, 0(1) ; fetch back-chain ptr (parent frame's sp) from stack of top by prolog -> gpr0, and ...
160: 94 01 ff 10 stwu 0, -240(1) ; ... update it further up the stack for alloca
164: 38 41 00 50 addi 2, 1, 80 ; |
168: 38 02 00 0f addi 0, 2, 15 ; | start of alloca()'d memory -> gpr2, by ...
16c: 54 00 e1 3e srwi 0, 0, 4 ; | ... using gpr0 as helper to align to 16b, l
170: 54 02 20 36 slwi 2, 0, 4 ; |
174: 38 00 00 4c li 0, 76 ; 'L' -> gpr0, and ...
178: 98 02 00 00 stb 0, 0(2) ; ... store in local area (of alloca()'d space)
17c: 80 7e 00 50 lwz 3, 80(30) ; arg 0
180: 80 9e 00 54 lwz 4, 84(30) ; arg 1
184: 80 be 00 58 lwz 5, 88(30) ; arg 2
188: 80 de 00 5c lwz 6, 92(30) ; arg 3
18c: c0 3e 00 68 lfs 1, 104(30) ; arg 4 (float)
190: c0 5e 00 6c lfs 2, 108(30) ; arg 5 (float)
194: 81 3e 00 60 lwz 9, 96(30) ; arg 6
198: 81 5e 00 64 lwz 10, 100(30) ; arg 7
19c: c0 7e 00 70 lfs 3, 112(30) ; arg 8 (float)
1a0: 4b ff fe 61 bl .+67108448 ; call and put return address -> lr
1a4: 80 21 00 00 lwz 1, 0(1) ; |
1a8: 80 01 00 08 lwz 0, 8(1) ; |
1ac: 7c 08 03 a6 mtlr 0 ; | epilog
1b0: bb c1 ff f8 lmw 30, -8(1) ; |
1b4: 4e 80 00 20 blr ; |
_main:
1b8: 7c 08 02 a6 mflr 0 ; |
1bc: bf c1 ff f8 stmw 30, -8(1) ; |
1c0: 90 01 00 08 stw 0, 8(1) ; | prolog
1c4: 94 21 ff 90 stwu 1, -112(1) ; |
1c8: 7c 3e 0b 78 mr 30, 1 ; |
1cc: 42 9f 00 05 bcl 20, 31, .+4 ; ppc way to get PC in ...
1d0: 7f e8 02 a6 mflr 31 ; ... gpr31
1d4: 38 00 00 07 li 0, 7 ; arg 7, ...
1d8: 90 01 00 3c stw 0, 60(1) ; ... "pushed" onto stack
1dc: 38 00 00 08 li 0, 8 ; arg 8, ...
1e0: 90 01 00 40 stw 0, 64(1) ; ... "pushed" onto stack
1e4: 3c 40 40 22 lis 2, 16418 ; | arg 9, top-half (double b/c of vararg), and ...
1e8: 38 60 00 00 li 3, 0 ; | ... bottom-half ...
dyncall/doc/disas_examples/ppc.darwin.disas view on Meta::CPAN
234: 3c 5f 00 00 addis 2, 31, 0 ; PC -> gpr2, to ...
238: c8 02 00 a0 lfd 0, 160(2) ; ... load some static data (arg 6, the 2nd float) stored right after this function -> gpr0
23c: 7d 6a 5b 78 mr 10, 11 ; arg 6, top-half
240: fc 40 00 90 fmr 2, 0 ; arg 5 in 2nd fp reg
244: c8 01 00 44 lfd 0, 68(1) ; arg 9, ...
248: fc 60 00 90 fmr 3, 0 ; ... -> 3rd fp reg
24c: 4b ff fd f1 bl .+67108336 ; call and put return address -> lr
250: 7c 03 03 78 mr 3, 0 ; return value @@@unsure why gpr0 is guaranteed to be 0 here
254: 80 21 00 00 lwz 1, 0(1) ; |
258: 80 01 00 08 lwz 0, 8(1) ; |
25c: 7c 08 03 a6 mtlr 0 ; | epilog
260: bb c1 ff f8 lmw 30, -8(1) ; |
264: 4e 80 00 20 blr ; |
; ---------- 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)
dyncall/doc/disas_examples/ppc.darwin.disas view on Meta::CPAN
00000144 li r3,0x0 ; arg 0
00000148 li r4,0x1 ; arg 1
0000014c li r5,0x2 ; arg 2
00000150 li r6,0x3 ; arg 3
00000154 li r7,0x4 ; arg 4
00000158 bl 0x38 ; call and put return address -> lr
0000015c li r0,0x0 ; return value (pointlessly) via gpr0 ...
00000160 or r3,r0,r0 ; ... to gpr3
00000164 lwz r1,0x0(r1) ; |
00000168 lwz r0,0x8(r1) ; |
0000016c mtspr lr,r0 ; | epilog
00000170 lmw r30,0xfff8(r1) ; |
00000174 blr ; |
; ---------- single-field structs by value (of different sizes) ---------->
;
; struct C { char c; }; // <= 2 bytes, but normal alignment as passed like a char
; struct S { short s; }; // <= 2 bytes, but normal alignment as passed like a short
; struct I { int i; };
dyncall/doc/disas_examples/ppc.darwin.disas view on Meta::CPAN
00000014 sth r5,0x60(r30)
00000018 stw r6,0x64(r30)
0000001c stfs f1,0x68(r30)
00000020 stfd f2,0x20(r30)
00000024 lwz r1,0x0(r1)
00000028 lmw r30,0xfff8(r1)
0000002c blr
_main:
00000030 mfspr r0,lr ; |
00000034 stmw r30,0xfff8(r1) ; |
00000038 stw r0,0x8(r1) ; | prolog
0000003c stwu r1,0xff80(r1) ; |
00000040 or r30,r1,r1 ; |
00000044 bcl 20,31,0x48 ; ppc way to get PC in ...
00000048 mfspr r31,lr ; ... gpr31
0000004c li r0,0x0 ; | \
00000050 stb r0,0x40(r30) ; | |
00000054 li r0,0x1 ; | | C2
00000058 stb r0,0x41(r30) ; | /
0000005c li r0,0x2 ; | local area struct init \ C
00000060 stb r0,0x42(r30) ; | /
dyncall/doc/disas_examples/ppc.darwin.disas view on Meta::CPAN
000000bc lhz r5,0x44(r30) ; arg 2 (struct S)
000000c0 lwz r6,0x48(r30) ; arg 3 (struct I)
000000c4 lfs f1,0x4c(r30) ; arg 4 (struct F, int arg reg r7 then skipped)
000000c8 lfd f2,0x50(r30) ; arg 5 (struct D, int arg regs r8 and r9 then skipped)
000000cc lwz r10,0x34(r1) ; arg 6 (struct C3, fetched from local area)
000000d0 bl 0x0 ; call and put return address -> lr
000000d4 li r0,0x0 ; return value (pointlessly) via gpr0 ...
000000d8 or r3,r0,r0 ; ... to gpr3
000000dc lwz r1,0x0(r1) ; |
000000e0 lwz r0,0x8(r1) ; |
000000e4 mtspr lr,r0 ; | epilog
000000e8 lmw r30,0xfff8(r1) ; |
000000ec blr ; |
; ---------- structs by value, complex example (multiple structs) ---------->
;
; struct A { int i, j; float f; };
; struct B { double d; long long l; };
;
dyncall/doc/disas_examples/ppc.sysv.disas view on Meta::CPAN
20: 91 1f 00 1c stw r8,28(r31)
24: 91 3f 00 20 stw r9,32(r31)
28: 81 61 00 00 lwz r11,0(r1)
2c: 83 eb ff fc lwz r31,-4(r11)
30: 7d 61 5b 78 mr r1,r11
34: 4e 80 00 20 blr
00000038 <nonleaf_call>:
38: 94 21 ff c0 stwu r1,-64(r1) ; | open frame and store sp at top of stack
3c: 7c 08 02 a6 mflr r0 ; | lr -> gpr0
40: 93 e1 00 3c stw r31,60(r1) ; | prolog store gpr31
44: 90 01 00 44 stw r0,68(r1) ; | store lr
48: 7c 3f 0b 78 mr r31,r1 ; / sp -> gpr31, latter used for some fixed addressing below
4c: 90 7f 00 08 stw r3,8(r31) ; \
50: 90 9f 00 0c stw r4,12(r31) ; |
54: 90 bf 00 10 stw r5,16(r31) ; |
58: 90 df 00 14 stw r6,20(r31) ; |
5c: 90 ff 00 18 stw r7,24(r31) ; | all in args -> temp space in local area
60: 91 1f 00 1c stw r8,28(r31) ; |
64: 91 3f 00 20 stw r9,32(r31) ; |
68: 91 5f 00 24 stw r10,36(r31) ; |
6c: 80 01 00 00 lwz r0,0(r1) ; fetch sp saved on stack of top by prolog -> gpr0, and ...
70: 94 01 ff 10 stwu r0,-240(r1) ; ... update it further up the stack for alloca(220) - with padding to guarantee alignment
74: 39 21 00 08 addi r9,r1,8 ; |
78: 91 3f 00 28 stw r9,40(r31) ; |
7c: 81 3f 00 28 lwz r9,40(r31) ; |
80: 38 09 00 0f addi r0,r9,15 ; | start of alloca()'d memory -> gpr9, by ...
84: 54 00 e1 3e rlwinm r0,r0,28,4,31 ; | ... using gpr0 as helper to align to 16b, leaving at least 8b at top of stock
88: 54 00 20 36 rlwinm r0,r0,4,0,27 ; |
8c: 90 1f 00 28 stw r0,40(r31) ; |
90: 81 3f 00 28 lwz r9,40(r31) ; |
94: 38 00 00 4c li r0,76 ; 'L' -> gpr0, and ...
dyncall/doc/disas_examples/ppc.sysv.disas view on Meta::CPAN
a0: 80 9f 00 10 lwz r4,16(r31) ; arg 1
a4: 80 bf 00 14 lwz r5,20(r31) ; arg 2
a8: 80 df 00 18 lwz r6,24(r31) ; arg 3
ac: 80 ff 00 1c lwz r7,28(r31) ; arg 4
b0: 81 1f 00 20 lwz r8,32(r31) ; arg 5
b4: 81 3f 00 24 lwz r9,36(r31) ; arg 6
b8: 48 00 00 01 bl b8 <nonleaf_call+0x80> ; call and put return address -> lr
bc: 81 61 00 00 lwz r11,0(r1) ; |
c0: 80 0b 00 04 lwz r0,4(r11) ; |
c4: 7c 08 03 a6 mtlr r0 ; |
c8: 83 eb ff fc lwz r31,-4(r11) ; | epilog
cc: 7d 61 5b 78 mr r1,r11 ; |
d0: 4e 80 00 20 blr ; |
000000d4 <main>:
d4: 94 21 ff f0 stwu r1,-16(r1) ; |
d8: 7c 08 02 a6 mflr r0 ; |
dc: 93 e1 00 0c stw r31,12(r1) ; | prolog
e0: 90 01 00 14 stw r0,20(r1) ; |
e4: 7c 3f 0b 78 mr r31,r1 ; |
e8: 38 60 00 00 li r3,0 ; arg 0
ec: 38 80 00 01 li r4,1 ; arg 1
f0: 38 a0 00 02 li r5,2 ; arg 2
f4: 38 c0 00 03 li r6,3 ; arg 3
f8: 38 e0 00 04 li r7,4 ; arg 4
fc: 39 00 00 05 li r8,5 ; arg 5
100: 39 20 00 06 li r9,6 ; arg 6
104: 39 40 00 07 li r10,7 ; arg 7
108: 48 00 00 01 bl 108 <main+0x34> ; call and put return address -> lr
10c: 38 00 00 00 li r0,0 ; return value (pointlessly) via gpr0 ...
110: 7c 03 03 78 mr r3,r0 ; ... to gpr3
114: 81 61 00 00 lwz r11,0(r1) ; |
118: 80 0b 00 04 lwz r0,4(r11) ; |
11c: 7c 08 03 a6 mtlr r0 ; |
120: 83 eb ff fc lwz r31,-4(r11) ; | epilog
124: 7d 61 5b 78 mr r1,r11 ; |
128: 4e 80 00 20 blr ; |
; output from netbsd-4.0.1-macppc w/ gcc 4.1.2
00000000 <leaf_call>:
0: 94 21 ff c0 stwu r1,-64(r1)
4: 93 e1 00 3c stw r31,60(r1)
dyncall/doc/disas_examples/ppc.sysv.disas view on Meta::CPAN
20: 91 3f 00 20 stw r9,32(r31)
24: 91 5f 00 24 stw r10,36(r31)
28: 81 61 00 00 lwz r11,0(r1)
2c: 83 eb ff fc lwz r31,-4(r11)
30: 7d 61 5b 78 mr r1,r11
34: 4e 80 00 20 blr
00000038 <main>:
38: 94 21 ff e0 stwu r1,-32(r1) ; |
3c: 7c 08 02 a6 mflr r0 ; |
40: 93 e1 00 1c stw r31,28(r1) ; | prolog
44: 90 01 00 24 stw r0,36(r1) ; |
48: 7c 3f 0b 78 mr r31,r1 ; /
4c: 39 20 00 00 li r9,0 ; \
50: 39 40 00 05 li r10,5 ; |
54: 91 21 00 08 stw r9,8(r1) ; | arg 5 via stack
58: 91 41 00 0c stw r10,12(r1) ; |
5c: 38 60 00 00 li r3,0 ; arg 0
60: 38 a0 00 00 li r5,0 ; |
64: 38 c0 00 01 li r6,1 ; | arg 1 (note that r4 is skipped)
68: 38 e0 00 02 li r7,2 ; arg 2
6c: 39 00 00 03 li r8,3 ; arg 3
70: 39 20 00 00 li r9,0 ; |
74: 39 40 00 04 li r10,4 ; | arg 4
78: 48 00 00 01 bl 78 <main+0x40> ; call and put return address -> lr
7c: 38 00 00 01 li r0,1 ; return value (pointlessly) via gpr0 ...
80: 7c 03 03 78 mr r3,r0 ; ... to gpr3
84: 81 61 00 00 lwz r11,0(r1) ; |
88: 80 0b 00 04 lwz r0,4(r11) ; |
8c: 7c 08 03 a6 mtlr r0 ; |
90: 83 eb ff fc lwz r31,-4(r11) ; | epilog
94: 7d 61 5b 78 mr r1,r11 ; |
98: 4e 80 00 20 blr ; |
; ------------- var args with ints and floats to see spilling (which remains only int regs), b/c doubles are passed via them and floats are promoted to doubles in (...) ----------->
; #include <stdlib.h>
; #include <stdarg.h>
;
dyncall/doc/disas_examples/ppc.sysv.disas view on Meta::CPAN
458: 81 61 00 00 lwz r11,0(r1)
45c: 80 0b 00 04 lwz r0,4(r11)
460: 7c 08 03 a6 mtlr r0
464: 83 eb ff fc lwz r31,-4(r11)
468: 7d 61 5b 78 mr r1,r11
46c: 4e 80 00 20 blr
00000470 <main>:
470: 94 21 ff f0 stwu r1,-16(r1) ; |
474: 7c 08 02 a6 mflr r0 ; |
478: 93 e1 00 0c stw r31,12(r1) ; | prolog
47c: 90 01 00 14 stw r0,20(r1) ; |
480: 7c 3f 0b 78 mr r31,r1 ; /
484: 3d 20 00 00 lis r9,0 ; \ prep arg 5 (float, but double in reg & ellipsis), load from 0 b/c objdump is from .o, not finally linked exec
488: c8 09 00 00 lfd f0,0(r9) ; /
48c: 3d 20 00 00 lis r9,0 ; \ prep arg 6 (float, but double in reg & ellipsis), load from 0 b/c objdump is from .o, not finally linked exec
490: c9 a9 00 08 lfd f13,8(r9) ; /
494: 3d 20 00 00 lis r9,0 ; \ prep arg 9 (float, but double in reg & ellipsis), load from 0 b/c objdump is from .o, not finally linked exec
498: c9 89 00 10 lfd f12,16(r9) ; /
49c: 38 60 00 00 li r3,0 ; arg 0
4a0: 38 80 00 01 li r4,1 ; arg 1
dyncall/doc/disas_examples/ppc.sysv.disas view on Meta::CPAN
4b8: 39 00 00 07 li r8,7 ; arg 7
4bc: 39 20 00 08 li r9,8 ; arg 8
4c0: fc 60 60 90 fmr f3,f12 ; arg 9
4c4: 4c c6 32 42 crset 4*cr1+eq ; set CR bit for ellipsis call
4c8: 48 00 00 01 bl 4c8 <main+0x58> ; call and put return address -> lr
4cc: 38 00 00 00 li r0,0 ; return value (pointlessly) via gpr0 ...
4d0: 7c 03 03 78 mr r3,r0 ; ... to gpr3
4d4: 81 61 00 00 lwz r11,0(r1) ; |
4d8: 80 0b 00 04 lwz r0,4(r11) ; |
4dc: 7c 08 03 a6 mtlr r0 ; |
4e0: 83 eb ff fc lwz r31,-4(r11) ; | epilog
4e4: 7d 61 5b 78 mr r1,r11 ; |
4e8: 4e 80 00 20 blr ; |
; ---------- 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)
dyncall/doc/disas_examples/ppc.sysv.disas view on Meta::CPAN
88: 91 0b 00 0c stw r8,12(r11) ;
8c: 7d 63 5b 78 mr r3,r11 ;
90: 81 61 00 00 lwz r11,0(r1) ;
94: 83 eb ff fc lwz r31,-4(r11) ;
98: 7d 61 5b 78 mr r1,r11 ;
9c: 4e 80 00 20 blr ;
000000a0 <main>:
a0: 94 21 ff c0 stwu r1,-64(r1) ; | open frame and store sp at top of stack
a4: 7c 08 02 a6 mflr r0 ; | lr -> gpr0
a8: 93 e1 00 3c stw r31,60(r1) ; | prolog store gpr31
ac: 90 01 00 44 stw r0,68(r1) ; | store lr
b0: 7c 3f 0b 78 mr r31,r1 ; / sp -> gpr31, latter used for some fixed addressing below
b4: 38 1f 00 28 addi r0,r31,40 ; \
b8: 7c 03 03 78 mr r3,r0 ; | space to retval -> gpr3 (hidden arg)
bc: 4c c6 31 82 crclr 4*cr1+eq ; :
c0: 48 00 00 01 bl c0 <main+0x20> ; call f0()
c4: 88 1f 00 28 lbz r0,40(r31) ;
c8: 98 1f 00 08 stb r0,8(r31) ;
cc: 38 1f 00 10 addi r0,r31,16 ; |
d0: 7c 03 03 78 mr r3,r0 ; | space to retval -> gpr3 (hidden arg)
d4: 4c c6 31 82 crclr 4*cr1+eq ; :
d8: 48 00 00 01 bl d8 <main+0x38> ; call f1()
dc: 81 3f 00 18 lwz r9,24(r31) ;
e0: 88 1f 00 08 lbz r0,8(r31) ;
e4: 54 00 06 3e clrlwi r0,r0,24 ;
e8: 7c 09 02 14 add r0,r9,r0 ;
ec: 7c 03 03 78 mr r3,r0 ;
f0: 81 61 00 00 lwz r11,0(r1) ; |
f4: 80 0b 00 04 lwz r0,4(r11) ; |
f8: 7c 08 03 a6 mtlr r0 ; |
fc: 83 eb ff fc lwz r31,-4(r11) ; | epilog
100: 7d 61 5b 78 mr r1,r11 ; |
104: 4e 80 00 20 blr ; |
; output from netbsd-4.0.1-macppc w/ gcc 4.1.2 (demonstrates default (non-LSB) aggr return values)
018007a0 <f0>:
18007a0: 94 21 ff d0 stwu r1,-48(r1)
18007a4: 93 e1 00 2c stw r31,44(r1)
dyncall/doc/disas_examples/ppc.sysv.disas view on Meta::CPAN
1800820: 91 0b 00 0c stw r8,12(r11)
1800824: 7d 63 5b 78 mr r3,r11
1800828: 81 61 00 00 lwz r11,0(r1)
180082c: 83 eb ff fc lwz r31,-4(r11)
1800830: 7d 61 5b 78 mr r1,r11
1800834: 4e 80 00 20 blr
01800838 <main>:
1800838: 94 21 ff c0 stwu r1,-64(r1) ; | open frame and store sp at top of stack
180083c: 7c 08 02 a6 mflr r0 ; | lr -> gpr0
1800840: 93 e1 00 3c stw r31,60(r1) ; | prolog store gpr31
1800844: 90 01 00 44 stw r0,68(r1) ; | store lr
1800848: 7c 3f 0b 78 mr r31,r1 ; | sp -> gpr31, latter used for some fixed addressing below
180084c: 4b ff ff 55 bl 18007a0 <f0> ; call f0()
1800850: 7c 60 1b 78 mr r0,r3 ; | NOTE: ret val is returned via gpr3
1800854: 98 1f 00 08 stb r0,8(r31) ; / ret val
1800858: 38 1f 00 10 addi r0,r31,16 ; \
180085c: 7c 03 03 78 mr r3,r0 ; | space to retval -> gpr3 (hidden arg)
1800860: 4c c6 31 82 crclr 4*cr1+eq ; :
1800864: 4b ff ff 69 bl 18007cc <f1> ; call f0()
1800868: 81 3f 00 18 lwz r9,24(r31) ;
dyncall/doc/disas_examples/ppc.sysv.disas view on Meta::CPAN
1000043c: 80 0b 00 04 lwz r0,4(r11)
10000440: 7c 08 03 a6 mtlr r0
10000444: 83 ab ff f4 lwz r29,-12(r11)
10000448: 83 eb ff fc lwz r31,-4(r11)
1000044c: 7d 61 5b 78 mr r1,r11
10000450: 4e 80 00 20 blr
10000454 <f>:
10000454: 94 21 ff d0 stwu r1,-48(r1) ; | open frame and store sp at top of stack
10000458: 7c 08 02 a6 mflr r0 ; | lr -> gpr0
1000045c: 93 e1 00 2c stw r31,44(r1) ; | prolog store gpr31
10000460: 90 01 00 34 stw r0,52(r1) ; | store lr
10000464: 7c 3f 0b 78 mr r31,r1 ; / sp -> gpr31, latter used for some fixed addressing below
10000468: 38 00 00 01 li r0,1 ; \ a = 1
1000046c: 90 1f 00 08 stw r0,8(r31) ; /
10000470: 81 3f 00 08 lwz r9,8(r31) ; \
10000474: 38 09 00 7b addi r0,r9,123 ; | a += 123
10000478: 90 1f 00 08 stw r0,8(r31) ; /
1000047c: 38 1f 00 18 addi r0,r31,24 ; \
10000480: 7c 03 03 78 mr r3,r0 ; | space to retval -> gpr3 (hidden arg); NOTE: this follows the LSB definition
10000484: 4b ff ff 5d bl 100003e0 <f1> ; call f1()
dyncall/doc/disas_examples/ppc64.elfabi.disas view on Meta::CPAN
30: 91 3f 00 a0 stw r9,160(r31)
34: e8 21 00 00 ld r1,0(r1)
38: eb e1 ff f8 ld r31,-8(r1)
3c: 4e 80 00 20 blr
...
48: 80 01 00 01 lwz r0,1(r1)
000000000000004c <.nonleaf_call>:
4c: 7c 08 02 a6 mflr r0 ; |
50: fb e1 ff f8 std r31,-8(r1) ; |
54: f8 01 00 10 std r0,16(r1) ; | prolog
58: f8 21 ff 71 stdu r1,-144(r1) ; |
5c: 7c 3f 0b 78 mr r31,r1 ; use gpr31 as sort of frame pointer, below
60: 7c 60 1b 78 mr r0,r3 ; in arg 0 -> gpr0
64: 7c 8b 23 78 mr r11,r4 ; in arg 1 -> gpr11
68: 90 1f 00 c0 stw r0,192(r31) ; |
6c: 91 7f 00 c8 stw r11,200(r31) ; |
70: 90 bf 00 d0 stw r5,208(r31) ; |
74: 90 df 00 d8 stw r6,216(r31) ; |
78: 90 ff 00 e0 stw r7,224(r31) ; | all in args -> spill area in prev frame (jump over own frame (144) + linkage area of prev frame (48) = 192)
7c: 91 1f 00 e8 stw r8,232(r31) ; |
80: 91 3f 00 f0 stw r9,240(r31) ; |
84: 91 5f 00 f8 stw r10,248(r31) ; |
88: e8 01 00 00 ld r0,0(r1) ; fetch back-chain ptr (parent frame's sp) from stack of top by prolog -> gpr0, and ...
8c: f8 01 ff 11 stdu r0,-240(r1) ; ... update it further up the stack for alloca(220) - with padding to guarantee alignment
90: 39 21 00 70 addi r9,r1,112 ; |
94: f9 3f 00 70 std r9,112(r31) ; |
98: e9 3f 00 70 ld r9,112(r31) ; |
9c: 38 09 00 0f addi r0,r9,15 ; | start of alloca()'d memory -> gpr9, by ...
a0: 78 00 e1 02 rldicl r0,r0,60,4 ; | ... using gpr0 as helper to align to 16b, leaving at least 112b at top of stack
a4: 78 00 26 e4 rldicr r0,r0,4,59 ; |
a8: f8 1f 00 70 std r0,112(r31) ; |
ac: e9 3f 00 70 ld r9,112(r31) ; |
b0: 38 00 00 4c li r0,76 ; 'L' -> gpr0, and ...
dyncall/doc/disas_examples/ppc64.elfabi.disas view on Meta::CPAN
f0: 7d 03 43 78 mr r3,r8 ; arg 0
f4: 7c e4 3b 78 mr r4,r7 ; arg 1
f8: 7c c5 33 78 mr r5,r6 ; arg 2
fc: 7d 26 4b 78 mr r6,r9 ; arg 3
100: 7d 67 5b 78 mr r7,r11 ; arg 4
104: 7d 48 53 78 mr r8,r10 ; arg 5
108: 7c 09 03 78 mr r9,r0 ; arg 6
10c: 48 00 00 01 bl 10c <.nonleaf_call+0xc0> ; call and put return address -> lr
110: e8 21 00 00 ld r1,0(r1) ; |
114: e8 01 00 10 ld r0,16(r1) ; |
118: 7c 08 03 a6 mtlr r0 ; | epilog
11c: eb e1 ff f8 ld r31,-8(r1) ; |
120: 4e 80 00 20 blr ; |
124: 00 00 00 00 .long 0x0 ; data
128: 00 00 00 01 .long 0x1 ; data
12c: 80 01 00 01 lwz r0,1(r1) ; unsure@@@. data?
0000000000000130 <.main>:
130: 7c 08 02 a6 mflr r0 ; | lr -> gpr0
134: fb e1 ff f8 std r31,-8(r1) ; | preseve gpr31 (as used in func as helper addr)
138: f8 01 00 10 std r0,16(r1) ; | prolog store lr
13c: f8 21 ff 81 stdu r1,-128(r1) ; | open frame
140: 7c 3f 0b 78 mr r31,r1 ; use gpr31 as sort of frame pointer, below
144: 38 60 00 00 li r3,0 ; arg 0
148: 38 80 00 01 li r4,1 ; arg 1
14c: 38 a0 00 02 li r5,2 ; arg 2
150: 38 c0 00 03 li r6,3 ; arg 3
154: 38 e0 00 04 li r7,4 ; arg 4
158: 39 00 00 05 li r8,5 ; arg 5
15c: 39 20 00 06 li r9,6 ; arg 6
160: 39 40 00 07 li r10,7 ; arg 7
164: 48 00 00 01 bl 164 <.main+0x34> ; call and put return address -> lr
168: 38 00 00 00 li r0,0 ; return value ...
16c: 7c 03 03 78 mr r3,r0 ; ... in gpr3
170: e8 21 00 00 ld r1,0(r1) ; |
174: e8 01 00 10 ld r0,16(r1) ; |
178: 7c 08 03 a6 mtlr r0 ; | epilog
17c: eb e1 ff f8 ld r31,-8(r1) ; |
180: 4e 80 00 20 blr ; |
184: 00 00 00 00 .long 0x0 ; data
188: 00 00 00 01 .long 0x1 ; data
18c: 80 01 00 01 lwz r0,1(r1) ; unsure@@@. data?
; ------------- ints and floats, var args, struct return value (meaning implicit first param), more than 8 params (11, with implicit return value ptr) ----------->
dyncall/doc/disas_examples/ppc64.elfabi.disas view on Meta::CPAN
38: 91 1f 00 90 stw r8,144(r31)
3c: 90 1f 00 a8 stw r0,168(r31)
40: e8 21 00 00 ld r1,0(r1)
44: eb e1 ff f8 ld r31,-8(r1)
48: 4e 80 00 20 blr
...
54: 80 01 00 01 lwz r0,1(r1)
0000000000000058 <.nonleaf_call>:
58: fb e1 ff f8 std r31,-8(r1) ; |
5c: f8 21 ff 91 stdu r1,-112(r1) ; | prolog
60: 7c 3f 0b 78 mr r31,r1 ; use gpr31 as sort of frame pointer, below
64: 7c 8b 23 78 mr r11,r4 ; in arg 1 (first explicit arg, b/c of struct return value ptr being arg0) -> r11
68: 7c a8 2b 78 mr r8,r5 ; in arg 2 -> r8 (free reg, was skipped for float param)
6c: d0 3f 00 b8 stfs f1,184(r31) ; | in arg 3 (float) -> prev frame's spill area: 184 = 112 (frame) + 48 (prev frame's linkage area) + 8 (arg 0 = return value ptr) + 16 (first two explicit args)
70: d0 5f 00 c8 stfs f2,200(r31) ; | in arg 5 (float) -> prev frame's spill area
74: f9 5f 00 d8 std r10,216(r31) ; | in arg 7 (float, also held in gpr reg b/c vararg) -> prev frame's spill area
78: 7d 20 4b 78 mr r0,r9 ; | spilling in arg 6 in gpr0 (spilled below)
7c: 91 7f 00 a8 stw r11,168(r31) ; | in arg 1 (int) -> prev frame's spill area
80: 91 1f 00 b0 stw r8,176(r31) ; | in arg 2 (int) -> prev frame's spill area
84: 90 ff 00 c0 stw r7,192(r31) ; | in arg 4 (int) -> prev frame's spill area
dyncall/doc/disas_examples/ppc64.elfabi.disas view on Meta::CPAN
a0: 90 1f 00 50 stw r0,80(r31) ; |
a4: 38 1f 00 d8 addi r0,r31,216 ;
a8: f8 1f 00 40 std r0,64(r31) ; .
ac: 7f e0 00 08 trap ; .
... ; .
b8: 80 01 00 01 lwz r0,1(r1) ;
00000000000000bc <.main>:
bc: 7c 08 02 a6 mflr r0 ; | lr -> gpr0
c0: fb e1 ff f8 std r31,-8(r1) ; | preseve gpr31 (as used in func as helper addr)
c4: f8 01 00 10 std r0,16(r1) ; | prolog store lr
c8: f8 21 ff 41 stdu r1,-192(r1) ; | open frame
cc: 7c 3f 0b 78 mr r31,r1 ; use gpr31 as sort of frame pointer, below
d0: 39 61 00 30 addi r11,r1,48 ; ptr to param area -> r11
d4: e9 22 00 00 ld r9,0(r2) ; prep arg 3 (=explicit arg 2, b/c of implicit return value pointer), ...
d8: c1 a9 00 00 lfs f13,0(r9) ; ... load from static data -> f13
dc: e9 22 00 08 ld r9,8(r2) ; prep arg 5, ...
e0: c1 89 00 00 lfs f12,0(r9) ; ... load from static data -> f12
e4: e9 22 00 10 ld r9,16(r2) ; prep arg 7, ...
e8: c8 09 00 00 lfd f0,0(r9) ; ... load from static data -> f0
ec: d8 1f 00 a0 stfd f0,160(r31) ; |
dyncall/doc/disas_examples/ppc64.elfabi.disas view on Meta::CPAN
148: fc 40 60 90 fmr f2,f12 ; arg 5 (float, in 2nd double reg)
14c: 39 20 00 05 li r9,5 ; arg 6 (skipping gpr8 b/c of float arg, vararg)
150: fc 60 58 90 fmr f3,f11 ; arg 7 (float, in 3rd double reg, promoted to double anyways b/c vararg)
154: fc 80 50 90 fmr f4,f10 ; arg 8 (float, in 4th double reg, promoted to double anyways b/c vararg)
158: fc a0 00 90 fmr f5,f0 ; arg 10 (float, in 5th double reg, promoted to double anyways b/c vararg)
15c: 48 00 00 01 bl 15c <.main+0xa0> ; call and put return address -> lr
160: 38 00 00 00 li r0,0 ; return value ...
164: 7c 03 03 78 mr r3,r0 ; ... in gpr3
168: e8 21 00 00 ld r1,0(r1) ; |
16c: e8 01 00 10 ld r0,16(r1) ; |
170: 7c 08 03 a6 mtlr r0 ; | epilog
174: eb e1 ff f8 ld r31,-8(r1) ; |
178: 4e 80 00 20 blr ; |
17c: 00 00 00 00 .long 0x0 ; data
180: 00 00 00 01 .long 0x1 ; data
184: 80 01 00 01 lwz r0,1(r1) ; unsure@@@. data?
; ---------- structs by value ---------->
;
dyncall/doc/disas_examples/ppc64.elfabi.disas view on Meta::CPAN
11c: eb a1 ff e8 ld r29,-24(r1)
120: eb e1 ff f8 ld r31,-8(r1)
124: 4e 80 00 20 blr
128: 00 00 00 00 .long 0x0
12c: 00 00 00 01 .long 0x1
130: 80 03 00 01 lwz r0,1(r3)
0000000000000134 <.main>:
134: 7c 08 02 a6 mflr r0 ; | lr -> gpr0
138: fb e1 ff f8 std r31,-8(r1) ; | preseve gpr31 (as used in func as helper addr)
13c: f8 01 00 10 std r0,16(r1) ; | prolog store lr
140: f8 21 ff 61 stdu r1,-160(r1) ; | open frame
144: 7c 3f 0b 78 mr r31,r1 ; use gpr31 as sort of frame pointer, below
148: e9 22 00 00 ld r9,0(r2) ; |
14c: e9 49 00 08 ld r10,8(r9) ; | fetch local struct data's 2 doublewords (r2 = TOC ptr) -> r9/r10, and ...
150: e9 29 00 00 ld r9,0(r9) ; |
154: f9 3f 00 80 std r9,128(r31) ; | ... write to local area on stack
158: f9 5f 00 88 std r10,136(r31) ; /
15c: 38 00 00 09 li r0,9 ; \ arg 7, ...
160: f8 01 00 70 std r0,112(r1) ; | ... "pushed" onto stack
164: 38 60 00 00 li r3,0 ; arg 0
dyncall/doc/disas_examples/ppc64.elfabi.disas view on Meta::CPAN
170: 38 c0 00 03 li r6,3 ; arg 3
174: 38 e0 00 04 li r7,4 ; arg 4
178: e9 1f 00 80 ld r8,128(r31) ; |
17c: e9 3f 00 88 ld r9,136(r31) ; | arg 5 (struct, fetch from local area, pass as 2 doublewords)
180: 39 40 00 08 li r10,8 ; arg 6
184: 48 00 00 01 bl 184 <.main+0x50> ; call and put return address -> lr
188: 38 00 00 00 li r0,0 ; return value ...
18c: 7c 03 03 78 mr r3,r0 ; ... in gpr3
190: e8 21 00 00 ld r1,0(r1) ; |
194: e8 01 00 10 ld r0,16(r1) ; |
198: 7c 08 03 a6 mtlr r0 ; | epilog
19c: eb e1 ff f8 ld r31,-8(r1) ; |
1a0: 4e 80 00 20 blr ; |
1a4: 00 00 00 00 .long 0x0 ; data
1a8: 00 00 00 01 .long 0x1 ; data
1ac: 80 01 00 01 lwz r0,1(r1) ; unsure@@@. data?
; ---------- structs by value, complex example (multiple structs) ---------->
;
dyncall/doc/disas_examples/ppc64.elfabi.disas view on Meta::CPAN
140: eb a1 ff e8 ld r29,-24(r1)
144: eb e1 ff f8 ld r31,-8(r1)
148: 4e 80 00 20 blr
14c: 00 00 00 00 .long 0x0
150: 00 00 00 01 .long 0x1
154: 80 04 00 01 lwz r0,1(r4)
0000000000000158 <.main>:
158: 7c 08 02 a6 mflr r0 ; | lr -> gpr0
15c: fb e1 ff f8 std r31,-8(r1) ; | preseve gpr31 (as used in func as helper addr)
160: f8 01 00 10 std r0,16(r1) ; | prolog store lr
164: f8 21 ff 11 stdu r1,-240(r1) ; | open frame
168: 7c 3f 0b 78 mr r31,r1 ; use gpr31 as sort of frame pointer, below
16c: e9 22 00 00 ld r9,0(r2) ; |
170: e8 09 00 00 ld r0,0(r9) ; | fetch local first struct A data's 2 doublewords (r2 = TOC ptr) -> r9/r10, and ...
174: 81 29 00 08 lwz r9,8(r9) ; |
178: f8 1f 00 d0 std r0,208(r31) ; | ... write to local area on stack
17c: 91 3f 00 d8 stw r9,216(r31) ; /
180: e9 22 00 08 ld r9,8(r2) ; \
184: e9 49 00 08 ld r10,8(r9) ; | fetch local first struct B data's 2 doublewords (r2 = TOC ptr) -> r9/r10, and ...
188: e9 29 00 00 ld r9,0(r9) ; |
dyncall/doc/disas_examples/ppc64.elfabi.disas view on Meta::CPAN
204: 39 3f 00 c0 addi r9,r31,192 ; \
208: e8 e9 00 00 ld r7,0(r9) ; | arg 3 (first struct B, fetch from local area, pass as 2 doublewords)
20c: e9 09 00 08 ld r8,8(r9) ; |
210: 39 20 00 07 li r9,7 ; arg 4
214: 39 40 00 08 li r10,8 ; arg 5
218: 48 00 00 01 bl 218 <.main+0xc0> ; call and put return address -> lr
21c: 38 00 00 00 li r0,0 ; return value ...
220: 7c 03 03 78 mr r3,r0 ; ... in gpr3
224: e8 21 00 00 ld r1,0(r1) ; |
228: e8 01 00 10 ld r0,16(r1) ; |
22c: 7c 08 03 a6 mtlr r0 ; | epilog
230: eb e1 ff f8 ld r31,-8(r1) ; |
234: 4e 80 00 20 blr ; |
238: 00 00 00 00 .long 0x0 ; data
23c: 00 00 00 01 .long 0x1 ; data
240: 80 01 00 01 lwz r0,1(r1) ; unsure@@@. data?
; ---------- returning qwords ---------->
;
dyncall/doc/disas_examples/ppc64.elfabi.disas view on Meta::CPAN
; a -= 12;
; }
; }
; output from freebsd-11.0-ppc64 w/ gcc 4.2.1
0000000010000828 <.f1>:
10000828: fb e1 ff f8 std r31,-8(r1) ; |
1000082c: f8 21 ff c1 stdu r1,-64(r1) ; | prolog
10000830: 7c 3f 0b 78 mr r31,r1 ; use gpr31 as sort of frame pointer, below
10000834: 90 7f 00 70 stw r3,112(r31) ;
10000838: e8 21 00 00 ld r1,0(r1) ; |
1000083c: eb e1 ff f8 ld r31,-8(r1) ; | epilog
10000840: 4e 80 00 20 blr ; |
10000844: 00 00 00 00 .long 0x0 ; data
10000848: 00 09 00 00 .long 0x90000 ; data
1000084c: 80 01 00 01 lwz r0,1(r1) ; unsure@@@. data?
0000000010000850 <.f2>:
10000850: fb e1 ff f8 std r31,-8(r1) ; |
10000854: f8 21 ff c1 stdu r1,-64(r1) ; | prolog
10000858: 7c 3f 0b 78 mr r31,r1 ; use gpr31 as sort of frame pointer, below
1000085c: f8 7f 00 70 std r3,112(r31) ;
10000860: e8 21 00 00 ld r1,0(r1) ; |
10000864: eb e1 ff f8 ld r31,-8(r1) ; | epilog
10000868: 4e 80 00 20 blr ; |
1000086c: 00 00 00 00 .long 0x0 ; data
10000870: 00 09 00 00 .long 0x90000 ; data
10000874: 80 01 00 01 lwz r0,1(r1) ; unsure@@@. data?
0000000010000878 <.f>:
10000878: 7c 08 02 a6 mflr r0 ;
1000087c: fb e1 ff f8 std r31,-8(r1) ;
10000880: f8 01 00 10 std r0,16(r1) ;
10000884: f8 21 ff 71 stdu r1,-144(r1) ;
dyncall/doc/disas_examples/sparc.sparc.disas view on Meta::CPAN
8: f2 27 a0 48 st %i1, [ %fp + 0x48 ]
c: f4 27 a0 4c st %i2, [ %fp + 0x4c ]
10: f6 27 a0 50 st %i3, [ %fp + 0x50 ]
14: f8 27 a0 54 st %i4, [ %fp + 0x54 ]
18: fa 27 a0 58 st %i5, [ %fp + 0x58 ]
1c: 81 e8 00 00 restore
20: 81 c3 e0 08 retl
24: 01 00 00 00 nop
00000028 <nonleaf_call>:
28: 9d e3 bf 88 save %sp, -120, %sp ; prolog
2c: f0 27 a0 44 st %i0, [ %fp + 0x44 ] ; |
30: f2 27 a0 48 st %i1, [ %fp + 0x48 ] ; |
34: f4 27 a0 4c st %i2, [ %fp + 0x4c ] ; | write input to prev frame's spill area
38: f6 27 a0 50 st %i3, [ %fp + 0x50 ] ; | (e.g. offset = 68 for i0, jumping over i*/l* save area and aggregate return pointer)
3c: f8 27 a0 54 st %i4, [ %fp + 0x54 ] ; |
40: fa 27 a0 58 st %i5, [ %fp + 0x58 ] ; |
44: 9c 03 bf 20 add %sp, -224, %sp ; alloca(220) - with 4b padding (multiple of 8), and ...
48: 82 03 a0 64 add %sp, 0x64, %g1 ; ... at least 100b at top of stack, via ...
4c: c2 27 bf f4 st %g1, [ %fp + -12 ] ; ... local space (pointlessly) ...
50: c4 07 bf f4 ld [ %fp + -12 ], %g2 ; ... to g2
dyncall/doc/disas_examples/sparc.sparc.disas view on Meta::CPAN
74: c2 23 a0 5c st %g1, [ %sp + 0x5c ] ; ... "pushed" onto stack
78: d0 07 a0 48 ld [ %fp + 0x48 ], %o0 ; |
7c: d2 07 a0 4c ld [ %fp + 0x4c ], %o1 ; |
80: d4 07 a0 50 ld [ %fp + 0x50 ], %o2 ; |
84: d6 07 a0 54 ld [ %fp + 0x54 ], %o3 ; | arg 0,1,2,3,4 (fetched from prev frame's spill area)
88: d8 07 a0 58 ld [ %fp + 0x58 ], %o4 ; |
8c: da 07 a0 5c ld [ %fp + 0x5c ], %o5 ; arg 5 (fetched from prev frame's stack param area)
90: 40 00 00 00 call 90 <nonleaf_call+0x68> ; call leaf_call (objdump not from final link but .o)
94: 01 00 00 00 nop ; branch delay slot
98: 81 e8 00 00 restore ; |
9c: 81 c3 e0 08 retl ; | epilog
a0: 01 00 00 00 nop ; | branch delay slot
000000a4 <main>:
a4: 9d e3 bf 90 save %sp, -112, %sp ; prolog
a8: 82 10 20 06 mov 6, %g1 ; arg 6, ...
ac: c2 23 a0 5c st %g1, [ %sp + 0x5c ] ; ... "pushed" onto stack
b0: 82 10 20 07 mov 7, %g1 ; arg 7, ...
b4: c2 23 a0 60 st %g1, [ %sp + 0x60 ] ; ... "pushed" onto stack
b8: 90 10 20 00 clr %o0 ; arg 0
bc: 92 10 20 01 mov 1, %o1 ; arg 1
c0: 94 10 20 02 mov 2, %o2 ; arg 2
c4: 96 10 20 03 mov 3, %o3 ; arg 3
c8: 98 10 20 04 mov 4, %o4 ; arg 4
cc: 9a 10 20 05 mov 5, %o5 ; arg 5
d0: 40 00 00 00 call d0 <main+0x2c> ; call nonleaf_call (objdump not from final link but .o)
d4: 01 00 00 00 nop ; branch delay slot
d8: 82 10 20 00 clr %g1 ! 0 <leaf_call> ; |
dc: b0 10 00 01 mov %g1, %i0 ; / return value
e0: 81 e8 00 00 restore ; \
e4: 81 c3 e0 08 retl ; | epilog
e8: 01 00 00 00 nop ; | branch delay slot
; output from netbsd-6.0-sparc w/ gcc 4.5.3
00000000 <leaf_call>:
0: 9d e3 bf a0 save %sp, -96, %sp
4: f0 27 a0 44 st %i0, [ %fp + 0x44 ]
8: f2 27 a0 48 st %i1, [ %fp + 0x48 ]
dyncall/doc/disas_examples/sparc.sparc.disas view on Meta::CPAN
8: f2 27 a0 48 st %i1, [ %fp + 0x48 ]
c: f4 27 a0 4c st %i2, [ %fp + 0x4c ]
10: f6 27 a0 50 st %i3, [ %fp + 0x50 ]
14: f8 27 a0 54 st %i4, [ %fp + 0x54 ]
18: fa 27 a0 58 st %i5, [ %fp + 0x58 ]
1c: 81 e8 00 00 restore
20: 81 c3 e0 08 retl
24: 01 00 00 00 nop
00000028 <nonleaf_call>:
28: 9d e3 bf 78 save %sp, -136, %sp ; prolog
2c: e0 07 a0 40 ld [ %fp + 0x40 ], %l0 ; pointer to struct to return -> l0
30: f0 27 a0 44 st %i0, [ %fp + 0x44 ] ; |
34: f2 27 a0 48 st %i1, [ %fp + 0x48 ] ; |
38: f4 27 a0 4c st %i2, [ %fp + 0x4c ] ; |
3c: f6 27 a0 50 st %i3, [ %fp + 0x50 ] ; | write input to prev frame's spill area
40: f8 27 a0 54 st %i4, [ %fp + 0x54 ] ; |
44: fa 27 a0 58 st %i5, [ %fp + 0x58 ] ; /
48: c2 07 a0 48 ld [ %fp + 0x48 ], %g1 ; \
4c: c2 27 bf ec st %g1, [ %fp + -20 ] ; |
50: c2 07 a0 50 ld [ %fp + 0x50 ], %g1 ; | in arg 1,3,5 (the ints to be returned in struct), ...
dyncall/doc/disas_examples/sparc.sparc.disas view on Meta::CPAN
ac: 40 00 00 00 call ac <nonleaf_call+0x84> ; call leaf_call (objdump not from final link but .o)
b0: 01 00 00 00 nop ; branch delay slot
b4: c2 07 bf ec ld [ %fp + -20 ], %g1 ; |
b8: c2 24 00 00 st %g1, [ %l0 ] ; |
bc: c2 07 bf f0 ld [ %fp + -16 ], %g1 ; |
c0: c2 24 20 04 st %g1, [ %l0 + 4 ] ; | store struct elements
c4: c2 07 bf f4 ld [ %fp + -12 ], %g1 ; |
c8: c2 24 20 08 st %g1, [ %l0 + 8 ] ; |
cc: b0 10 00 10 mov %l0, %i0 ; return value (pointer to struct)
d0: 81 e8 00 00 restore ; |
d4: 81 c3 e0 0c jmp %o7 + 0xc ; | epilog
d8: 01 00 00 00 nop ; | branch delay slot
000000dc <main>:
dc: 9d e3 bf 80 save %sp, -128, %sp ; prolog
e0: 03 00 00 00 sethi %hi(0), %g1 ; |
e4: 82 10 60 00 mov %g1, %g1 ! 0 <leaf_call> ; | prep arg 2, load from static data into f8 (addr = 0 b/c objdumped .o, not final linked)
e8: d1 00 40 00 ld [ %g1 ], %f8 ; /
ec: 03 00 00 00 sethi %hi(0), %g1 ; \
f0: 82 10 60 00 mov %g1, %g1 ! 0 <leaf_call> ; | prep arg 4, load from static data into f9 (addr = 0 b/c objdumped .o, not final linked)
f4: d3 00 40 00 ld [ %g1 ], %f9 ; |
f8: 82 10 20 06 mov 6, %g1 ; arg 6, ...
fc: c2 23 a0 5c st %g1, [ %sp + 0x5c ] ; ... "pushed" onto stack
100: 82 10 20 07 mov 7, %g1 ; arg 7, ...
104: c2 23 a0 60 st %g1, [ %sp + 0x60 ] ; ... "pushed" onto stack
dyncall/doc/disas_examples/sparc.sparc.disas view on Meta::CPAN
120: 96 10 20 03 mov 3, %o3 ; arg 3
124: d3 27 bf f8 st %f9, [ %fp + -8 ] ; | arg 4, from f9 via temp space ...
128: d8 07 bf f8 ld [ %fp + -8 ], %o4 ; | ... to o4
12c: 9a 10 20 05 mov 5, %o5 ; arg 5
130: 40 00 00 00 call 130 <main+0x54> ; call nonleaf_call (objdump not from final link but .o)
134: 01 00 00 00 nop ; branch delay slot
138: 00 00 00 0c unimp 0xc ; sparc convention for returned aggregates: use unimp with field (here 0xc) specifiying size of returned struct (see sparc manual explanation)
13c: 82 10 20 00 clr %g1 ; |
140: b0 10 00 01 mov %g1, %i0 ; / return value
144: 81 e8 00 00 restore ; \
148: 81 c3 e0 08 retl ; | epilog
14c: 01 00 00 00 nop ; | branch delay slot
; ---------- 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)
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
1c: ca 27 a8 87 st %g5, [ %fp + 0x887 ]
20: c8 27 a8 8f st %g4, [ %fp + 0x88f ]
24: c6 27 a8 97 st %g3, [ %fp + 0x897 ]
28: c4 27 a8 9f st %g2, [ %fp + 0x89f ]
2c: c2 27 a8 a7 st %g1, [ %fp + 0x8a7 ]
30: 01 00 00 00 nop
34: 81 cf e0 08 rett %i7 + 8
38: 01 00 00 00 nop
000000000000003c <nonleaf_call>:
3c: 9d e3 bf 40 save %sp, -192, %sp ; prolog
40: 8a 10 00 19 mov %i1, %g5 ; |
44: 88 10 00 1a mov %i2, %g4 ; |
48: 86 10 00 1b mov %i3, %g3 ; |
4c: 84 10 00 1c mov %i4, %g2 ; |
50: 82 10 00 1d mov %i5, %g1 ; |
54: f0 27 a8 7f st %i0, [ %fp + 0x87f ] ; | write input to prev frame's spill area (e.g. offset = 128 for i0, jumping over i*/l* save area)
58: ca 27 a8 87 st %g5, [ %fp + 0x887 ] ; | (pointlessly using an extra reg copy to g* for most)
5c: c8 27 a8 8f st %g4, [ %fp + 0x88f ] ; |
60: c6 27 a8 97 st %g3, [ %fp + 0x897 ] ; |
64: c4 27 a8 9f st %g2, [ %fp + 0x89f ] ; |
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
c4: c2 73 a8 af stx %g1, [ %sp + 0x8af ] ; ... "pushed" onto stack
c8: 9a 10 00 1c mov %i4, %o5 ; |
cc: 98 10 00 1d mov %i5, %o4 ; |
d0: 96 10 00 05 mov %g5, %o3 ; |
d4: 94 10 00 04 mov %g4, %o2 ; | arg 0,1,2,3,4 (fetched from prev frame's spill area)
d8: 92 10 00 03 mov %g3, %o1 ; |
dc: 90 10 00 02 mov %g2, %o0 ; |
e0: 40 00 00 00 call e0 <nonleaf_call+0xa4> ; call leaf_call (objdump not from final link but .o)
e4: 01 00 00 00 nop ; branch delay slot
e8: 01 00 00 00 nop ;
ec: 81 cf e0 08 rett %i7 + 8 ; | epilog
f0: 01 00 00 00 nop ; | branch delay slot
00000000000000f4 <main>:
f4: 9d e3 bf 40 save %sp, -192, %sp ; prolog
f8: 82 10 20 07 mov 7, %g1 ; arg 7, ...
fc: c2 73 a8 b7 stx %g1, [ %sp + 0x8b7 ] ; ... "pushed" onto stack
100: 82 10 20 06 mov 6, %g1 ; arg 6, ...
104: c2 73 a8 af stx %g1, [ %sp + 0x8af ] ; ... "pushed" onto stack
108: 9a 10 20 05 mov 5, %o5 ; arg 5
10c: 98 10 20 04 mov 4, %o4 ; arg 4
110: 96 10 20 03 mov 3, %o3 ; arg 3
114: 94 10 20 02 mov 2, %o2 ; arg 2
118: 92 10 20 01 mov 1, %o1 ; arg 1
11c: 90 10 20 00 clr %o0 ; arg 0
120: 40 00 00 00 call 120 <main+0x2c> ; call nonleaf_call (objdump not from final link but .o)
124: 01 00 00 00 nop ; branch delay slot
128: 82 10 20 00 clr %g1 ! 0 <leaf_call> ; |
12c: 83 38 60 00 sra %g1, 0, %g1 ; | return value
130: b0 10 00 01 mov %g1, %i0 ; /
134: 81 cf e0 08 rett %i7 + 8 ; \ epilog
138: 01 00 00 00 nop ; | branch delay slot
; output from freebsd-11.0-sparc64 w/ gcc 4.2.1
0000000000000000 <leaf_call>:
0: 9d e3 bf 40 save %sp, -192, %sp
4: 82 10 00 18 mov %i0, %g1
8: 84 10 00 19 mov %i1, %g2
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
; {
; struct aggr st = nonleaf_call(0, 1, 2.f, 3, 4.f, 5, 6, 7.f);
; return 0;
; }
; output from netbsd-7.1-sparc64 w/ gcc 4.8.5
0000000000000000 <leaf_call>:
0: 9d e3 bf 50 save %sp, -176, %sp ; prolog
4: 88 10 00 18 mov %i0, %g4 ; |
8: c7 27 a8 87 st %f3, [ %fp + 0x887 ] ; |
c: 86 10 00 1a mov %i2, %g3 ; |
10: cf 27 a8 97 st %f7, [ %fp + 0x897 ] ; |
14: 84 10 00 1c mov %i4, %g2 ; | write input to prev frame's spill area (e.g. offset = 128 for i0, jumping over i*/l* save area)
18: 82 10 00 1d mov %i5, %g1 ; | (pointlessly using an extra reg copy to g* for most)
1c: db 27 a8 af st %f13, [ %fp + 0x8af ] ; | note: float args are spilled as are all others
20: c8 27 a8 7f st %g4, [ %fp + 0x87f ] ; |
24: c6 27 a8 8f st %g3, [ %fp + 0x88f ] ; |
28: c4 27 a8 9f st %g2, [ %fp + 0x89f ] ; |
2c: c2 27 a8 a7 st %g1, [ %fp + 0x8a7 ] ; /
30: 81 cf e0 08 rett %i7 + 8 ; \ trap epilog
34: 01 00 00 00 nop ; | branch delay slot
0000000000000038 <nonleaf_call>:
38: 9d e3 bf 20 save %sp, -224, %sp ; prolog
3c: 88 10 00 18 mov %i0, %g4 ; |
40: 86 10 00 19 mov %i1, %g3 ; |
44: cb 27 a8 8f st %f5, [ %fp + 0x88f ] ; |
48: 84 10 00 1b mov %i3, %g2 ; |
4c: d3 27 a8 9f st %f9, [ %fp + 0x89f ] ; | write input to prev frame's spill area (e.g. offset = 128 for i0, jumping over i*/l* save area)
50: 82 10 00 1d mov %i5, %g1 ; | (pointlessly using an extra reg copy to g* for most)
54: c8 27 a8 7f st %g4, [ %fp + 0x87f ] ; | note: float args are spilled as are all others
58: c6 27 a8 87 st %g3, [ %fp + 0x887 ] ; |
5c: c4 27 a8 97 st %g2, [ %fp + 0x897 ] ; |
60: c2 27 a8 a7 st %g1, [ %fp + 0x8a7 ] ; |
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
80: c2 77 a7 e7 stx %g1, [ %fp + 0x7e7 ] ; ... store to local space (0x7e7 - bias = -24)
84: c2 5f a7 e7 ldx [ %fp + 0x7e7 ], %g1 ; reread to start iteration (pointlessly)
88: 84 00 60 04 add %g1, 4, %g2 ; point read ptr in g2 to first unnamed param (int)
8c: c4 00 80 00 ld [ %g2 ], %g2 ; in arg 6 (fetched from prev frame's stack param area), ...
90: c4 27 a7 fb st %g2, [ %fp + 0x7fb ] ; ... copied to local space (0x7fb - bias = -4) helper var (probably int g)
94: 82 00 60 08 add %g1, 8, %g1 ; point read ptr in g1 to second unnamed param (float, promoted to double), ...
98: c2 77 a7 e7 stx %g1, [ %fp + 0x7e7 ] ; ... store in local space (0x7fb - bias = -24)
9c: 91 d0 20 05 ta 5 ; trap - not sure what else is involved (objdump was made from .o, not finally linked exec) - maybe just b/c objdump skipped this for the output?
00000000000000a0 <main>:
a0: 9d e3 bf 30 save %sp, -208, %sp ; prolog
a4: 03 00 00 00 sethi %hi(0), %g1 ; |
a8: 82 10 60 00 mov %g1, %g1 ! 0 <leaf_call> ; |
ac: 83 28 70 0c sllx %g1, 0xc, %g1 ; | prep arg 2, load from static data into f11 (addr = 0 b/c objdumped .o, not final linked)
b0: 82 10 60 00 mov %g1, %g1 ; |
b4: d7 00 40 00 ld [ %g1 ], %f11 ; /
b8: 03 00 00 00 sethi %hi(0), %g1 ; \
bc: 82 10 60 00 mov %g1, %g1 ! 0 <leaf_call> ; | prep arg 4, load from static data into f10 (addr = 0 b/c objdumped .o, not final linked)
c0: 83 28 70 0c sllx %g1, 0xc, %g1 ; |
c4: 82 10 60 00 mov %g1, %g1 ; |
c8: d5 00 40 00 ld [ %g1 ], %f10 ; |
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
13c: 84 10 c0 02 or %g3, %g2, %g2 ; |
140: c4 27 a7 f7 st %g2, [ %fp + 0x7f7 ] ; /
144: 83 38 70 20 srax %g1, 0x20, %g1 ; \
148: c4 07 a7 fb ld [ %fp + 0x7fb ], %g2 ; |
14c: 84 08 a0 00 and %g2, 0, %g2 ; | store 3rd struct field (int) by g1 >> 32 (and then some other operations unnecessary here)
150: 82 10 80 01 or %g2, %g1, %g1 ; |
154: c2 27 a7 fb st %g1, [ %fp + 0x7fb ] ; /
158: 82 10 20 00 clr %g1 ; \
15c: 83 38 60 00 sra %g1, 0, %g1 ; / return value
160: b0 10 00 01 mov %g1, %i0 ; \
164: 81 cf e0 08 rett %i7 + 8 ; | epilog
168: 01 00 00 00 nop ; | branch delay slot
; ---------- 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)
; {
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
164: 03 00 00 00 sethi %hi(0), %g1
168: 82 10 60 00 mov %g1, %g1 ! 0 <leaf_call>
16c: c2 5d c0 01 ldx [ %l7 + %g1 ], %g1
170: 90 10 00 01 mov %g1, %o0
174: 40 00 00 00 call 174 <nonleaf_call+0x130>
178: 01 00 00 00 nop
17c: 81 cf e0 08 rett %i7 + 8
180: 01 00 00 00 nop
0000000000000184 <main>:
184: 9d e3 bf 00 save %sp, -256, %sp ; prolog
188: 82 10 20 05 mov 5, %g1 ; | \ i
18c: c2 27 a7 d7 st %g1, [ %fp + 0x7d7 ] ; | /
190: 82 10 20 06 mov 6, %g1 ; | put together local struct \ j
194: c2 27 a7 db st %g1, [ %fp + 0x7db ] ; | /
198: 82 10 20 07 mov 7, %g1 ; | \ l
19c: c2 77 a7 df stx %g1, [ %fp + 0x7df ] ; / /
1a0: 84 03 a8 7f add %sp, 0x87f, %g2 ; \
1a4: c2 5f a7 d7 ldx [ %fp + 0x7d7 ], %g1 ; |
1a8: c2 70 a0 28 stx %g1, [ %g2 + 0x28 ] ; | (part of) arg 5, fetched from local area, "pushed" onto stack (entirely, so first 8 bytes (i,j) are already placed in reg save area)
1ac: c2 5f a7 df ldx [ %fp + 0x7df ], %g1 ; |
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
1cc: 92 10 20 01 mov 1, %o1 ; arg 1
1d0: 94 10 20 02 mov 2, %o2 ; arg 2
1d4: 96 10 20 03 mov 3, %o3 ; arg 3
1d8: 98 10 20 04 mov 4, %o4 ; arg 4
1dc: 9a 10 00 03 mov %g3, %o5 ; (part of) arg 5 (first 8 bytes of struct)
1e0: 40 00 00 00 call 1e0 <main+0x5c> ; call nonleaf_call (objdump not from final link but .o)
1e4: 01 00 00 00 nop ; branch delay slot
1e8: 82 10 20 00 clr %g1 ! 0 <leaf_call> ; \
1ec: 83 38 60 00 sra %g1, 0, %g1 ; / return value
1f0: b0 10 00 01 mov %g1, %i0 ; \
1f4: 81 cf e0 08 rett %i7 + 8 ; | epilog
1f8: 01 00 00 00 nop ; | branch delay slot
; ---------- 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)
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
1b8: 03 00 00 00 sethi %hi(0), %g1
1bc: 82 10 60 00 mov %g1, %g1 ! 0 <leaf_call>
1c0: c2 5d c0 01 ldx [ %l7 + %g1 ], %g1
1c4: 90 10 00 01 mov %g1, %o0
1c8: 40 00 00 00 call 1c8 <nonleaf_call+0x170>
1cc: 01 00 00 00 nop
1d0: 81 cf e0 08 rett %i7 + 8
1d4: 01 00 00 00 nop
00000000000001d8 <main>:
1d8: 9d e3 be c0 save %sp, -320, %sp ; prolog
1dc: 2f 00 00 00 sethi %hi(0), %l7 ; |
1e0: ae 05 e0 00 add %l7, 0, %l7 ! 0 <leaf_call> ; | @@@ unsure, call to some code stub adding o7 to l7
1e4: 7f ff ff 9a call 4c <leaf_call+0x4c> ; |
1e8: 01 00 00 00 nop ; /
1ec: 82 10 20 02 mov 2, %g1 ! 2 <leaf_call+0x2> ; \
1f0: c2 27 a7 db st %g1, [ %fp + 0x7db ] ; |
1f4: 82 10 20 03 mov 3, %g1 ; |
1f8: c2 27 a7 df st %g1, [ %fp + 0x7df ] ; |
1fc: 03 00 00 00 sethi %hi(0), %g1 ; | put together first local struct A
200: 82 10 60 00 mov %g1, %g1 ! 0 <leaf_call> ; |
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
2e8: 8d a0 00 28 fmovs %f8, %f6 ; / arg 2 (first struct A) (f -> fp reg, (f{0,2,4} skipped))
2ec: 91 a0 00 4a fmovd %f10, %f8 ; \ (d -> fp reg d8)
2f0: 9a 10 00 04 mov %g4, %o5 ; / arg 3 (first struct B) (l -> int reg, (o{3,4} skipped))
2f4: a5 a0 00 2c fmovs %f12, %f18 ; (part of) arg 6 (second struct A) (f -> fp reg, (f[10-16] skipped))
2f8: a9 a0 00 4e fmovd %f14, %f20 ; (part of) arg 7 (second struct B) (d -> fp reg d20))
2fc: 40 00 00 00 call 2fc <main+0x124> ; call nonleaf_call (objdump not from final link but .o)
300: 01 00 00 00 nop ; branch delay slot
304: 82 10 20 00 clr %g1 ! 0 <leaf_call> ; \
308: 83 38 60 00 sra %g1, 0, %g1 ; / return value
30c: b0 10 00 01 mov %g1, %i0 ; \
310: 81 cf e0 08 rett %i7 + 8 ; | epilog
314: 01 00 00 00 nop ; | branch delay slot
; ---------- passing structs with mixed 8-byte parts ---------->
;
; struct A { int i; float f; };
; struct B { float f; char c; };
; struct C { float f; short s, t; };
; struct D { short s; float f; };
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
38: c6 27 a8 93 st %g3, [ %fp + 0x893 ]
3c: c8 77 a8 97 stx %g4, [ %fp + 0x897 ]
40: d7 27 a8 9b st %f11, [ %fp + 0x89b ]
44: 81 cf e0 08 rett %i7 + 8
48: 01 00 00 00 nop
4c: ae 03 c0 17 add %o7, %l7, %l7
50: 81 c3 e0 08 retl
54: 01 00 00 00 nop
0000000000000058 <main>:
58: 9d e3 bf 10 save %sp, -240, %sp ; prolog
5c: 2f 00 00 00 sethi %hi(0), %l7 ; |
60: ae 05 e0 00 add %l7, 0, %l7 ! 0 <leaf_call> ; | @@@ unsure, call to some code stub adding o7 to l7
64: 7f ff ff fa call 4c <leaf_call+0x4c> ; |
68: 01 00 00 00 nop ; /
6c: c0 27 a7 df clr [ %fp + 0x7df ] ; \
70: 03 00 00 00 sethi %hi(0), %g1 ; |
74: 82 10 60 00 mov %g1, %g1 ! 0 <leaf_call> ; |
78: c2 5d c0 01 ldx [ %l7 + %g1 ], %g1 ; | put together local struct A
7c: d1 00 40 00 ld [ %g1 ], %f8 ; |
80: d1 27 a7 e3 st %f8, [ %fp + 0x7e3 ] ; /
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
10c: 92 10 00 02 mov %g2, %o1 ; arg 1 (int part)
110: 89 a0 00 2a fmovs %f10, %f4 ; arg 2 (fp part)
114: 94 10 00 03 mov %g3, %o2 ; arg 2 (int part)
118: 96 10 00 04 mov %g4, %o3 ; arg 3 (int part)
11c: 8f a0 00 2b fmovs %f11, %f7 ; arg 3 (fp part)
120: 40 00 00 00 call 120 <main+0xc8> ; call nonleaf_call (objdump not from final link but .o)
124: 01 00 00 00 nop ; branch delay slot
128: 82 10 20 00 clr %g1 ! 0 <leaf_call> ; \
12c: 83 38 60 00 sra %g1, 0, %g1 ; / return value
130: b0 10 00 01 mov %g1, %i0 ; \
134: 81 cf e0 08 rett %i7 + 8 ; | epilog
138: 01 00 00 00 nop ; | branch delay slot
; ---------- 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; };
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
38: e1 27 a8 8f st %f16, [ %fp + 0x88f ]
3c: e3 27 a8 93 st %f17, [ %fp + 0x893 ]
40: e5 27 a8 97 st %f18, [ %fp + 0x897 ]
44: 81 cf e0 08 rett %i7 + 8
48: 01 00 00 00 nop
4c: ae 03 c0 17 add %o7, %l7, %l7
50: 81 c3 e0 08 retl
54: 01 00 00 00 nop
0000000000000058 <main>:
58: 9d e3 be b0 save %sp, -336, %sp ; prolog
5c: 2f 00 00 00 sethi %hi(0), %l7 ; |
60: ae 05 e0 00 add %l7, 0, %l7 ! 0 <leaf_call> ; | @@@ unsure, call to some code stub adding o7 to l7
64: 7f ff ff fa call 4c <leaf_call+0x4c> ; |
68: 01 00 00 00 nop ; /
6c: 03 00 00 00 sethi %hi(0), %g1 ; \
70: 82 10 60 00 mov %g1, %g1 ! 0 <leaf_call> ; |
74: c2 5d c0 01 ldx [ %l7 + %g1 ], %g1 ; | put together local struct A
78: d1 00 40 00 ld [ %g1 ], %f8 ; |
7c: d1 27 a7 e3 st %f8, [ %fp + 0x7e3 ] ; /
80: 03 00 00 00 sethi %hi(0), %g1 ; \
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
1b0: 87 a0 00 2e fmovs %f14, %f3 ; / second float
1b4: 89 a0 00 2f fmovs %f15, %f4 ; \ first float
1b8: 8b a0 00 30 fmovs %f16, %f5 ; | arg 2 (struct C) second float
1bc: 8d a0 00 31 fmovs %f17, %f6 ; / third float
1c0: 91 a0 00 52 fmovd %f18, %f8 ; arg 3 (entire struct D, single field double)
1c4: 40 00 00 00 call 1c4 <main+0x16c> ; call nonleaf_call (objdump not from final link but .o)
1c8: 01 00 00 00 nop ; branch delay slot
1cc: 82 10 20 00 clr %g1 ! 0 <leaf_call> ; \
1d0: 83 38 60 00 sra %g1, 0, %g1 ; / return value
1d4: b0 10 00 01 mov %g1, %i0 ; \
1d8: 81 cf e0 08 rett %i7 + 8 ; | epilog
1dc: 01 00 00 00 nop ; | branch delay slot
; ---------- passing only unions with only fp parts ---------->
;
; union A { float a; };
; union B { float a, b; };
; union C { float a, b, c; };
; union D { double a; };
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
4c: 82 08 60 00 and %g1, 0, %g1
50: 82 10 40 04 or %g1, %g4, %g1
54: c2 27 a8 8f st %g1, [ %fp + 0x88f ]
58: 81 cf e0 08 rett %i7 + 8
5c: 01 00 00 00 nop
60: ae 03 c0 17 add %o7, %l7, %l7
64: 81 c3 e0 08 retl
68: 01 00 00 00 nop
000000000000006c <main>:
6c: 9d e3 bf 10 save %sp, -240, %sp ; prolog
70: 2f 00 00 00 sethi %hi(0), %l7 ; |
74: ae 05 e0 00 add %l7, 0, %l7 ! 0 <leaf_call> ; | @@@ unsure, call to some code stub adding o7 to l7
78: 7f ff ff fa call 60 <leaf_call+0x60> ; |
7c: 01 00 00 00 nop ; /
80: 03 00 00 00 sethi %hi(0), %g1 ; \
84: 82 10 60 00 mov %g1, %g1 ! 0 <leaf_call> ; |
88: c2 5d c0 01 ldx [ %l7 + %g1 ], %g1 ; | put together local union A
8c: d1 00 40 00 ld [ %g1 ], %f8 ; |
90: d1 27 a7 e3 st %f8, [ %fp + 0x7e3 ] ; /
94: 03 00 00 00 sethi %hi(0), %g1 ; \
dyncall/doc/disas_examples/sparc64.sparc64.disas view on Meta::CPAN
128: 90 10 00 03 mov %g3, %o0 ; arg 0 |
12c: 92 10 00 02 mov %g2, %o1 ; arg 1 | note: all left-justified
130: 94 10 00 01 mov %g1, %o2 ; arg 2 |
134: 96 10 00 04 mov %g4, %o3 ; arg 3
138: 98 10 00 05 mov %g5, %o4 ; arg 4
13c: 40 00 00 00 call 13c <main+0xd0> ; call nonleaf_call (objdump not from final link but .o)
140: 01 00 00 00 nop ; branch delay slot
144: 82 10 20 00 clr %g1 ! 0 <leaf_call> ; \
148: 83 38 60 00 sra %g1, 0, %g1 ; / return value
14c: b0 10 00 01 mov %g1, %i0 ; \
150: 81 cf e0 08 rett %i7 + 8 ; | epilog
154: 01 00 00 00 nop ; | branch delay slot
; ---------- returning structs by value ---------->
;
; struct Small { char x; };
; struct Big { long long i,j,k,l; long m; }; /* bigger than 32b */
;
; struct Small f0()
dyncall/doc/disas_examples/x64.sysv.disas view on Meta::CPAN
d: 89 55 f4 mov %edx,-0xc(%rbp)
10: 89 4d f0 mov %ecx,-0x10(%rbp)
13: 44 89 45 ec mov %r8d,-0x14(%rbp)
17: 44 89 4d e8 mov %r9d,-0x18(%rbp)
1b: 89 45 e4 mov %eax,-0x1c(%rbp)
1e: 5d pop %rbp
1f: c3 retq
0000000000000020 <nonleaf_call>:
20: 55 push %rbp ; |
21: 48 89 e5 mov %rsp,%rbp ; | prolog
24: 48 83 ec 40 sub $0x40,%rsp ; | open frame *with* static alloca() size included
28: 8b 45 18 mov 0x18(%rbp),%eax ; unsure... get stack param from prev frame into some scratch reg... but why? see below @@@
2b: 44 8b 55 10 mov 0x10(%rbp),%r10d ; unsure... get stack param from prev frame into some scratch reg... but why? see below @@@
2f: 89 7d fc mov %edi,-0x4(%rbp) ; in arg 0 -> local area (as temp store)
32: 89 75 f8 mov %esi,-0x8(%rbp) ; in arg 1 -> local area (as temp store)
35: 89 55 f4 mov %edx,-0xc(%rbp) ; in arg 2 -> local area (as temp store)
38: 89 4d f0 mov %ecx,-0x10(%rbp) ; in arg 3 -> local area (as temp store)
3b: 44 89 45 ec mov %r8d,-0x14(%rbp) ; in arg 4 -> local area (as temp store)
3f: 44 89 4d e8 mov %r9d,-0x18(%rbp) ; in arg 5 -> local area (as temp store)
43: c6 45 d0 4c movb $0x4c,-0x30(%rbp) ; 'L' -> local area (of alloca()'d space)
dyncall/doc/disas_examples/x64.sysv.disas view on Meta::CPAN
4d: 8b 55 f0 mov -0x10(%rbp),%edx ; arg 2
50: 8b 4d ec mov -0x14(%rbp),%ecx ; arg 3
53: 44 8b 45 e8 mov -0x18(%rbp),%r8d ; arg 4
57: 44 8b 4d 10 mov 0x10(%rbp),%r9d ; arg 5 (fetched from prev frame's param area - behind return addr on 16b aligned stack)
5b: 44 8b 5d 18 mov 0x18(%rbp),%r11d ; arg 6 (fetched from prev frame's param area), and ...
5f: 44 89 1c 24 mov %r11d,(%rsp) ; ... "pushed" onto stack
63: 44 89 55 cc mov %r10d,-0x34(%rbp) ; unsure... write something to local area @@@?
67: 89 45 c8 mov %eax,-0x38(%rbp) ; unsure... write something to local area @@@?
6a: e8 91 ff ff ff callq 0 <leaf_call> ; push return addr and call
6f: 48 83 c4 40 add $0x40,%rsp ; |
73: 5d pop %rbp ; | epilog
74: c3 retq ; |
75: 66 66 2e 0f 1f 84 00 nopw %cs:0x0(%rax,%rax,1) ; garbage data
7c: 00 00 00 00 ; garbage data
0000000000000080 <main>:
80: 55 push %rbp ; |
81: 48 89 e5 mov %rsp,%rbp ; | prolog
84: 48 83 ec 20 sub $0x20,%rsp ; |
88: 31 ff xor %edi,%edi ; arg 0
8a: be 01 00 00 00 mov $0x1,%esi ; arg 1
8f: ba 02 00 00 00 mov $0x2,%edx ; arg 2
94: b9 03 00 00 00 mov $0x3,%ecx ; arg 3
99: 41 b8 04 00 00 00 mov $0x4,%r8d ; arg 4
9f: 41 b9 05 00 00 00 mov $0x5,%r9d ; arg 5
a5: b8 06 00 00 00 mov $0x6,%eax ; unsure... see below @@@?
aa: 41 ba 07 00 00 00 mov $0x7,%r10d ; unsure... see below @@@?
b0: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) ; unsure... write 0 to local area @@@?
b7: c7 04 24 06 00 00 00 movl $0x6,(%rsp) ; "push" arg6 onto stack
be: c7 44 24 08 07 00 00 00 movl $0x7,0x8(%rsp) ; "push" arg7 onto stack
c6: 44 89 55 f8 mov %r10d,-0x8(%rbp) ; unsure... write something to local area @@@?
ca: 89 45 f4 mov %eax,-0xc(%rbp) ; unsure... write something to local area @@@?
cd: e8 4e ff ff ff callq 20 <nonleaf_call> ; push return addr and call
d2: 31 c0 xor %eax,%eax ; return value
d4: 48 83 c4 20 add $0x20,%rsp ; |
d8: 5d pop %rbp ; | epilog
d9: c3 retq ; |
; output from arch_linux-2011.08.19-x64 w/ gcc 4.6.1 (w/ alloca(220) instead of 10)
0000000000000000 <leaf_call>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 89 7d fc mov %edi,-0x4(%rbp)
dyncall/doc/disas_examples/x64.sysv.disas view on Meta::CPAN
201936: 89 75 e8 mov %esi,-0x18(%rbp)
201939: 89 55 e4 mov %edx,-0x1c(%rbp)
20193c: 89 4d e0 mov %ecx,-0x20(%rbp)
20193f: 5d pop %rbp
201940: c3 retq
201941: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0(%rax,%rax,1)
20194b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
0000000000201950 <nonleaf_call>:
201950: 55 push %rbp ; |
201951: 48 89 e5 mov %rsp,%rbp ; | prolog
201954: 53 push %rbx ; |
201955: 48 81 ec 18 01 00 00 sub $0x118,%rsp ; | open frame *with* static alloca() size included
20195c: 8b 45 20 mov 0x20(%rbp),%eax ; unsure... stack param from prev frame into some scratch reg... but why? see below @@@
20195f: 4c 8d 55 10 lea 0x10(%rbp),%r10 ; ptr to struct on stack -> r10
201963: 89 7d f4 mov %edi,-0xc(%rbp) ; |
201966: 89 75 f0 mov %esi,-0x10(%rbp) ; |
201969: 89 55 ec mov %edx,-0x14(%rbp) ; |
20196c: 89 4d e8 mov %ecx,-0x18(%rbp) ; | in args (regs) -> local area (as temp store, mem order 8,4,3,2,1,0)
20196f: 44 89 45 e4 mov %r8d,-0x1c(%rbp) ; |
201973: 44 89 4d e0 mov %r9d,-0x20(%rbp) ; |
dyncall/doc/disas_examples/x64.sysv.disas view on Meta::CPAN
2019a3: 44 89 8d f8 fe ff ff mov %r9d,-0x108(%rbp) ; 'free' r9, temp store content
2019aa: 4d 89 d1 mov %r10,%r9 ; arg 4 (A.l)
2019ad: 8b 9d fc fe ff ff mov -0x104(%rbp),%ebx ; |
2019b3: 89 1c 24 mov %ebx,(%rsp) ; / arg 5 (fetch from temp store, pushed) pointless, could've been pushed, directly
2019b6: 8b 9d f8 fe ff ff mov -0x108(%rbp),%ebx ; \
2019bc: 89 5c 24 08 mov %ebx,0x8(%rsp) ; | arg 6 (fetch from temp store, pushed) pointless, could've been pushed, directly
2019c0: 89 85 f4 fe ff ff mov %eax,-0x10c(%rbp) ; unsure... write something to local area @@@?
2019c6: e8 55 ff ff ff callq 201920 <leaf_call> ; push return addr and call
2019cb: 48 81 c4 18 01 00 00 add $0x118,%rsp ; |
2019d2: 5b pop %rbx ; |
2019d3: 5d pop %rbp ; | epilog
2019d4: c3 retq ; |
2019d5: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0(%rax,%rax,1) ; garbage data
2019df: 90 nop ; garbage data
00000000002019e0 <main>:
2019e0: 55 push %rbp ; |
2019e1: 48 89 e5 mov %rsp,%rbp ; | prolog
2019e4: 48 83 ec 30 sub $0x30,%rsp ; |
2019e8: 31 ff xor %edi,%edi ; arg 0
2019ea: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) ; unsure... write 0 to local area @@@?
2019f1: c7 45 e8 05 00 00 00 movl $0x5,-0x18(%rbp) ; | field i
2019f8: c7 45 ec 06 00 00 00 movl $0x6,-0x14(%rbp) ; | fill struct A (local area) field j
2019ff: 48 c7 45 f0 07 00 00 00 movq $0x7,-0x10(%rbp) ; | field l
201a07: be 01 00 00 00 mov $0x1,%esi ; arg 1
201a0c: ba 02 00 00 00 mov $0x2,%edx ; arg 2
201a11: b9 03 00 00 00 mov $0x3,%ecx ; arg 3
201a16: 41 b8 04 00 00 00 mov $0x4,%r8d ; arg 4
201a1c: 48 8d 45 e8 lea -0x18(%rbp),%rax ; |
201a20: 4c 8b 08 mov (%rax),%r9 ; |
201a23: 4c 89 0c 24 mov %r9,(%rsp) ; | arg 5 (struct, pushed onto stack, as not enough regs)
201a27: 48 8b 40 08 mov 0x8(%rax),%rax ; |
201a2b: 48 89 44 24 08 mov %rax,0x8(%rsp) ; |
201a30: 41 b9 08 00 00 00 mov $0x8,%r9d ; arg 6 (in reg)
201a36: c7 44 24 10 09 00 00 00 movl $0x9,0x10(%rsp) ; arg 7 (pushed)
201a3e: e8 0d ff ff ff callq 201950 <nonleaf_call> ; push return addr and call
201a43: 31 c0 xor %eax,%eax ; return value
201a45: 48 83 c4 30 add $0x30,%rsp ; |
201a49: 5d pop %rbp ; | epilog
201a4a: c3 retq ; |
; ---------- structs by value, complex example (multiple structs, partly passed via regs) ---------->
;
; #include <stdlib.h>
;
; struct A { int i, j; float f; };
; struct B { double d; long long l; };
;
dyncall/doc/disas_examples/x64.sysv.disas view on Meta::CPAN
20198c: 44 89 45 a4 mov %r8d,-0x5c(%rbp)
201990: 5d pop %rbp
201991: c3 retq
201992: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0(%rax,%rax,1)
20199c: 0f 1f 40 00 nopl 0x0(%rax)
00000000002019a0 <nonleaf_call>:
2019a0: 55 push %rbp ; |
2019a1: 48 89 e5 mov %rsp,%rbp ; |
2019a4: 41 57 push %r15 ; |
2019a6: 41 56 push %r14 ; | prolog
2019a8: 41 54 push %r12 ; |
2019aa: 53 push %rbx ; |
2019ab: 48 81 ec 70 01 00 00 sub $0x170,%rsp ; | open frame *with* static alloca() size included
2019b2: 8b 45 38 mov 0x38(%rbp),%eax ; unsure... get last (15) stack param from prev frame into some scratch reg... but why? see below @@@
2019b5: 44 8b 55 30 mov 0x30(%rbp),%r10d ; unsure... get one to last (14) stack param from prev frame into some scratch reg... but why? see below @@@
2019b9: 4c 8d 5d 20 lea 0x20(%rbp),%r11 ; ptr to struct B on stack -> rbx
2019bd: 48 8d 5d 10 lea 0x10(%rbp),%rbx ; ptr to struct A on stack -> r11
2019c1: 48 89 55 c0 mov %rdx,-0x40(%rbp) ; | \ i, j
2019c5: f3 0f 11 45 c8 movss %xmm0,-0x38(%rbp) ; | / reassemble first struct A in mem (local area) f
2019ca: 48 8b 55 c0 mov -0x40(%rbp),%rdx ; . \ pointless reload of rdx w/ same val from same addr
dyncall/doc/disas_examples/x64.sysv.disas view on Meta::CPAN
201a69: 44 8b b5 9c fe ff ff mov -0x164(%rbp),%r14d ; \
201a70: 44 89 74 24 10 mov %r14d,0x10(%rsp) ; / arg 7 (pushed, aligned)
201a75: 44 8b b5 98 fe ff ff mov -0x168(%rbp),%r14d ; \
201a7c: 44 89 74 24 18 mov %r14d,0x18(%rsp) ; / arg 8 (pushed, aligned)
201a81: 89 85 94 fe ff ff mov %eax,-0x16c(%rbp) ; unsure... write something to local area @@@?
201a87: 44 89 95 90 fe ff ff mov %r10d,-0x170(%rbp) ; unsure... write something to local area @@@?
201a8e: e8 ad fe ff ff callq 201940 <leaf_call> ; push return addr and call
201a93: 48 81 c4 70 01 00 00 add $0x170,%rsp ; |
201a9a: 5b pop %rbx ; |
201a9b: 41 5c pop %r12 ; |
201a9d: 41 5e pop %r14 ; | epilog
201a9f: 41 5f pop %r15 ; |
201aa1: 5d pop %rbp ; |
201aa2: c3 retq ; |
201aa3: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0(%rax,%rax,1) ; garbage data
201aad: 0f 1f 00 nopl (%rax) ; garbage data
0000000000201ab0 <main>:
201ab0: 55 push %rbp ; |
201ab1: 48 89 e5 mov %rsp,%rbp ; | prolog
201ab4: 48 81 ec 80 00 00 00 sub $0x80,%rsp ; |
201abb: 31 ff xor %edi,%edi ; arg 0
201abd: f2 0f 10 05 2b ea ff ff movsd -0x15d5(%rip),%xmm0 ; not arg: prep to fill struct B field d (12.0)
201ac5: f3 0f 10 0d 2f ea ff ff movss -0x15d1(%rip),%xmm1 ; not arg: prep to fill struct A field f (11.f)
201acd: f2 0f 10 15 13 ea ff ff movsd -0x15ed(%rip),%xmm2 ; not arg: prep to fill struct B field d (5.0)
201ad5: f3 0f 10 1d 1b ea ff ff movss -0x15e5(%rip),%xmm3 ; not arg: prep to fill struct A field f (4.f)
201add: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) ; unsure... write 0 to local area @@@?
201ae4: c7 45 f0 02 00 00 00 movl $0x2,-0x10(%rbp) ; \ field i
201aeb: c7 45 f4 03 00 00 00 movl $0x3,-0xc(%rbp) ; | fill first struct A (local area) field j
201af2: f3 0f 11 5d f8 movss %xmm3,-0x8(%rbp) ; / field f
dyncall/doc/disas_examples/x64.sysv.disas view on Meta::CPAN
201b69: 48 8d 45 c0 lea -0x40(%rbp),%rax ; \ \
201b6d: 4c 8b 10 mov (%rax),%r10 ; | | d (aligned)
201b70: 4c 89 54 24 10 mov %r10,0x10(%rsp) ; | arg 7 (last struct B, *pushed* by value) /
201b75: 48 8b 40 08 mov 0x8(%rax),%rax ; | \ l
201b79: 48 89 44 24 18 mov %rax,0x18(%rsp) ; / /
201b7e: c7 44 24 20 0e 00 00 00 movl $0xe,0x20(%rsp) ; arg 8 (pushed, aligned)
201b86: c7 44 24 28 0f 00 00 00 movl $0xf,0x28(%rsp) ; arg 9 (pushed, aligned)
201b8e: e8 0d fe ff ff callq 2019a0 <nonleaf_call> ; push return addr and call
201b93: 31 c0 xor %eax,%eax ; return value
201b95: 48 81 c4 80 00 00 00 add $0x80,%rsp ; |
201b9c: 5d pop %rbp ; | epilog
201b9d: c3 retq ; |
; ---------- returning tiny struct by value (passes via regs) ---------->
;
; struct A { unsigned char a; };
;
; struct A call(unsigned char c)
; {
dyncall/doc/disas_examples/x64.sysv.disas view on Meta::CPAN
; struct A a = call(123);
; return 0;
; }
; output from freebsd-12.2-x64 w/ clang 10.0.1
00000000002018f0 <call>:
2018f0: 55 push %rbp ; |
2018f1: 48 89 e5 mov %rsp,%rbp ; | prolog
2018f4: 40 88 7d f7 mov %dil,-0x9(%rbp) ; in arg 0 -> local area, ... | a bit pointless, could've been
2018f8: 8a 45 f7 mov -0x9(%rbp),%al ; ... from local area -> eax, then ... | moved to -0x8(%rbp) directly
2018fb: 88 45 f8 mov %al,-0x8(%rbp) ; ... to struct in local area
2018fe: 8a 45 f8 mov -0x8(%rbp),%al ; return value
201901: 5d pop %rbp ; | epilog
201902: c3 retq ; |
201903: 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:0x0(%rax,%rax,1) ; garbage data
20190d: 0f 1f 00 nopl (%rax) ; garbage data
0000000000201910 <main>:
201910: 55 push %rbp ; |
201911: 48 89 e5 mov %rsp,%rbp ; | prolog
201914: 48 83 ec 10 sub $0x10,%rsp ; |
201918: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) ; @@@ unsure, clears dword of local area
20191f: bf 7b 00 00 00 mov $0x7b,%edi ; arg 0 (123)
201924: e8 c7 ff ff ff callq 2018f0 <call> ; push return addr and call
201929: 31 c9 xor %ecx,%ecx ; return value prep (a bit pointless)
20192b: 88 45 f8 mov %al,-0x8(%rbp) ; write struct data to local area (123)
20192e: 89 c8 mov %ecx,%eax ; return value
201930: 48 83 c4 10 add $0x10,%rsp ; |
201934: 5d pop %rbp ; | epilog
201935: c3 retq ; |
; output from freebsd-12.2-x64 w/ gcc 10.3.0
00000000004007a5 <call>:
4007a5: 55 push %rbp ; |
4007a6: 48 89 e5 mov %rsp,%rbp ; | prolog
4007a9: 89 f8 mov %edi,%eax ; in arg 0 ...
4007ab: 88 45 fc mov %al,-0x4(%rbp) ; ... -> struct in local area
4007ae: 0f b6 45 fc movzbl -0x4(%rbp),%eax ; return value (entire struct in eax)
4007b2: 5d pop %rbp ; | epilog
4007b3: c3 retq ; |
00000000004007b4 <main>:
4007b4: 55 push %rbp ; |
4007b5: 48 89 e5 mov %rsp,%rbp ; | prolog
4007b8: 48 83 ec 10 sub $0x10,%rsp ; |
4007bc: bf 7b 00 00 00 mov $0x7b,%edi ; arg 0 (123)
4007c1: e8 df ff ff ff callq 4007a5 <call> ; push return addr and call
4007c6: 88 45 ff mov %al,-0x1(%rbp) ; write struct data to local area (123)
4007c9: b8 00 00 00 00 mov $0x0,%eax ; return value
4007ce: c9 leaveq ; |
4007cf: c3 retq ; | epilog
; ---------- 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" {
;
dyncall/doc/disas_examples/x64.sysv.disas view on Meta::CPAN
; f2(n);
; a -= 12;
; }
; }
; output from freebsd-12.2-x64 w/ clang 10.0.1
0000000000000000 <f1>:
0: 55 push %rbp ; | prolog
1: 48 89 e5 mov %rsp,%rbp ; |
4: 89 7d f8 mov %edi,-0x8(%rbp) ; local copy of trivial struct
7: 5d pop %rbp ; |
8: c3 retq ; | epilog
0000000000000010 <f2>:
10: 55 push %rbp ; | prolog
11: 48 89 e5 mov %rsp,%rbp ; /
14: 5d pop %rbp ; \ note: no local copy as non-trivial
15: c3 retq ; | epilog
0000000000000020 <f>:
20: 55 push %rbp ; |
21: 48 89 e5 mov %rsp,%rbp ; | prolog
24: 48 83 ec 20 sub $0x20,%rsp ; /
28: 48 8d 7d f0 lea -0x10(%rbp),%rdi ; \ this ptr (NULL)
2c: e8 00 00 00 00 callq 31 <f+0x11> ; | NonTrivial::NonTrivial() / ctor
31: c7 45 ec 01 00 00 00 movl $0x1,-0x14(%rbp) ; a = 1
38: 8b 45 ec mov -0x14(%rbp),%eax ; |
3b: 83 c0 7b add $0x7b,%eax ; | a += 123
3e: 89 45 ec mov %eax,-0x14(%rbp) ; /
41: 8b 45 f8 mov -0x8(%rbp),%eax ; \
44: 89 45 e8 mov %eax,-0x18(%rbp) ; / local copy of t (struct Trivial)
47: 8b 7d e8 mov -0x18(%rbp),%edi ; f1 arg 0 (struct Trivial), via reg as small struct
dyncall/doc/disas_examples/x64.sysv.disas view on Meta::CPAN
55: 89 45 ec mov %eax,-0x14(%rbp) ; /
58: 48 8d 7d e0 lea -0x20(%rbp),%rdi ; \ ptr to dest of copy of n
5c: 48 8d 75 f0 lea -0x10(%rbp),%rsi ; | copy n ptr to n
60: e8 00 00 00 00 callq 65 <f+0x45> ; / NonTrivial::NonTrivial(const NonTrivial&) / copy ctor
65: 48 8d 7d e0 lea -0x20(%rbp),%rdi ; f2 arg 0 (ptr to copy of struct NonTrivial), via ptr as non-trivial
69: e8 00 00 00 00 callq 6e <f+0x4e> ; call f2(struct NonTrivial)
6e: 8b 45 ec mov -0x14(%rbp),%eax ; |
71: 83 e8 0c sub $0xc,%eax ; | a -= 12
74: 89 45 ec mov %eax,-0x14(%rbp) ; /
77: 48 83 c4 20 add $0x20,%rsp ; \
7b: 5d pop %rbp ; | epilog
7c: c3 retq ; |
; ... 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) { } };
dyncall/doc/disas_examples/x64.sysv.disas view on Meta::CPAN
2019fe: 48 89 4d f8 mov %rcx,-0x8(%rbp)
201a02: 48 89 45 f0 mov %rax,-0x10(%rbp)
201a06: e8 85 00 00 00 callq 201a90 <_ZN10NonTrivialC2Ev>
201a0b: 48 8b 45 f0 mov -0x10(%rbp),%rax
201a0f: 48 83 c4 10 add $0x10,%rsp
201a13: 5d pop %rbp
201a14: c3 retq
0000000000201a20 <f>:
201a20: 55 push %rbp ; |
201a21: 48 89 e5 mov %rsp,%rbp ; | prolog
201a24: 48 83 ec 10 sub $0x10,%rsp ; |
201a28: c7 45 fc 01 00 00 00 movl $0x1,-0x4(%rbp) ; a = 1
201a2f: 8b 45 fc mov -0x4(%rbp),%eax ; |
201a32: 83 c0 7b add $0x7b,%eax ; | a += 123
201a35: 89 45 fc mov %eax,-0x4(%rbp) ; |
201a38: e8 83 ff ff ff callq 2019c0 <f1> ; call f1()
201a3d: 89 45 f8 mov %eax,-0x8(%rbp) ; retval via reg, as small struct
201a40: 8b 45 fc mov -0x4(%rbp),%eax ; |
201a43: 83 e8 7b sub $0x7b,%eax ; | a -= 123
201a46: 89 45 fc mov %eax,-0x4(%rbp) ; |
201a49: 48 8d 7d f0 lea -0x10(%rbp),%rdi ; ptr to space to hold non-triv retval
201a4d: e8 9e ff ff ff callq 2019f0 <_Z2f2v> ; call f2()
201a52: 8b 45 fc mov -0x4(%rbp),%eax ; |
201a55: 83 e8 0c sub $0xc,%eax ; | a-= 12
201a58: 89 45 fc mov %eax,-0x4(%rbp) ; /
201a5b: 48 83 c4 10 add $0x10,%rsp ; \
201a5f: 5d pop %rbp ; | epilog
201a60: c3 retq ; |
; ---------- structs by value, struct passed as vararg ---------->
;
; #include <stdlib.h>
; #include <stdarg.h>
;
dyncall/doc/disas_examples/x64.sysv.disas view on Meta::CPAN
a: 89 55 f4 mov %edx,-0xc(%rbp) ;
d: 89 4d f0 mov %ecx,-0x10(%rbp) ;
10: 5d pop %rbp ;
11: c3 retq ;
12: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) ;
19: 00 00 00 ;
1c: 0f 1f 40 00 nopl 0x0(%rax) ;
0000000000000020 <nonleaf_call>:
20: 55 push %rbp ; |
21: 48 89 e5 mov %rsp,%rbp ; | prolog
24: 53 push %rbx ; |
25: 48 81 ec 28 02 00 00 sub $0x228,%rsp ; | open frame *with* static alloca() size included
2c: 84 c0 test %al,%al ; test how many used xmm regs (= 0)
2e: 0f 29 bd f0 fe ff ff movaps %xmm7,-0x110(%rbp) ; |
35: 0f 29 b5 e0 fe ff ff movaps %xmm6,-0x120(%rbp) ; |
3c: 0f 29 ad d0 fe ff ff movaps %xmm5,-0x130(%rbp) ; |
43: 0f 29 a5 c0 fe ff ff movaps %xmm4,-0x140(%rbp) ; | spill xmm regs onto stack (none used by call, though)
4a: 0f 29 9d b0 fe ff ff movaps %xmm3,-0x150(%rbp) ; |
51: 0f 29 95 a0 fe ff ff movaps %xmm2,-0x160(%rbp) ; |
58: 0f 29 8d 90 fe ff ff movaps %xmm1,-0x170(%rbp) ; |
dyncall/doc/disas_examples/x64.sysv.disas view on Meta::CPAN
3d2: 45 89 4b 08 mov %r9d,0x8(%r11) ; 'push' arg 5, 'frees' r9 implicitly
3d6: 45 89 03 mov %r8d,(%r11) ; 'push' arg 6, 'frees' r8 implicitly
3d9: 45 31 c0 xor %r8d,%r8d ; |
3dc: 44 88 85 df fd ff ff mov %r8b,-0x221(%rbp) ; | number of used xmm registers (0) -> temp store (see below)
3e3: 49 89 c0 mov %rax,%r8 ; arg 4 (A.i, A.j) |
3e6: 4d 89 d1 mov %r10,%r9 ; arg 4 (A.l) | struct passed in regs, regardless of it being a vararg
3e9: 8a 85 df fd ff ff mov -0x221(%rbp),%al ; number of used xmm registers (upper bound, req for varargs)
3ef: e8 00 00 00 00 callq 3f4 <nonleaf_call+0x3d4> ; push return addr and call
3f4: 48 8d 65 f8 lea -0x8(%rbp),%rsp ; |
3f8: 5b pop %rbx ; |
3f9: 5d pop %rbp ; | epilog
3fa: c3 retq ; |
3fb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) ; garbage data
0000000000000400 <main>:
400: 55 push %rbp ; |
401: 48 89 e5 mov %rsp,%rbp ; | prolog
404: 48 83 ec 30 sub $0x30,%rsp ; |
408: 31 ff xor %edi,%edi ; arg 0
40a: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp) ; unsure... write 0 to local area @@@?
411: c7 45 e8 05 00 00 00 movl $0x5,-0x18(%rbp) ; | field i
418: c7 45 ec 06 00 00 00 movl $0x6,-0x14(%rbp) ; | fill struct A (local area) field j
41f: 48 c7 45 f0 07 00 00 00 movq $0x7,-0x10(%rbp) ; | field l
427: be 01 00 00 00 mov $0x1,%esi ; arg 1
42c: ba 02 00 00 00 mov $0x2,%edx ; arg 2
431: b9 03 00 00 00 mov $0x3,%ecx ; arg 3
436: 41 b8 04 00 00 00 mov $0x4,%r8d ; arg 4
dyncall/doc/disas_examples/x64.sysv.disas view on Meta::CPAN
440: 4c 8b 08 mov (%rax),%r9 ; |
443: 4c 89 0c 24 mov %r9,(%rsp) ; | arg 5 (struct, pushed onto stack, as not enough regs)
447: 48 8b 40 08 mov 0x8(%rax),%rax ; |
44b: 48 89 44 24 08 mov %rax,0x8(%rsp) ; |
450: 41 b9 08 00 00 00 mov $0x8,%r9d ; arg 6 (in reg)
456: c7 44 24 10 09 00 00 00 movl $0x9,0x10(%rsp) ; arg 7 (pushed)
45e: b0 00 mov $0x0,%al ; number of used xmm registers (upper bound, req for varargs)
460: e8 00 00 00 00 callq 465 <main+0x65> ; push return addr and call
465: 31 c0 xor %eax,%eax ; return value
467: 48 83 c4 30 add $0x30,%rsp ; |
46b: 5d pop %rbp ; | epilog
46c: c3 retq ; |
; vim: ft=asm
dyncall/doc/disas_examples/x64.win.disas view on Meta::CPAN
e$ = 128
f$ = 136
g$ = 144
h$ = 152
nonleaf_call PROC
mov DWORD PTR [rsp+32], r9d ; | |
mov DWORD PTR [rsp+24], r8d ; | |
mov DWORD PTR [rsp+16], edx ; | | spill
mov DWORD PTR [rsp+8], ecx ; | |
push rdi ; |
sub rsp, 80 ; | prolog
mov BYTE PTR x$[rsp], 76 ; 'L' -> local area (of local array's space)
lea rax, QWORD PTR x$[rsp+1] ; |
mov rdi, rax ; |
xor eax, eax ; | zero-init rest of local array's space
mov ecx, 9 ; |
rep stosb ; |
mov eax, DWORD PTR h$[rsp] ; arg 6 (fetched from caller's frame param area), and ...
mov DWORD PTR [rsp+48], eax ; ... "pushed" onto stack
mov eax, DWORD PTR g$[rsp] ; arg 5 (fetched from caller's frame param area), and ...
mov DWORD PTR [rsp+40], eax ; ... "pushed" onto stack
mov eax, DWORD PTR f$[rsp] ; arg 4 (fetched from caller's frame param area), and ...
mov DWORD PTR [rsp+32], eax ; ... "pushed" onto stack
mov r9d, DWORD PTR e$[rsp] ; arg 3
mov r8d, DWORD PTR d$[rsp] ; arg 2
mov edx, DWORD PTR c$[rsp] ; arg 1
mov ecx, DWORD PTR b$[rsp] ; arg 0
call leaf_call ; push return addr and call
add rsp, 80 ; |
pop rdi ; | epilog
ret 0 ; |
nonleaf_call ENDP
main PROC
sub rsp, 72 ; prolog
mov DWORD PTR [rsp+56], 7 ; "push" arg 7 onto stack
mov DWORD PTR [rsp+48], 6 ; "push" arg 6 onto stack
mov DWORD PTR [rsp+40], 5 ; "push" arg 5 onto stack
mov DWORD PTR [rsp+32], 4 ; "push" arg 4 onto stack
mov r9d, 3 ; arg 3
mov r8d, 2 ; arg 2
mov edx, 1 ; arg 1
xor ecx, ecx ; arg 0
call nonleaf_call ; push return addr and call
xor eax, eax ; return value
add rsp, 72 ; |
ret 0 ; | epilog
main ENDP
; ---------- structs by value, struct never in reg or on reg arg boundary ---------->
;
; 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)
; {
dyncall/doc/disas_examples/x64.win.disas view on Meta::CPAN
; }
; output from godbolt compiler explorer w/ msvc 19.0
r$ = 0
c$ = 32
call PROC
mov BYTE PTR [rsp+8], cl ; | spill
sub rsp, 24 ; | prolog
movzx eax, BYTE PTR c$[rsp] ; in arg 0 (fetched from spill area) -> eax, then ...
mov BYTE PTR r$[rsp], al ; ... -> struct in local area (top of stack, as leaf call and thus no reserved spill area)
movzx eax, BYTE PTR r$[rsp] ; reget same value into eax to return (small) struct via reg (a bit pointless to refetch)
add rsp, 24 ; |
ret 0 ; | epilog
call ENDP
a$ = 32
main PROC
sub rsp, 56 ; prolog
mov cl, 123 ; arg 0
call call ; push return addr and call
mov BYTE PTR a$[rsp], al ; write struct data to local area (123)
xor eax, eax ; return value
add rsp, 56 ; |
ret 0 ; | epilog
main ENDP
; ---------- 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" {
dyncall/doc/disas_examples/x64.win.disas view on Meta::CPAN
ret 0
f2 ENDP
a$ = 32
n$ = 36
t$ = 40
$T1 = 44
$T2 = 48
f PROC
$LN3:
sub rsp, 72 ; prolog
lea rcx, QWORD PTR n$[rsp] ; \ this ptr (NULL)
call NonTrivial::NonTrivial(void) ; | NonTrivial::NonTrivial() / ctor
mov DWORD PTR a$[rsp], 1 ; a = 1
mov eax, DWORD PTR a$[rsp] ; |
add eax, 123 ; | a += 123
mov DWORD PTR a$[rsp], eax ; /
mov ecx, DWORD PTR t$[rsp] ; f1 arg 0 (struct Trivial), via reg as small struct
call f1 ; call f1(struct Trivial)
mov eax, DWORD PTR a$[rsp] ; |
sub eax, 123 ; | a -= 123
dyncall/doc/disas_examples/x64.win.disas view on Meta::CPAN
mov QWORD PTR $T2[rsp], rax ; ... @@@
lea rdx, QWORD PTR n$[rsp] ; \ ptr to dest of copy of n
mov rcx, QWORD PTR $T2[rsp] ; | copy n ptr to n
call NonTrivial::NonTrivial(NonTrivial const &) ; / NonTrivial::NonTrivial(const NonTrivial&) / copy ctor
mov rcx, rax ; f2 arg 0 (ptr to copy of struct NonTrivial), via ptr as non-trivial
call f2 ; call f2(struct NonTrivial)
mov eax, DWORD PTR a$[rsp] ; |
sub eax, 12 ; | a -= 12
mov DWORD PTR a$[rsp], eax ; /
add rsp, 72 ; \
ret 0 ; | epilog
f ENDP
; ---------- 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" {
dyncall/doc/disas_examples/x64.win.disas view on Meta::CPAN
add rsp, 40
ret 0
NonTrivial f2(void) ENDP
a$ = 32
$T1 = 36
t$ = 40
n$ = 44
f PROC
$LN3:
sub rsp, 56 ; prolog
mov DWORD PTR a$[rsp], 1 ; a = 1
mov eax, DWORD PTR a$[rsp] ; |
add eax, 123 ; | a += 123
mov DWORD PTR a$[rsp], eax ; |
call f1 ; call f1()
mov DWORD PTR $T1[rsp], eax ;
mov eax, DWORD PTR $T1[rsp] ;
mov DWORD PTR t$[rsp], eax ;
mov eax, DWORD PTR a$[rsp] ; |
sub eax, 123 ; | a -= 123
mov DWORD PTR a$[rsp], eax ; |
lea rcx, QWORD PTR n$[rsp] ; ptr to space to hold non-triv retval
call NonTrivial f2(void) ; call f2()
mov eax, DWORD PTR a$[rsp] ; |
sub eax, 12 ; | a -= 12
mov DWORD PTR a$[rsp], eax ; /
add rsp, 56 ; \ epilog
ret 0 ; |
f ENDP
; ---------- structs by value, struct passed as vararg ---------->
;
; #include <stdlib.h>
; #include <stdarg.h>
;
dyncall/doc/disas_examples/x86.cdecl.disas view on Meta::CPAN
; output from arch_linux-2011.08.19-x86 w/ gcc 4.6.1
00000000 <leaf_call>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 5d pop %ebp
4: c3 ret
00000005 <nonleaf_call>:
5: 55 push %ebp ; |
6: 89 e5 mov %esp,%ebp ; | prolog
8: 83 ec 38 sub $0x38,%esp ; /
b: b8 10 00 00 00 mov $0x10,%eax ; \ |
10: 83 e8 01 sub $0x1,%eax ; | | creative way to move 250 to eax
13: 05 eb 00 00 00 add $0xeb,%eax ; | /
18: c7 45 f4 10 00 00 00 movl $0x10,-0xc(%ebp) ; | size comp wtf? \
1f: ba 00 00 00 00 mov $0x0,%edx ; | |
24: f7 75 f4 divl -0xc(%ebp) ; | | obviously fastest way to round to multiple of 16
27: 6b c0 10 imul $0x10,%eax,%eax ; | |
2a: 29 c4 sub %eax,%esp ; alloca(220) with size containing some padding computed above
2c: 8d 44 24 1c lea 0x1c(%esp),%eax ; |
dyncall/doc/disas_examples/x86.cdecl.disas view on Meta::CPAN
51: 8b 45 18 mov 0x18(%ebp),%eax ; | read in args 1-7 from prev frame's param area, and ...
54: 89 44 24 0c mov %eax,0xc(%esp) ; | ... "push" onto stack as arg 0-6
58: 8b 45 14 mov 0x14(%ebp),%eax ; |
5b: 89 44 24 08 mov %eax,0x8(%esp) ; |
5f: 8b 45 10 mov 0x10(%ebp),%eax ; |
62: 89 44 24 04 mov %eax,0x4(%esp) ; |
66: 8b 45 0c mov 0xc(%ebp),%eax ; |
69: 89 04 24 mov %eax,(%esp) ; |
6c: e8 fc ff ff ff call 6d <nonleaf_call+0x68> ; push return address and call leaf_call (objdump not from final link but .o)
71: c9 leave ; |
72: c3 ret ; | epilog
00000073 <main>:
73: 55 push %ebp ; |
74: 89 e5 mov %esp,%ebp ; |
76: 83 e4 f0 and $0xfffffff0,%esp ; | prolog
79: 83 ec 20 sub $0x20,%esp ; |
7c: c7 44 24 1c 07 00 00 00 movl $0x7,0x1c(%esp) ; arg 7 -> stack
84: c7 44 24 18 06 00 00 00 movl $0x6,0x18(%esp) ; arg 6 -> stack
8c: c7 44 24 14 05 00 00 00 movl $0x5,0x14(%esp) ; arg 5 -> stack
94: c7 44 24 10 04 00 00 00 movl $0x4,0x10(%esp) ; arg 4 -> stack
9c: c7 44 24 0c 03 00 00 00 movl $0x3,0xc(%esp) ; arg 3 -> stack
a4: c7 44 24 08 02 00 00 00 movl $0x2,0x8(%esp) ; arg 2 -> stack
ac: c7 44 24 04 01 00 00 00 movl $0x1,0x4(%esp) ; arg 1 -> stack
b4: c7 04 24 00 00 00 00 movl $0x0,(%esp) ; arg 0 -> stack
bb: e8 fc ff ff ff call bc <main+0x49> ; push return address and call nonleaf_call (objdump not from final link but .o)
c0: b8 00 00 00 00 mov $0x0,%eax ; return value
c5: c9 leave ; |
c6: c3 ret ; | epilog
; output from darwin-8.0.1-x86 w/ gcc 3.3
_leaf_call:
0: 55 pushl %ebp
1: 89 e5 movl %esp, %ebp
3: 83 ec 08 subl $8, %esp
6: c9 leave
7: c3 retl
_nonleaf_call:
8: 55 pushl %ebp ; |
9: 89 e5 movl %esp, %ebp ; | prolog
b: 83 ec 28 subl $40, %esp ; |
e: 81 ec e0 00 00 00 subl $224, %esp ; alloca(220) - with 4b padding
14: 8d 44 24 20 leal 32(%esp), %eax ; |
18: c6 00 4c movb $76, (%eax) ; / 'L' -> alloca()'d space
1b: 8b 45 24 movl 36(%ebp), %eax ; \
1e: 89 44 24 18 movl %eax, 24(%esp) ; |
22: 8b 45 20 movl 32(%ebp), %eax ; |
25: 89 44 24 14 movl %eax, 20(%esp) ; |
29: 8b 45 1c movl 28(%ebp), %eax ; |
2c: 89 44 24 10 movl %eax, 16(%esp) ; |
30: 8b 45 18 movl 24(%ebp), %eax ; | read in args 1-7 from prev frame's param area, and ...
33: 89 44 24 0c movl %eax, 12(%esp) ; | ... "push" onto stack as arg 0-6
37: 8b 45 14 movl 20(%ebp), %eax ; |
3a: 89 44 24 08 movl %eax, 8(%esp) ; |
3e: 8b 45 10 movl 16(%ebp), %eax ; |
41: 89 44 24 04 movl %eax, 4(%esp) ; |
45: 8b 45 0c movl 12(%ebp), %eax ; |
48: 89 04 24 movl %eax, (%esp) ; |
4b: e8 b0 ff ff ff calll -80 <_leaf_call> ; push return address and call
50: c9 leave ; |
51: c3 retl ; | epilog
52: 90 nop ;
53: 90 nop ;
_main:
54: 55 pushl %ebp ; |
55: 89 e5 movl %esp, %ebp ; | prolog
57: 83 ec 28 subl $40, %esp ; |
5a: c7 44 24 1c 07 00 00 00 movl $7, 28(%esp) ; arg 7 -> stack
62: c7 44 24 18 06 00 00 00 movl $6, 24(%esp) ; arg 6 -> stack
6a: c7 44 24 14 05 00 00 00 movl $5, 20(%esp) ; arg 5 -> stack
72: c7 44 24 10 04 00 00 00 movl $4, 16(%esp) ; arg 4 -> stack
7a: c7 44 24 0c 03 00 00 00 movl $3, 12(%esp) ; arg 3 -> stack
82: c7 44 24 08 02 00 00 00 movl $2, 8(%esp) ; arg 2 -> stack
8a: c7 44 24 04 01 00 00 00 movl $1, 4(%esp) ; arg 1 -> stack
92: c7 04 24 00 00 00 00 movl $0, (%esp) ; arg 0 -> stack
99: e8 6a ff ff ff calll -150 <_nonleaf_call> ; push return address and call
9e: b8 00 00 00 00 movl $0, %eax ; return value
a3: c9 leave ; |
a4: c3 retl ; | epilog
; output from freebsd-9.3-x86 w/ gcc 4.2.1
00000000 <leaf_call>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 5d pop %ebp
4: c3 ret
5: 8d 74 26 00 lea 0x0(%esi),%esi
9: 8d bc 27 00 00 00 00 lea 0x0(%edi),%edi
00000010 <nonleaf_call>:
10: 55 push %ebp ; |
11: 89 e5 mov %esp,%ebp ; | prolog
13: 83 ec 28 sub $0x28,%esp ; |
16: 81 ec f0 00 00 00 sub $0xf0,%esp ; alloca(220) - with padding for 16b alignment
1c: 8d 44 24 1c lea 0x1c(%esp),%eax ; |
20: 89 45 fc mov %eax,-0x4(%ebp) ; |
23: 8b 45 fc mov -0x4(%ebp),%eax ; |
26: 83 c0 0f add $0xf,%eax ; | start of alloca()'d memory -> eax, by ...
29: c1 e8 04 shr $0x4,%eax ; | ... using ebx and 2 pointless store/reads in local space as helper to align to 16b
2c: c1 e0 04 shl $0x4,%eax ; |
2f: 89 45 fc mov %eax,-0x4(%ebp) ; |
32: 8b 45 fc mov -0x4(%ebp),%eax ; |
dyncall/doc/disas_examples/x86.cdecl.disas view on Meta::CPAN
4d: 8b 45 18 mov 0x18(%ebp),%eax ; | read in args 1-7 from prev frame's param area, and ...
50: 89 44 24 0c mov %eax,0xc(%esp) ; | ... "push" onto stack as arg 0-6
54: 8b 45 14 mov 0x14(%ebp),%eax ; |
57: 89 44 24 08 mov %eax,0x8(%esp) ; |
5b: 8b 45 10 mov 0x10(%ebp),%eax ; |
5e: 89 44 24 04 mov %eax,0x4(%esp) ; |
62: 8b 45 0c mov 0xc(%ebp),%eax ; |
65: 89 04 24 mov %eax,(%esp) ; |
68: e8 fc ff ff ff call 69 <nonleaf_call+0x59> ; push return address and call leaf_call (objdump not from final link but .o)
6d: c9 leave ; |
6e: c3 ret ; | epilog
6f: 90 nop ;
00000070 <main>:
70: 8d 4c 24 04 lea 0x4(%esp),%ecx ; |
74: 83 e4 f0 and $0xfffffff0,%esp ; |
77: ff 71 fc pushl -0x4(%ecx) ; |
7a: 55 push %ebp ; | prolog
7b: 89 e5 mov %esp,%ebp ; |
7d: 51 push %ecx ; |
7e: 83 ec 24 sub $0x24,%esp ; |
81: c7 44 24 1c 07 00 00 00 movl $0x7,0x1c(%esp) ; arg 7 -> stack
89: c7 44 24 18 06 00 00 00 movl $0x6,0x18(%esp) ; arg 6 -> stack
91: c7 44 24 14 05 00 00 00 movl $0x5,0x14(%esp) ; arg 5 -> stack
99: c7 44 24 10 04 00 00 00 movl $0x4,0x10(%esp) ; arg 4 -> stack
a1: c7 44 24 0c 03 00 00 00 movl $0x3,0xc(%esp) ; arg 3 -> stack
a9: c7 44 24 08 02 00 00 00 movl $0x2,0x8(%esp) ; arg 2 -> stack
b1: c7 44 24 04 01 00 00 00 movl $0x1,0x4(%esp) ; arg 1 -> stack
b9: c7 04 24 00 00 00 00 movl $0x0,(%esp) ; arg 0 -> stack
c0: e8 fc ff ff ff call c1 <main+0x51> ; push return address and call leaf_call (objdump not from final link but .o)
c5: b8 00 00 00 00 mov $0x0,%eax ; return value
ca: 83 c4 24 add $0x24,%esp ; |
cd: 59 pop %ecx ; |
ce: 5d pop %ebp ; | epilog
cf: 8d 61 fc lea -0x4(%ecx),%esp ; |
d2: c3 ret ; |
; output from gentoo_linux-20191029-x86 w/ gcc 8.3.0
00000000 <leaf_call>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
dyncall/doc/disas_examples/x86.cdecl.disas view on Meta::CPAN
80: 74 05 je 87 <nonleaf_call+0x77>
82: e8 fc ff ff ff call 83 <nonleaf_call+0x73>
87: c9 leave
88: c3 ret
00000089 <main>:
89: 8d 4c 24 04 lea 0x4(%esp),%ecx ; |
8d: 83 e4 f0 and $0xfffffff0,%esp ; |
90: ff 71 fc pushl -0x4(%ecx) ; |
93: 55 push %ebp ; |
94: 89 e5 mov %esp,%ebp ; | prolog (with some stack protection check call, I think)
96: 51 push %ecx ; |
97: 83 ec 04 sub $0x4,%esp ; |
9a: e8 fc ff ff ff call 9b <main+0x12> ; | unsure@@@ call of stackguard stuff, maybe?. (objdump not from final link but .o)
9f: 05 01 00 00 00 add $0x1,%eax ; | ??? add 1 to ret val from unknown call
a4: 6a 07 push $0x7 ; arg 7 -> stack
a6: 6a 06 push $0x6 ; arg 6 -> stack
a8: 6a 05 push $0x5 ; arg 5 -> stack
aa: 6a 04 push $0x4 ; arg 4 -> stack
ac: 6a 03 push $0x3 ; arg 3 -> stack
ae: 6a 02 push $0x2 ; arg 2 -> stack
b0: 6a 01 push $0x1 ; arg 1 -> stack
b2: 6a 00 push $0x0 ; arg 0 -> stack
b4: e8 fc ff ff ff call b5 <main+0x2c> ; push return address and call nonleaf_call (objdump not from final link but .o)
b9: 83 c4 20 add $0x20,%esp ; ???
bc: b8 00 00 00 00 mov $0x0,%eax ; return value
c1: 8b 4d fc mov -0x4(%ebp),%ecx ; | ???
c4: c9 leave ; |
c5: 8d 61 fc lea -0x4(%ecx),%esp ; | epilog ???
c8: c3 ret ; |
; output from haiku w/ gcc 4.4.4
00000000 <leaf_call>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 5d pop %ebp
dyncall/doc/disas_examples/x86.cdecl.disas view on Meta::CPAN
; return 0;
; }
; output from godbolt compiler explorer w/ msvc 19.0
$T1 = 8
_a$ = 12
_leaf_call PROC
push ebp ; | prolog
mov ebp, esp ; /
mov eax, DWORD PTR _a$[ebp] ; \
add eax, 1 ; | get struct's x (from stack args), add 1 and write back
mov DWORD PTR _a$[ebp], eax ; /
mov ecx, DWORD PTR $T1[ebp] ; get ptr to retval struct passed as hidden arg (+8 to skip retval and saved ebp)
mov edx, DWORD PTR _a$[ebp] ; |
mov DWORD PTR [ecx], edx ; |
mov eax, DWORD PTR _a$[ebp+4] ; |
mov DWORD PTR [ecx+4], eax ; | copy modified (b/c of x+=1) struct arg to space of retval
mov edx, DWORD PTR _a$[ebp+8] ; |
mov DWORD PTR [ecx+8], edx ; |
mov eax, DWORD PTR _a$[ebp+12] ; |
mov DWORD PTR [ecx+12], eax ; |
mov eax, DWORD PTR $T1[ebp] ; return value (= ptr to struct that was passed-in as hidden arg)
pop ebp ; |
ret 0 ; | epilog
_leaf_call ENDP
$T1 = -32
_a$ = -16
_main PROC
push ebp ; |
mov ebp, esp ; | prolog
sub esp, 32 ; / 32 = 16b local area for struct + 16b space used for retval struct
mov DWORD PTR _a$[ebp], 9 ; \ int x
mov eax, 99 ; | |
mov WORD PTR _a$[ebp+4], ax ; | struct values (local area) | short y
mov BYTE PTR _a$[ebp+6], 23 ; | char z
mov DWORD PTR _a$[ebp+8], 12 ; | |
mov DWORD PTR _a$[ebp+12], 0 ; / | long long t
push 0 ; \
push 7 ; | arg 7
push 6 ; arg 6
dyncall/doc/disas_examples/x86.cdecl.disas view on Meta::CPAN
mov edx, DWORD PTR _a$[ebp+8] ; |
mov DWORD PTR [ecx+8], edx ; |
mov eax, DWORD PTR _a$[ebp+12] ; |
mov DWORD PTR [ecx+12], eax ; /
lea ecx, DWORD PTR $T1[ebp] ; \ ptr to space used for struct retval (pushed as hidden first arg)
push ecx ; |
call _leaf_call ; push return address and call
add esp, 56 ; |
xor eax, eax ; : return value
mov esp, ebp ; |
pop ebp ; | epilog
ret 0 ; |
_main ENDP
; ---------- 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) { } };
;
dyncall/doc/disas_examples/x86.fastcall_borland.disas view on Meta::CPAN
;
; ...
; TTest t = DoTest();
; from http://codeverge.com/embarcadero.cppbuilder.cpp/does-fastcall-have-any-bearing-on/1043767
DoTest():
push ebp ; |
mov ebp,esp ; | prolog
add esp,-0x0c ; |
mov [ebp-0x04],eax ; pointer to hidden param in eax -> local area
mov [ebp-0x0c],0x00000001 ; val 1 -> local area
mov [ebp-0x08],0x00000002 ; val 2 -> local area
mov eax,[ebp-0x04] ; refetch eax (pointlessly)
mov edx,[ebp-0x0c] ; get val 1 in edx and ...
mov [eax],edx ; ... store at *eax
mov edx,[ebp-0x08] ; get val 2 in edx and ...
mov [eax+0x04],edx ; ... store at *(eax + 4)
mov eax, [ebp-0x04] ; return value
mov esp,ebp ; |
pop ebp ; | epilog
ret ; |
; vim: ft=asm
dyncall/doc/disas_examples/x86.fastcall_gnu.disas view on Meta::CPAN
; nonleaf_call(0, 1, 2, 3, 4, 5, 6, 7);
; return 0;
; }
; output from alpine_linux-3.11.3-x86 w/ gcc 9.2.0 (w/ flags to simplify: -fno-stack-protector -fno-pic)
00001205 <leaf_call>:
1205: 55 push %ebp ; |
1206: 89 e5 mov %esp,%ebp ; | prolog
1208: 83 ec 08 sub $0x8,%esp ; |
120b: 89 4d fc mov %ecx,-0x4(%ebp) ;
120e: 89 55 f8 mov %edx,-0x8(%ebp) ;
1211: 90 nop ;
1212: c9 leave ; |
1213: c2 14 00 ret $0x14 ; | epilog
00001216 <nonleaf_call>:
1216: 55 push %ebp ; |
1217: 89 e5 mov %esp,%ebp ; | prolog
1219: 83 ec 18 sub $0x18,%esp ; /
121c: 89 4d f4 mov %ecx,-0xc(%ebp) ; in arg 0 -> local area on stack
121f: 89 55 f0 mov %edx,-0x10(%ebp) ; in arg 1 -> local area on stack
1222: b8 10 00 00 00 mov $0x10,%eax ; |
1227: 83 e8 01 sub $0x1,%eax ; |
122a: 05 e8 00 00 00 add $0xe8,%eax ; |
122f: b9 10 00 00 00 mov $0x10,%ecx ; | alloca (seems like 220 is rounded up for stack alignment purposes)
1234: ba 00 00 00 00 mov $0x0,%edx ; |
1239: f7 f1 div %ecx ; |
123b: 6b c0 10 imul $0x10,%eax,%eax ; |
dyncall/doc/disas_examples/x86.fastcall_gnu.disas view on Meta::CPAN
1257: ff 75 18 pushl 0x18(%ebp) ; |
125a: ff 75 14 pushl 0x14(%ebp) ; | read in args 3-7 from prev frame's param area, and ...
125d: ff 75 10 pushl 0x10(%ebp) ; | ... push onto stack as arg 2-6
1260: ff 75 0c pushl 0xc(%ebp) ; |
1263: 8b 55 08 mov 0x8(%ebp),%edx ; arg 1 (via reg, read in arg 2 from prev frame's param area)
1266: 89 c1 mov %eax,%ecx ; arg 0 (via reg)
1268: e8 98 ff ff ff call 1205 <leaf_call> ; push return address and call
126d: 83 c4 0c add $0xc,%esp ; @@@ restore esp to what it was before pushing args
1270: 90 nop ;
1271: c9 leave ; |
1272: c2 18 00 ret $0x18 ; | epilog
00001275 <main>:
1275: 8d 4c 24 04 lea 0x4(%esp),%ecx ; |
1279: 83 e4 f0 and $0xfffffff0,%esp ; | @@@? alignment?
127c: ff 71 fc pushl -0x4(%ecx) ; | prolog
127f: 55 push %ebp ; |
1280: 89 e5 mov %esp,%ebp ; |
1282: 51 push %ecx ; preserve ecx (so it can be used for passing arg 0)
1283: 83 ec 04 sub $0x4,%esp ; @@@ unsure why, alignment?
1286: 83 ec 08 sub $0x8,%esp ; @@@ unsure why, alignment? pointless
1289: 6a 07 push $0x7 ; arg 7
128b: 6a 06 push $0x6 ; arg 6
128d: 6a 05 push $0x5 ; arg 5
128f: 6a 04 push $0x4 ; arg 4
1291: 6a 03 push $0x3 ; arg 3
1293: 6a 02 push $0x2 ; arg 2
1295: ba 01 00 00 00 mov $0x1,%edx ; arg 1 (via reg)
129a: b9 00 00 00 00 mov $0x0,%ecx ; arg 0 (via reg)
129f: e8 72 ff ff ff call 1216 <nonleaf_call> ; push return address and call
12a4: 83 c4 08 add $0x8,%esp ; @@@ restore one of the two "sub...esp"s above
12a7: b8 00 00 00 00 mov $0x0,%eax ; return value
12ac: 8b 4d fc mov -0x4(%ebp),%ecx ; restore ecx
12af: c9 leave ; |
12b0: 8d 61 fc lea -0x4(%ecx),%esp ; | epilog
12b3: c3 ret ; |
; ---------- vararg call (shows that all args are pushed) ---------->
; void __attribute__((fastcall)) leaf_call(int a, short b, char c, ...)
; {
; }
;
dyncall/doc/disas_examples/x86.fastcall_gnu.disas view on Meta::CPAN
; leaf_call(a, 1, 2, 3, 4, 5, 6, 7LL);
; return 0;
; }
; output from alpine_linux-3.11.3-x86 w/ gcc 9.2.0 (w/ flags to simplify: -fno-stack-protector -fno-pic)
00001205 <leaf_call>:
1205: 55 push %ebp ; |
1206: 89 e5 mov %esp,%ebp ; | prolog
1208: 83 ec 20 sub $0x20,%esp ; |
120b: 89 4d fc mov %ecx,-0x4(%ebp) ; ptr to retval space for struct (hidden first arg) -> local area
120e: 8b 45 18 mov 0x18(%ebp),%eax ;
1211: 8b 55 24 mov 0x24(%ebp),%edx ;
1214: 66 89 45 f8 mov %ax,-0x8(%ebp) ;
1218: 8b 45 1c mov 0x1c(%ebp),%eax ;
121b: 89 45 f0 mov %eax,-0x10(%ebp) ;
121e: 8b 45 20 mov 0x20(%ebp),%eax ;
1221: 89 45 f4 mov %eax,-0xc(%ebp) ;
1224: 89 d0 mov %edx,%eax ;
dyncall/doc/disas_examples/x86.fastcall_gnu.disas view on Meta::CPAN
1241: 8b 55 08 mov 0x8(%ebp),%edx ; |
1244: 89 10 mov %edx,(%eax) ; |
1246: 8b 55 0c mov 0xc(%ebp),%edx ; |
1249: 89 50 04 mov %edx,0x4(%eax) ; | copy struct from param area in prev frame to retval space
124c: 8b 55 10 mov 0x10(%ebp),%edx ; |
124f: 89 50 08 mov %edx,0x8(%eax) ; |
1252: 8b 55 14 mov 0x14(%ebp),%edx ; |
1255: 89 50 0c mov %edx,0xc(%eax) ; |
1258: 8b 45 fc mov -0x4(%ebp),%eax ; return value (passed-in hidden ptr)
125b: c9 leave ; |
125c: c2 34 00 ret $0x34 ; | epilog
0000125f <main>:
125f: 8d 4c 24 04 lea 0x4(%esp),%ecx ; |
1263: 83 e4 f0 and $0xfffffff0,%esp ; |
1266: ff 71 fc pushl -0x4(%ecx) ; | prolog
1269: 55 push %ebp ; |
126a: 89 e5 mov %esp,%ebp ; |
126c: 51 push %ecx ; preserve ecx (so it can be used for passing arg 0)
126d: 83 ec 24 sub $0x24,%esp ; reserve stack space for struct (local area)
1270: c7 45 e8 09 00 00 00 movl $0x9,-0x18(%ebp) ; | int x
1277: 66 c7 45 ec 63 00 movw $0x63,-0x14(%ebp) ; | short y
127d: c6 45 ee 17 movb $0x17,-0x12(%ebp) ; | struct values (local area) char z
1281: c7 45 f0 0c 00 00 00 movl $0xc,-0x10(%ebp) ; | |
1288: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp) ; | | long long t
128f: 8d 45 d8 lea -0x28(%ebp),%eax ; ptr to space used for struct retval (passed as hidden first arg) -> eax
dyncall/doc/disas_examples/x86.fastcall_gnu.disas view on Meta::CPAN
12a7: ff 75 f4 pushl -0xc(%ebp) ; |
12aa: ff 75 f0 pushl -0x10(%ebp) ; | arg 0 (struct by value, pushed onto stack)
12ad: ff 75 ec pushl -0x14(%ebp) ; |
12b0: ff 75 e8 pushl -0x18(%ebp) ; |
12b3: 89 c1 mov %eax,%ecx ; ptr to free space for call's retval (struct), hidden first arg
12b5: e8 4b ff ff ff call 1205 <leaf_call> ; push return address and call
12ba: 83 c4 04 add $0x4,%esp ; @@@ restore esp to what it was before pushing args
12bd: b8 00 00 00 00 mov $0x0,%eax ; return value
12c2: 8b 4d fc mov -0x4(%ebp),%ecx ; restore ecx
12c5: c9 leave ; |
12c6: 8d 61 fc lea -0x4(%ecx),%esp ; | epilog
12c9: c3 ret ; |
; ---------- small struct returned by value (shows it's never returned via regs) ---------->
; struct A { short x; short y; };
;
; struct A __attribute__((fastcall)) leaf_call(int a, int b)
; {
dyncall/doc/disas_examples/x86.fastcall_gnu.disas view on Meta::CPAN
; leaf_call(99, 2);
; return 0;
; }
; output from alpine_linux-3.11.3-x86 w/ gcc 9.2.0 (w/ flags to simplify: -fno-stack-protector -fno-pic)
00001205 <leaf_call>:
1205: 55 push %ebp ; |
1206: 89 e5 mov %esp,%ebp ; | prolog
1208: 83 ec 18 sub $0x18,%esp ; |
120b: 89 4d ec mov %ecx,-0x14(%ebp) ; ptr to retval space for struct (hidden first arg) -> local area
120e: 89 55 e8 mov %edx,-0x18(%ebp) ; in arg 0 -> local area
1211: 66 c7 45 fc 0d 00 movw $0xd,-0x4(%ebp) ; |
1217: 66 c7 45 fe 0f 00 movw $0xf,-0x2(%ebp) ; | struct values (local area)
121d: 8b 45 ec mov -0x14(%ebp),%eax ; ptr to retval space for struct (fetched from local area) -> eax
1220: 8b 55 fc mov -0x4(%ebp),%edx ; |
1223: 89 10 mov %edx,(%eax) ; | copy struct in local area to retval space
1225: 8b 45 ec mov -0x14(%ebp),%eax ; return value (passed-in hidden ptr)
1228: c9 leave ; |
1229: c2 04 00 ret $0x4 ; | epilog
0000122c <main>:
122c: 55 push %ebp ; |
122d: 89 e5 mov %esp,%ebp ; | prolog
122f: 83 ec 04 sub $0x4,%esp ; |
1232: 8d 45 fc lea -0x4(%ebp),%eax ; ptr to space used for struct retval (passed as hidden first arg)
1235: 6a 02 push $0x2 ; arg 1
1237: ba 63 00 00 00 mov $0x63,%edx ; arg 0 (via reg)
123c: 89 c1 mov %eax,%ecx ; ptr to free space for call's retval (struct), hidden first arg
123e: e8 c2 ff ff ff call 1205 <leaf_call> ; push return address and call
1243: b8 00 00 00 00 mov $0x0,%eax ; return value
1248: c9 leave ; |
1249: c3 ret ; | epilog
; ---------- C++ trivial and non-trivial aggrs passed to C funcs ---------->
;
; struct Trivial { int a; };
; struct NonTrivial {
; int a;
; __attribute__((fastcall)) NonTrivial() : a(0) {}
; __attribute__((fastcall)) NonTrivial(const NonTrivial& rhs) : a(rhs.a) { }
dyncall/doc/disas_examples/x86.fastcall_ms.disas view on Meta::CPAN
_a$ = -8
_b$ = -4
_c$ = 8
_d$ = 12
_e$ = 16
_f$ = 20
_g$ = 24
_h$ = 28
@nonleaf_call@32 PROC
push ebp ; |
mov ebp, esp ; | prolog
sub esp, 8 ; |
mov DWORD PTR _b$[ebp], edx ; in arg 1 -> local area on stack
mov DWORD PTR _a$[ebp], ecx ; in arg 0 -> local area on stack
mov ecx, 220 ; |
call @alloca@4 ; | call alloca(220) (ecx = arg)
mov BYTE PTR [eax], 76 ; 'L' -> alloca()'d space (pointed to by alloca's retval in eax)
mov eax, DWORD PTR _h$[ebp] ; |
push eax ; |
mov ecx, DWORD PTR _g$[ebp] ; |
push ecx ; |
mov edx, DWORD PTR _f$[ebp] ; | read in args 3-7 from prev frame's param area, and ...
push edx ; | ... "push" onto stack as arg 2-6
mov eax, DWORD PTR _e$[ebp] ; |
push eax ; |
mov ecx, DWORD PTR _d$[ebp] ; |
push ecx ; |
mov edx, DWORD PTR _c$[ebp] ; arg 1 | read from prev frame's param
mov ecx, DWORD PTR _b$[ebp] ; arg 0 | area and put in regs
call @leaf_call@28 ; push return address and call
mov esp, ebp ; |
pop ebp ; | epilog
ret 24 ; |
@nonleaf_call@32 ENDP
_main PROC
push ebp ; | prolog
mov ebp, esp ; |
push 7 ; arg 7
push 6 ; arg 6
push 5 ; arg 5
push 4 ; arg 4
push 3 ; arg 3
push 2 ; arg 2
mov edx, 1 ; arg 1 (via reg)
xor ecx, ecx ; arg 0 (via reg)
call @nonleaf_call@32 ; push return address and call
xor eax, eax ; return value
pop ebp ; |
ret 0 ; | epilog
_main ENDP
; ---------- structs by value (arg and return value), struct arg not fitting in regs ---------->
;
; struct A { int x; short y; char z; long long t; };
;
; struct A leaf_call(struct A a, short b, long long c, char d, int e, int f, int g, long long h)
; {
dyncall/doc/disas_examples/x86.fastcall_ms.disas view on Meta::CPAN
_d$ = -4
$T1 = 8
_a$ = 12
_c$ = 28
_e$ = 36
_f$ = 40
_g$ = 44
_h$ = 48
@leaf_call@52 PROC
push ebp ; |
mov ebp, esp ; | prolog
sub esp, 8 ; |
mov BYTE PTR _d$[ebp], dl ; in arg 3 -> local area on stack
mov WORD PTR _b$[ebp], cx ; in arg 1 -> local area on stack
mov eax, DWORD PTR _a$[ebp] ; \
add eax, 1 ; | get struct's x (from stack args), add 1 and write back
mov DWORD PTR _a$[ebp], eax ; /
mov ecx, DWORD PTR $T1[ebp] ; get ptr to retval struct passed as hidden arg (+8 to skip retval and saved ebp)
mov edx, DWORD PTR _a$[ebp] ; |
mov DWORD PTR [ecx], edx ; |
mov eax, DWORD PTR _a$[ebp+4] ; |
mov DWORD PTR [ecx+4], eax ; | copy modified (b/c of x+=1) struct arg to space of retval
mov edx, DWORD PTR _a$[ebp+8] ; |
mov DWORD PTR [ecx+8], edx ; |
mov eax, DWORD PTR _a$[ebp+12] ; |
mov DWORD PTR [ecx+12], eax ; |
mov eax, DWORD PTR $T1[ebp] ; return value (= ptr to struct that was passed-in as hidden arg)
mov esp, ebp ; |
pop ebp ; | epilog
ret 48 ; |
@leaf_call@52 ENDP
$T1 = -32
_a$ = -16
_main PROC
push ebp ; |
mov ebp, esp ; | prolog
sub esp, 32 ; / 32 = 16b local area for struct + 16b space used for retval struct
mov DWORD PTR _a$[ebp], 9 ; \ int x
mov eax, 99 ; | |
mov WORD PTR _a$[ebp+4], ax ; | struct values (local area) | short y
mov BYTE PTR _a$[ebp+6], 23 ; | char z
mov DWORD PTR _a$[ebp+8], 12 ; | |
mov DWORD PTR _a$[ebp+12], 0 ; / | long long t
push 0 ; \
push 7 ; | arg 7
push 6 ; arg 6
dyncall/doc/disas_examples/x86.fastcall_ms.disas view on Meta::CPAN
mov DWORD PTR [ecx+8], edx ; |
mov eax, DWORD PTR _a$[ebp+12] ; |
mov DWORD PTR [ecx+12], eax ; /
lea ecx, DWORD PTR $T1[ebp] ; \ ptr to space used for struct retval (pushed as hidden first arg)
push ecx ; |
mov dl, 3 ; arg 3 (via reg)
mov ecx, 1 ; arg 1 (via reg)
call @leaf_call@52 ; push return address and call
xor eax, eax ; return value
mov esp, ebp ; |
pop ebp ; | epilog
ret 0 ; |
_main ENDP
; ---------- C++ trivial and non-trivial aggrs passed to C funcs ---------->
;
; struct Trivial { int a; };
; struct NonTrivial {
; int a;
dyncall/doc/disas_examples/x86.plan9call.disas view on Meta::CPAN
; }
; output from plan9-4th_edition-x86 w/ 8c x.c && 8l -a x.8
001020 (1) TEXT leaf_call+0(SB),$0
001020 c3 (3) RET ,
001021 (5) TEXT nonleaf_call+0(SB),$28
001021 83ec1c (5) SUBL $28,SP ; prolog (note, there is no register save area at all)
001024 8b442424 (7) MOVL b+36(FP),AX ; |
001028 890424 (7) MOVL AX,(SP) ; |
00102b 8b442428 (7) MOVL c+40(FP),AX ; |
00102f 89442404 (7) MOVL AX,4(SP) ; |
001033 8b44242c (7) MOVL d+44(FP),AX ; |
001037 89442408 (7) MOVL AX,8(SP) ; | fetch in args from prev frame's param area ...
00103b 8b442430 (7) MOVL e+48(FP),AX ; | ... and "push" onto stack
00103f 8944240c (7) MOVL AX,12(SP) ; |
001043 8b442434 (7) MOVL f+52(FP),AX ; |
001047 89442410 (7) MOVL AX,16(SP) ; |
00104b 8b442438 (7) MOVL g+56(FP),AX ; |
00104f 89442414 (7) MOVL AX,20(SP) ; |
001053 e8c8ffffff (7) CALL ,1020+leaf_call ; push return address and call
001058 b878000000 (8) MOVL $120,AX ; return value: 'x' -> eax
00105d 83c41c (8) ADDL $28,SP ; |
001060 c3 (8) RET , ; | epilog
001061 (11) TEXT main+0(SB),$32
001061 83ec20 (11) SUBL $32,SP ; prolog (note, there is no register save area at all)
001064 c7042400000000 (13) MOVL $0,(SP) ; arg 0 -> "push" onto stack
00106b b801000000 (13) MOVL $1,AX ; arg 1 -> eax, then ...
001070 89442404 (13) MOVL AX,4(SP) ; ... "pushed" onto stack
001074 b802000000 (13) MOVL $2,AX ; arg 2 -> eax, then ...
001079 89442408 (13) MOVL AX,8(SP) ; ... "pushed" onto stack
00107d b803000000 (13) MOVL $3,AX ; .
001082 8944240c (13) MOVL AX,12(SP) ; .
001086 b804000000 (13) MOVL $4,AX ; .
00108b 89442410 (13) MOVL AX,16(SP) ; .
00108f b805000000 (13) MOVL $5,AX ; .
001094 89442414 (13) MOVL AX,20(SP) ; .
001098 b806000000 (13) MOVL $6,AX ; arg 6 -> eax, then ...
00109d 89442418 (13) MOVL AX,24(SP) ; ... "pushed" onto stack
0010a1 e87bffffff (13) CALL ,1021+nonleaf_call ; push return address and call
0010a6 31c0 (14) MOVL $0,AX ; return value
0010a8 83c420 (14) ADDL $32,SP ; |
0010ab c3 (14) RET , ; | epilog
; ---------- 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)
; {
; }
dyncall/doc/disas_examples/x86.plan9call.disas view on Meta::CPAN
; }
; output from plan9-4th_edition-x86 w/ 8c x.c && 8l -a x.8
001020 (3) TEXT leaf_call+0(SB),$0
001020 c3 (5) RET ,
001021 (7) TEXT nonleaf_call+0(SB),$148
001021 81ec94000000 (7) SUBL $148,SP ; prolog (note, there is no register save area at all)
001027 8d842494000000 (10) LEAL l+148(SP),AX ; |
00102e 89442430 (10) MOVL AX,l+48(SP) ; | loop's write ptr (stored at beginning of char[100] space)
001032 83442430fc (10) ADDL $-4,l+48(SP) ; | decr loop ptr in memory
001037 8b442430 (10) MOVL l+48(SP),AX ; | ptr -> eax
00103b c70000000000 (10) MOVL $0,(AX) ; | zero-init char[100] space write a 0
001041 837c243000 (10) CMPL l+48(SP),$0 ; | cmp if done
001046 75ea (10) JNE ,1032 ; | loop
001048 c64424304c (10) MOVB $76,l+48(SP) ; 'L' -> local area (beginning of char[100] space)
00104d 8b84249c000000 (11) MOVL b+156(FP),AX ; |
001054 890424 (11) MOVL AX,(SP) ; |
dyncall/doc/disas_examples/x86.plan9call.disas view on Meta::CPAN
001083 b904000000 (11) MOVL $4,CX ; | rep counter (4, for dwords = 16b = sizeof(struct A))
001088 fc (11) CLD , ; | copy struct to next call's stack
001089 f3 (11) REP , ; |
00108a a5 (11) MOVSL , ; /
00108b 8b8424bc000000 (11) MOVL g+188(FP),AX ; \
001092 89442420 (11) MOVL AX,32(SP) ; | fetch remaining in args (ints after struct) from prev frame's param area ...
001096 8b8424c0000000 (11) MOVL h+192(FP),AX ; | ... and "push" onto stack
00109d 89442424 (11) MOVL AX,36(SP) ; |
0010a1 e87affffff (11) CALL ,1020+leaf_call ; push return address and call
0010a6 81c494000000 (11) ADDL $148,SP ; |
0010ac c3 (11) RET , ; | epilog
0010ad (14) TEXT main+0(SB),$52
0010ad 83ec34 (14) SUBL $52,SP ; prolog (note, there is no register save area at all)
0010b0 c7042400000000 (16) MOVL $0,(SP) ; arg 0 -> "push" onto stack
0010b7 b801000000 (16) MOVL $1,AX ; arg 1 -> eax, then ...
0010bc 89442404 (16) MOVL AX,4(SP) ; ... "pushed" onto stack
0010c0 b802000000 (16) MOVL $2,AX ; arg 2 -> eax, then ...
0010c5 89442408 (16) MOVL AX,8(SP) ; ... "pushed" onto stack
0010c9 b803000000 (16) MOVL $3,AX ; .
0010ce 8944240c (16) MOVL AX,12(SP) ; .
0010d2 b804000000 (16) MOVL $4,AX ; .
0010d7 89442410 (16) MOVL AX,16(SP) ; .
0010db 8d442414 (16) LEAL 20(SP),AX ; get ptr to next (unused) stack bytes -> eax ...
dyncall/doc/disas_examples/x86.plan9call.disas view on Meta::CPAN
0010f8 8b442430 (16) MOVL .safe+48(SP),AX ; |
0010fc c7400807000000 (16) MOVL $7,8(AX) ; |
001103 c7400c00000000 (16) MOVL $0,12(AX) ; | msbytes of long long
00110a b808000000 (16) MOVL $8,AX ; arg 6 -> eax, then ...
00110f 89442424 (16) MOVL AX,36(SP) ; ... "pushed" onto stack
001113 b809000000 (16) MOVL $9,AX ; arg 7 -> eax, then ...
001118 89442428 (16) MOVL AX,40(SP) ; ... "pushed" onto stack
00111c e800ffffff (16) CALL ,1021+nonleaf_call ; push return address and call
001121 31c0 (17) MOVL $0,AX ; return value
001123 83c434 (17) ADDL $52,SP ; |
001126 c3 (17) RET , ; | epilog
; ---------- 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)
; {
dyncall/doc/disas_examples/x86.plan9call.disas view on Meta::CPAN
; output from plan9-4th_edition-x86 w/ 8c x.c && 8l -a x.8
001020 (2) TEXT f1+0(SB),$0
001020 8b442404 (4) MOVL .ret+4(FP),AX ; ptr to retval space -> eax
001024 c700031c0000 (4) MOVL $7171,(AX) ; |
00102a c7400400000000 (4) MOVL $0,4(AX) ; | return value
001031 c3 (4) RET ,
001032 (7) TEXT main+0(SB),$16
001032 83ec10 (7) SUBL $16,SP ; prolog
001035 8d4c2408 (9) LEAL .safe+8(SP),CX ; | ptr to space for return value ...
001039 890c24 (9) MOVL CX,(SP) ; | ... pushed as implicit first arg
00103c e8dfffffff (9) CALL ,1020+f1 ; push return address and call
001041 8b442408 (9) MOVL .safe+8(SP),AX ; return value
001045 8b54240c (9) MOVL .safe+12(SP),DX ; @@@ unsure, b/c we have a cast
001049 83c410 (9) ADDL $16,SP ; |
00104c c3 (9) RET , ; | epilog
; ---------- returning structs by value ---------->
;
; struct Small { char x; };
; struct Big { long long i; long j; };
;
; struct Small f0()
; {
dyncall/doc/disas_examples/x86.plan9call.disas view on Meta::CPAN
; struct Small s = f0();
; struct Big b = f1();
; return b.j + s.x;
; }
; output from plan9-4th_edition-x86 w/ 8c x.c && 8l -a x.8
001020 (5) TEXT f0+0 (SB),$16
001020 83ec08 (5) SUBL $8,SP ; prolog
001023 c644240484 (7) MOVB $-124,s+4(SP) ; struct data in local area (s.x)
001028 8b7c240c (8) MOVL .ret+12(FP),DI ; \
00102c 8d742404 (8) LEAL s+4(SP),SI ; |
001030 b901000000 (8) MOVL $1,CX ; | copy struct in local area to return
001035 fc (8) CLD , ; | value (pointed to by implicit first arg)
001036 f3 (8) REP , ; |
001037 a5 (8) MOVSL , ; /
001038 83c408 (8) ADDL $8,SP ; \
00103b c3 (8) RET , ; | epilog
00103c (11) TEXT f1+0(SB),$16
00103c 83ec10 (11) SUBL $16,SP ; prolog
00103f c7442404031c0000 (13) MOVL $7171,b+4(SP) ; | |
001047 c744240800000000 (13) MOVL $0,b+8(SP) ; | struct data in local area | b.i
00104f c744240ce8000000 (13) MOVL $232,b+12(SP) ; / b.j
001057 8b7c2414 (14) MOVL .ret+20(FP),DI ; \
00105b 8d742404 (14) LEAL b+4(SP),SI ; |
00105f b903000000 (14) MOVL $3,CX ; | copy struct in local area to return
001064 fc (14) CLD , ; | value (pointed to by implicit first arg)
001065 f3 (14) REP , ; |
001066 a5 (14) MOVSL , ; /
001067 83c410 (14) ADDL $16,SP ; \
00106a c3 (14) RET , ; | epilog
00106b (17) TEXT main+0(SB),$28
00106b 83ec1c (17) SUBL $28,SP ; prolog
00106e 8d442418 (19) LEAL s+24(SP),AX ; | ptr to space for return value ...
001072 890424 (19) MOVL AX,(SP) ; | ... pushed as implicit first arg
001075 e8a6ffffff (19) CALL ,1020+f0 ; push return address and call
00107a 8d44240c (20) LEAL b+12(SP),AX ; | ptr to space for return value ...
00107e 890424 (20) MOVL AX,(SP) ; | ... pushed as implicit first arg
001081 e8b6ffffff (20) CALL ,103c+f1 ; push return address and call
001086 0fbe442418 (21) MOVBLSX s+24(SP),AX ; |
00108b 03442414 (21) ADDL b+20(SP),AX ; / return value
00108f 83c41c (21) ADDL $28,SP ; \
001092 c3 (21) RET , ; | epilog
; vim: ft=asm