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 21ASM_GLOBAL ASM_PFX(CopyMem); 22ASM_GLOBAL ASM_PFX(EbcInterpret); 23ASM_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) 37ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative); 38ASM_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 64skip_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 98ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret); 99ASM_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 136ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint); 137ASM_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