Home | History | Annotate | Download | only in X64
      1 #/** @file
      2 #
      3 #    This code provides low level routines that support the Virtual Machine
      4 #   for option ROMs.
      5 #
      6 #  Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
      7 #  This program and the accompanying materials
      8 #  are licensed and made available under the terms and conditions of the BSD License
      9 #  which accompanies this distribution.  The full text of the license may be found at
     10 #  http://opensource.org/licenses/bsd-license.php
     11 #
     12 #  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13 #  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 #
     15 #**/
     16 
     17 #---------------------------------------------------------------------------
     18 # Equate files needed.
     19 #---------------------------------------------------------------------------
     20 
     21 ASM_GLOBAL ASM_PFX(CopyMem);
     22 ASM_GLOBAL ASM_PFX(EbcInterpret);
     23 ASM_GLOBAL ASM_PFX(ExecuteEbcImageEntryPoint);
     24 
     25 #****************************************************************************
     26 # EbcLLCALLEX
     27 #
     28 # This function is called to execute an EBC CALLEX instruction.
     29 # This instruction requires that we thunk out to external native
     30 # code. For x64, we switch stacks, copy the arguments to the stack
     31 # and jump to the specified function.
     32 # On return, we restore the stack pointer to its original location.
     33 #
     34 # Destroys no working registers.
     35 #****************************************************************************
     36 # VOID EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)
     37 ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative);
     38 ASM_PFX(EbcLLCALLEXNative):
     39       push   %rbp
     40       push   %rbx
     41       mov    %rsp, %rbp
     42       # Function prolog
     43 
     44       # Copy FuncAddr to a preserved register.
     45       mov    %rcx, %rbx
     46 
     47       # Set stack pointer to new value
     48       sub    %rdx, %r8
     49 
     50       #
     51       # Fix X64 native function call prolog. Prepare space for at least 4 arguments,
     52       # even if the native function's arguments are less than 4.
     53       #
     54       # From MSDN x64 Software Conventions, Overview of x64 Calling Conventions:
     55       #   "The caller is responsible for allocating space for parameters to the
     56       #   callee, and must always allocate sufficient space for the 4 register
     57       #   parameters, even if the callee doesn't have that many parameters.
     58       #   This aids in the simplicity of supporting C unprototyped functions,
     59       #   and vararg C/C++ functions."
     60       #
     61       cmp    $0x20, %r8
     62       jae    skip_expansion
     63       mov    $0x20, %r8
     64 skip_expansion:
     65 
     66       sub    %r8,  %rsp
     67 
     68       #
     69       # Fix X64 native function call 16-byte alignment.
     70       #
     71       # From MSDN x64 Software Conventions, Stack Usage:
     72       #   "The stack will always be maintained 16-byte aligned, except within
     73       #   the prolog (for example, after the return address is pushed)."
     74       #
     75       and    $0xFFFFFFFFFFFFFFF0, %rsp
     76 
     77       mov    %rsp, %rcx
     78       sub    $0x20, %rsp
     79       call   ASM_PFX(CopyMem)
     80       add    $0x20, %rsp
     81 
     82       # Considering the worst case, load 4 potiential arguments
     83       # into registers.
     84       mov    (%rsp), %rcx
     85       mov    0x8(%rsp), %rdx
     86       mov    0x10(%rsp), %r8
     87       mov    0x18(%rsp), %r9
     88 
     89       # Now call the external routine
     90       call  *%rbx
     91 
     92       # Function epilog
     93       mov      %rbp, %rsp
     94       pop      %rbx
     95       pop      %rbp
     96       ret
     97 
     98 ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret);
     99 ASM_PFX(EbcLLEbcInterpret):
    100     # save old parameter to stack
    101     mov  %rcx, 0x8(%rsp)
    102     mov  %rdx, 0x10(%rsp)
    103     mov  %r8, 0x18(%rsp)
    104     mov  %r9, 0x20(%rsp)
    105 
    106     # Construct new stack
    107     push %rbp
    108     mov  %rsp, %rbp
    109     push %rsi
    110     push %rdi
    111     push %rbx
    112     sub  $0x80, %rsp
    113     push %r10
    114     mov  %rbp, %rsi
    115     add  $0x10, %rsi
    116     mov  %rsp, %rdi
    117     add  $0x8, %rdi
    118     mov  $0x10, %rcx
    119     rep  movsq
    120 
    121     # build new paramater calling convention
    122     mov  0x18(%rsp), %r9
    123     mov  0x10(%rsp), %r8
    124     mov  0x8(%rsp), %rdx
    125     mov  %r10, %rcx
    126 
    127     # call C-code
    128     call ASM_PFX(EbcInterpret)
    129     add  $0x88, %esp
    130     pop  %rbx
    131     pop  %rdi
    132     pop  %rsi
    133     pop  %rbp
    134     ret
    135 
    136 ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint);
    137 ASM_PFX(EbcLLExecuteEbcImageEntryPoint):
    138     # build new paramater calling convention
    139     mov  %rdx, %r8
    140     mov  %rcx, %rdx
    141     mov  %r10, %rcx
    142 
    143     # call C-code
    144     sub  $0x28, %rsp
    145     call ASM_PFX(ExecuteEbcImageEntryPoint)
    146     add  $0x28, %rsp
    147     ret
    148