changeset 472:e5820b7a3fbc

doc: - some more plan 9 disas examples - x86 callconv doc updated: * mainly info about aggregate passing and returning * removing section about pascal calling convention, as dyncall doesn't support 16bit abis - some cleanups
author Tassilo Philipp
date Thu, 10 Feb 2022 17:32:05 +0100
parents 4e84d6faed54
children ead041d93e36
files doc/disas_examples/x86.plan9call.disas doc/manual/callconvs/callconv_x86.tex doc/manual/manual_dyncall_api.tex
diffstat 3 files changed, 163 insertions(+), 99 deletions(-) [+]
line wrap: on
line diff
--- a/doc/disas_examples/x86.plan9call.disas	Mon Feb 07 23:29:24 2022 +0100
+++ b/doc/disas_examples/x86.plan9call.disas	Thu Feb 10 17:32:05 2022 +0100
@@ -280,7 +280,7 @@
 0011b2 e86afeffff             (17)      CALL                        ,1021+nonleaf_call
 0011b7 31c0                   (18)      MOVL                        $0,AX
 0011b9 83c464                 (18)      ADDL                        $100,SP
-0011bc c3                     (18)      RET                          ,
+0011bc c3                     (18)      RET                         ,
 
 002000 0000000000001040       (17)      DATA $0.40100000+0(SB)/8,$(40100000,00000000)
 002008 0000000000001440       (17)      DATA $0.40140000+0(SB)/8,$(40140000,00000000)
@@ -289,5 +289,104 @@
 
 
 
+; ---------- returning qwords ---------->
+;
+; long long f()
+; {
+;     return 7171LL;
+; }
+;
+; int main()
+; {
+;     return (int)f();
+; }
+
+; 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()
+; {
+;     struct Small s = { 132 };
+;     return s;
+; }
+;
+; struct Big f1()
+; {
+;     struct Big b = { 7171LL, 232 };
+;     return b;
+; }
+;
+; int main()
+; {
+;     struct Small s = f0();
+;     struct Big b = f1();
+;     return b.j + s.x;
+; }
+
+; output from 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
 
--- a/doc/manual/callconvs/callconv_x86.tex	Mon Feb 07 23:29:24 2022 +0100
+++ b/doc/manual/callconvs/callconv_x86.tex	Thu Feb 10 17:32:05 2022 +0100
@@ -95,15 +95,17 @@
 \begin{itemize}
 \item stack parameter order: right-to-left
 \item caller cleans up the stack
-\item all arguments are pushed onto the stack
+\item all arguments are pushed onto the stack (as dwords)
+\item arguments \textgreater\ 64 bits are pushed as a sequence of dwords
+\item aggregates (structs, unions) are pushed as a sequence of dwords
 \end{itemize}
 
 \paragraph{Return values}
 
 \begin{itemize}
 \item return values of pointer or integral type (\textless=\ 32 bits) are returned via the eax register
-\item integers \textgreater\ 32 bits are returned via the eax and edx registers
-\item return values \textgreater\ 64 bits (e.g. structures) are returned by the caller allocating the space and
+\item integers and aggregates (structs, unions) \textgreater\ 32 and \textless=\ 64 bits are returned via the eax and edx registers
+\item return values \textgreater\ 64 bits (e.g. aggregates) are returned by the caller allocating the space and
 passing a pointer to the callee as a new, implicit first parameter (this means, on the stack)
 \item floating point types are returned via the st0 register (except on Minix, where they are returned as integers are)
 \end{itemize}
@@ -172,15 +174,20 @@
 \item called function cleans up the stack
 \item first two integers/pointers (\textless=\ 32bit) are passed via ecx and edx (even if preceded by other arguments)
 \item if first argument is a 64 bit integer, it is passed via ecx and edx
