"Fossies" - the Fresh Open Source Software Archive

Member "ndiswrapper-1.63/driver/lin2win.S" (3 May 2020, 3876 Bytes) of package /linux/misc/ndiswrapper-1.63.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PowerPC Assembler source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "lin2win.S": 1.62_vs_1.63.

    1 /*
    2  *  Copyright (C) 2011 Pavel Roskin
    3  *
    4  *  This program is free software; you can redistribute it and/or modify
    5  *  it under the terms of the GNU General Public License as published by
    6  *  the Free Software Foundation; either version 2 of the License, or
    7  *  (at your option) any later version.
    8  *
    9  *  This program is distributed in the hope that it will be useful,
   10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   12  *  GNU General Public License for more details.
   13  *
   14  */
   15 
   16 #include <linux/linkage.h>
   17 #include <linux/version.h>
   18 
   19     .text
   20 
   21 #define WORD_BYTES 8
   22 #define LINUX_REG_ARGS 6
   23 #define WINDOWS_REG_ARGS 4
   24 
   25 /* %rbp is saved to create a stack frame, which can help with debugging */
   26 #define SAVED_REGS 1
   27 
   28 /*
   29  * When calling a Windows function, stack space is allocated for at least 4
   30  * arguments even if the number of arguments is less than 4.  The value of
   31  * true is -1 in assembler, so we multiply it by another true value.
   32  */
   33 #define stack_args(argc)                        \
   34     (WINDOWS_REG_ARGS +                     \
   35      (0 < 1) * (argc > WINDOWS_REG_ARGS) * (argc - WINDOWS_REG_ARGS))
   36 
   37 /* Full required change of stack pointer, in words */
   38 #define stack_words_raw(argc) (stack_args(argc) + SAVED_REGS + 1)
   39 
   40 /* Full actual change of stack pointer, in words (must be even) */
   41 #define stack_words_aligned(argc) ((stack_words_raw(argc) + 1) & ~1)
   42 
   43 /* Space allocated for Linux arguments on stack */
   44 #define stack_space(argc) \
   45     ((stack_words_aligned(argc) - SAVED_REGS - 1) * WORD_BYTES)
   46 
   47 /*
   48  * lin2win_win_arg(N) gives the address of the Nth Windows argument on our
   49  * stack frame.  %rsp points to the first argument.  The Nth argument is
   50  * therefore at ((N - 1) * 8)(%rsp).
   51  *
   52  * Don't call with N less than 5!
   53  */
   54 #define lin2win_win_arg(n) ((n - 1) * WORD_BYTES)(%rsp)
   55 
   56 /*
   57  * lin2win_lin_arg(N, ARGC) gives the address of the Nth Linux argument after
   58  * the stack has been prepared for a Windows function call with ARGC arguments.
   59  *
   60  * When called from Linux, the Nth argument is at ((N - 6) * 8)(%rsp).  We add
   61  * the allocated stack space and saved registers to compensate for %rsp change.
   62  *
   63  * Don't call with N less than 7!
   64  */
   65 #define lin2win_lin_arg(n, argc)                    \
   66     (stack_space(argc) +                        \
   67      (SAVED_REGS + n - LINUX_REG_ARGS) * WORD_BYTES)(%rsp)
   68 
   69 /*
   70  * lin2win(func, winarg1, winarg2, ...)
   71  * Call Windows FUNC function with ARGC arguments WINARG1, WINARG2, ...
   72  * We get (ARGC + 1) arguments.
   73  */
   74 .macro lin2win name, argc
   75 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0)
   76     SYM_FUNC_START(\name)
   77 #else
   78     .type \name, @function
   79     ENTRY(\name)
   80 #endif
   81 
   82     /* Create a call frame - it's optional, but good for debugging */
   83     .cfi_startproc
   84     push %rbp
   85     .cfi_def_cfa %rsp, 2 * WORD_BYTES
   86     .cfi_offset %rbp, -2 * WORD_BYTES
   87     mov %rsp, %rbp
   88     .cfi_def_cfa %rbp, 2 * WORD_BYTES
   89 
   90     /* Allocate space for Windows arguments */
   91     sub $stack_space(\argc), %rsp
   92 
   93     /* arg7 to winarg6 */
   94     .if (\argc >= 6)
   95         mov lin2win_lin_arg(7, \argc), %r11
   96         mov %r11, lin2win_win_arg(6)
   97     .endif
   98 
   99     /* arg6 to winarg5 */
  100     .if (\argc >= 5)
  101         mov %r9, lin2win_win_arg(5)
  102     .endif
  103 
  104     /* arg5 to winarg4 */
  105     .if (\argc >= 4)
  106         mov %r8, %r9
  107     .endif
  108 
  109     /* arg4 to winarg3 */
  110     .if (\argc >= 3)
  111         mov %rcx, %r8
  112     .endif
  113 
  114     /* arg3 to winarg2 - nothing needed, both are in %rdx */
  115 
  116     /* arg2 to winarg1 */
  117     .if (\argc >= 1)
  118         mov %rsi, %rcx
  119     .endif
  120 
  121     /* Call function (arg1) */
  122     call *%rdi
  123 
  124     /* Reclaim space for Windows arguments */
  125     add $stack_space(\argc), %rsp
  126 
  127     /* Return to the caller */
  128     leave
  129     .cfi_def_cfa %rsp, WORD_BYTES
  130     .cfi_restore %rbp
  131     ret
  132     .cfi_endproc
  133 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,5,0)
  134     SYM_FUNC_END(\name)
  135 #else
  136     .size   \name, (. - \name)
  137 #endif
  138 .endm
  139 
  140 /* Define lin2winN functions */
  141 lin2win lin2win0, 0
  142 lin2win lin2win1, 1
  143 lin2win lin2win2, 2
  144 lin2win lin2win3, 3
  145 lin2win lin2win4, 4
  146 lin2win lin2win5, 5
  147 lin2win lin2win6, 6