-\item all other parameters are pushed onto the stack
+\item all other parameters are pushed onto the stack (as dwords)
+\item arguments \textgreater\ 64 bits are pushed as a sequence of dwords
+\item aggregates (structs, unions) are pushed as a sequence of dwords, but are never split between registers and stack (if registers are still available and
+aggregate doesn't fit entirely into ecx and edx, it is passed via the stack and remaining registers are free for subsequent arguments)
 \end{itemize}
 
 \paragraph{Return values}
 
 \begin{itemize}
 \item return values of pointer or integral type (\textless=\ 32 bits) are returned via the eax register
-\item integers \textgreater\ 32 bits are returned via the eax and edx registers@@@verify
-\item floating point types are returned via the st0 register@@@ really ?
+\item integers and aggregates (structs, unions) \textgreater\ 32 and \textless=\ 64 bits are returned via the eax and edx registers
+\item return values \textgreater\ 64 bits (e.g. aggregates) are returned by the caller allocating the space and
+passing a pointer to the callee as a new, implicit first parameter (always via the stack, never via a register)
+\item floating point types are returned via the st0 register
 \end{itemize}
 
 
@@ -244,17 +251,21 @@
 \item stack parameter order: right-to-left
 \item called function cleans up the stack
 \item first two integers/pointers (\textless=\ 32bit) are passed via ecx and edx (even if preceded by other arguments)
-\item if first argument is a 64 bit integer, it is pushed on the stack and the two registers are skipped 
-\item all other parameters are pushed onto the stack
+\item arguments \textgreater\ 32 bits are pushed onto the stack as a sequence of dwords (never passed via registers, any respective register is skipped and not used for subsequent args)
+\item all other parameters are pushed onto the stack (as dwords)
+\item aggregates (structs, unions) are pushed as a sequence of dwords, and never passed via registers (no matter their size, any respective register is skipped and not used for subsequent args)
+\item varargs are always passed via the stack
 \end{itemize}
 
 
 \paragraph{Return values}
 
 \begin{itemize}
-\item return values of pointer or integral type (\textless=\ 32 bits) are returned via the eax register.
-\item integers \textgreater\ 32 bits are returned via the eax and edx registers.
-\item floating point types are returned via the st0.
+\item return values of pointer or integral type (\textless=\ 32 bits) are returned via the eax register
+\item integers \textgreater\ 32 and \textless=\ 64 bits are returned via the eax and edx registers
+\item aggregates (structs, unions) of any size are returned by the caller allocating the space and
+passing a pointer to the callee as a new, implicit first parameter (always via ecx), that same pointer is returned in eax
+\item floating point types are returned via the st0
 \end{itemize}
 
 
@@ -320,8 +331,12 @@
 \begin{itemize}
 \item stack parameter order: left-to-right
 \item called function cleans up the stack
-\item first three integers/pointers (with exception of method pointers) (\textless=\ 32bit) are passed via eax, ecx and edx (even if preceded or interleaved by other arguments)
+\item first three integers/pointers (with exception of method pointers) (\textless=\ 32bit) are passed via eax, ecx and edx (preceding or interleaved arguments that are not passed via registers are pushed onto the stack)
+\item arguments \textgreater\ 32 bits are passed as a pointer to the value
+\item aggregates (structs, unions) are pushed as a sequence of dwords, and never passed via registers (no matter their size)
+\item varargs are always passed via the stack
 \item all other parameters are pushed onto the stack
+\item the direction flag is clear on entry and must be returned clear % mention it first, above @@@
 \end{itemize}
 
 
@@ -331,10 +346,10 @@
 
 \begin{itemize}
 \item return values of pointer or integral type (\textless=\ 32 bits) are returned via the eax register
-\item integers \textgreater\ 32 bits are returned via the eax and edx registers
+\item integers and aggregates (structs, unions) \textgreater\ 32 and \textless=\ 64 bits are returned via the eax and edx registers
 \item floating point types are returned via the st0 register
-\item all others (e.g. all structs, return values \textgreater\ 64 bits, ...) are returned by the caller allocating the space and
-passing a pointer to the callee as a new, implicit first parameter
+\item return values \textgreater\ 32 bits (e.g. aggregates, long long, ...) are returned by the caller allocating the space and
+passing a pointer to the callee as a new, implicit {\bf last} parameter
 \end{itemize}
 
 
@@ -398,9 +413,9 @@
 \item stack parameter order: right-to-left
 \item called function cleans up the stack
 \item first four integers/pointers (\textless=\ 32bit) are passed via eax, edx, ebx and ecx (even if preceded by other arguments)
-\item arguments \textgreater 32 bits, as well as all subsequent arguments, are passed via the stack
+\item arguments \textgreater\ 32 bits, as well as all subsequent arguments, are passed via the stack
+\item aggregates (structs, unions) are passed as a pointer to the aggregate
 \item all other parameters are pushed onto the stack
-\item varargs are always passed via the stack
 \end{itemize}
 
 
@@ -408,8 +423,10 @@
 
 \begin{itemize}
 \item return values of pointer or integral type (\textless=\ 32 bits) are returned via the eax register
-\item integers \textgreater\ 32 bits are returned via the eax and edx registers@@@ verify
-\item floating point types are returned via the st0 register@@@ really ?
+\item integers \textgreater\ 32 bits and \textless=\ 64 bits are returned via the eax and edx registers
+\item aggregates (structs, unions) \textless=\ 32 bits are returned in eax
+\item aggregates (structs, unions) \textgreater\ 32 bits are returned by the caller allocating the space and
+passing a pointer to the callee via esi, that same pointer is returned in eax
 \end{itemize}
 
 
@@ -469,10 +486,12 @@
 \paragraph{Parameter passing}
 
 \begin{itemize}
-\item Stack parameter order: right-to-left
-\item Called function cleans up the stack
-\item All parameters are pushed onto the stack
-\item Stack is usually 4 byte aligned (GCC \textgreater=\ 3.x seems to use a 16byte alignement)
+\item stack parameter order: right-to-left
+\item called function cleans up the stack
+\item all parameters are pushed onto the stack (as dwords)
+\item arguments \textgreater\ 64 bits are pushed as a sequence of dwords
+\item aggregates (structs, unions) are pushed as a sequence of dwords
+\item stack is usually 4 byte aligned (GCC \textgreater=\ 3.x seems to use a 16byte alignement)
 \item the direction flag is clear on entry and must be returned clear % mention it first, above @@@
 \end{itemize}
 
@@ -482,7 +501,9 @@
 
 \begin{itemize}
 \item return values of pointer or integral type (\textless=\ 32 bits) are returned via the eax register
-\item integers \textgreater\ 32 bits are returned via the eax and edx registers
+\item integers and aggregates (structs, unions) \textgreater\ 32 and \textless=\ 64 bits are returned via the eax and edx registers
+\item return values \textgreater\ 64 bits (e.g. aggregates) are returned by the caller allocating the space and
+passing a pointer to the callee as a new, implicit first parameter (this means, on the stack)
 \item floating point types are returned via the st0 register
 \end{itemize}
 
@@ -545,9 +566,11 @@
 
 \begin{itemize}
 \item stack parameter order: right-to-left
-\item called function cleans up the stack
+\item called function cleans up the stack (except for variadic functions where the caller cleans up)
 \item first parameter (this pointer) is passed via ecx
 \item all other parameters are pushed onto the stack
+\item arguments \textgreater\ 64 bits are pushed as a sequence of dwords
+\item aggregates (structs, unions) are pushed as a sequence of dwords
 \end{itemize}
 
 % introduce mangling section? \item Function name is decorated by prepending a '@' character and appending a '@' character and the number of bytes (decimal) of stack space required
@@ -556,8 +579,10 @@
 
 \begin{itemize}
 \item return values of pointer or integral type (\textless=\ 32 bits) are returned via the eax register
-\item integers \textgreater\ 32 bits are returned via the eax and edx registers@@@verify
-\item floating point types are returned via the st0 register@@@ really ?
+\item integers \textgreater\ 32 bits and \textless=\ 64 bits are returned via the eax and edx
+\item aggregates (structs, unions) of any size are returned by the caller allocating the space and passing
+a pointer to the callee as a new, implicit first parameter, that same pointer is returned in eax
+\item floating point types are returned via the st0 register
 \end{itemize}
 
 
@@ -668,73 +693,10 @@
 \subsubsection{pascal}
 
 The best known uses of the pascal calling convention are the 16 bit OS/2 APIs, Microsoft Windows 3.x and Borland Delphi 1.x.
-
-\paragraph{Registers and register usage}
-
-\begin{table}[h]
-\begin{tabular*}{0.95\textwidth}{3 B}
-Name          & Brief description\\
-\hline
-{\bf eax}     & scratch, return value\\
-{\bf ebx}     & preserve\\
-{\bf ecx}     & scratch\\
-{\bf edx}     & scratch, return value\\
-{\bf esi}     & preserve\\
-{\bf edi}     & preserve\\
-{\bf ebp}     & preserve\\
-{\bf esp}     & stack pointer\\
-{\bf st0}     & scratch, floating point return value\\
-{\bf st1-st7} & scratch\\
-\end{tabular*}
-\caption{Register usage on x86 pascal calling convention}
-\end{table}
-
-\paragraph{Parameter passing}
-
-\begin{itemize}
-\item stack parameter order: left-to-right
-\item called function cleans up the stack
-\item all parameters are pushed onto the stack
-\end{itemize}
-
-
-\paragraph{Return values}
+It is a variation of stdcall, however, arguments are passed from left-to-right.
+Since this calling convention is for 16-bit APIs, it is not discussed in
+further detail, here.
 
-\begin{itemize}
-\item return values of pointer or integral type (\textless=\ 32 bits) are returned via the eax register
-\item integers \textgreater\ 32 bits are returned via the eax and edx registers
-\item floating point types are returned via the st0 register
-\end{itemize}
-
-
-\paragraph{Stack layout}
-
-Stack directly after function prolog:\\
-
-\begin{figure}[h]
-\begin{tabular}{5|3|1 1}
-                                  & \vdots         &                                &                              \\
-\hhline{~=~~}
-register save area                & \hspace{4cm}   &                                & \mrrbrace{6}{caller's frame} \\
-\hhline{~-~~}
-local data                        &                &                                &                              \\
-\hhline{~-~~}
-\mrlbrace{3}{parameter area}      & arg 0          & \mrrbrace{3}{stack parameters} &                              \\
-                                  & \ldots         &                                &                              \\
-                                  & arg n-1        &                                &                              \\
-\hhline{~-~~}
-                                  & return address &                                &                              \\
-\hhline{~=~~}
-register save area                &                &                                & \mrrbrace{4}{current frame}  \\
-\hhline{~-~~}
-local data                        &                &                                &                              \\
-\hhline{~-~~}
-parameter area                    &                &                                &                              \\
-\hhline{~-~~}
-                                  & \vdots         &                                &                              \\
-\end{tabular}
-\caption{Stack layout on x86 pascal calling convention}
-\end{figure}
 
 
 \clearpage
@@ -767,6 +729,9 @@
 \item stack parameter order: right-to-left
 \item caller cleans up the stack
 \item all parameters are pushed onto the stack
+\item all parameters are pushed onto the stack (as dwords)
+\item arguments \textgreater\ 64 bits are pushed as a sequence of dwords
+\item aggregates (structs, unions) are pushed as a sequence of dwords
 \end{itemize}
 
 \pagebreak
@@ -775,8 +740,8 @@
 
 \begin{itemize}
 \item return values of pointer or integral type (\textless=\ 32 bits) are returned via the eax register
-\item integers \textgreater\ 32 bits or structures are returned by the caller allocating the space and
-passing a pointer to the callee as a new, implicit first parameter (this means, on the stack)
+\item integers \textgreater\ 32 bits and aggregates (structs, unions) of any size are returned by the caller allocating
+the space and passing a pointer to the callee as a new, implicit first parameter, that same pointer is returned in eax
 \item floating point types are returned via the st0 register (called F0 in plan9 8a's terms)
 \end{itemize}
 
--- a/doc/manual/manual_dyncall_api.tex	Mon Feb 07 23:29:24 2022 +0100
+++ b/doc/manual/manual_dyncall_api.tex	Thu Feb 10 17:32:05 2022 +0100
@@ -155,9 +155,9 @@
 Constant & Description\\
 \hline
 \lstinline@DC_CALL_C_DEFAULT@            & C default function call for current platform\\
-\lstinline@DC_CALL_C_DEFAULT_THIS@       & C++ default function call for current platform\\
-\lstinline@DC_CALL_C_ELLIPSIS@           & C ellipsis function call (named arguments (before '...'))\\
-\lstinline@DC_CALL_C_ELLIPSIS_VARARGS@   & C ellipsis function call (variable/unnamed arguments (after '...'))\\
+\lstinline@DC_CALL_C_DEFAULT_THIS@       & C++ default method call for current platform\\
+\lstinline@DC_CALL_C_ELLIPSIS@           & C ellipsis function call (named arguments (before '...', but after hidden args))\\
+\lstinline@DC_CALL_C_ELLIPSIS_VARARGS@   & C ellipsis function call (variable/unnamed arguments (starting with '...'))\\
 \lstinline@DC_CALL_C_X86_CDECL@          & C x86 platforms standard call\\
 \lstinline@DC_CALL_C_X86_WIN32_STD@      & C x86 Windows standard call\\
 \lstinline@DC_CALL_C_X86_WIN32_FAST_MS@  & C x86 Windows Microsoft fast call\\