summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/EbcDxe/X64/EbcLowLevel.S
blob: 859cbce24cd1e8d3140f8d265974f23d4a58164a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#/** @file
#  
#    This code provides low level routines that support the Virtual Machine
#   for option ROMs.
#  
#  Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
#  This program and the accompanying materials
#  are licensed and made available under the terms and conditions of the BSD License
#  which accompanies this distribution.  The full text of the license may be found at
#  http://opensource.org/licenses/bsd-license.php
#  
#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#  
#**/

#---------------------------------------------------------------------------
# Equate files needed.
#---------------------------------------------------------------------------

ASM_GLOBAL ASM_PFX(CopyMem);
ASM_GLOBAL ASM_PFX(EbcInterpret);
ASM_GLOBAL ASM_PFX(ExecuteEbcImageEntryPoint);

#****************************************************************************
# EbcLLCALLEX
#
# This function is called to execute an EBC CALLEX instruction.
# This instruction requires that we thunk out to external native
# code. For x64, we switch stacks, copy the arguments to the stack
# and jump to the specified function.
# On return, we restore the stack pointer to its original location.
#
# Destroys no working registers.
#****************************************************************************
# VOID EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)
ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative);
ASM_PFX(EbcLLCALLEXNative):
      push   %rbp
      push   %rbx
      mov    %rsp, %rbp
      # Function prolog

      # Copy FuncAddr to a preserved register.
      mov    %rcx, %rbx

      # Set stack pointer to new value
      sub    %rdx, %r8  
      sub    %r8,  %rsp 
      mov    %rsp, %rcx
      sub    $0x20, %rsp 
      call   ASM_PFX(CopyMem)
      add    $0x20, %rsp

      # Considering the worst case, load 4 potiential arguments
      # into registers.
      mov    (%rsp), %rcx
      mov    0x8(%rsp), %rdx
      mov    0x10(%rsp), %r8
      mov    0x18(%rsp), %r9

      # Now call the external routine
      call  *%rbx

      # Function epilog
      mov      %rbp, %rsp
      pop      %rbx
      pop      %rbp
      ret

ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret);
ASM_PFX(EbcLLEbcInterpret):
    # save old parameter to stack
    mov  %rcx, 0x8(%rsp)
    mov  %rdx, 0x10(%rsp)
    mov  %r8, 0x18(%rsp)
    mov  %r9, 0x20(%rsp)

    # Construct new stack
    push %rbp
    mov  %rsp, %rbp
    push %rsi
    push %rdi
    push %rbx
    sub  $0x80, %rsp
    push %r10
    mov  %rbp, %rsi
    add  $0x10, %rsi
    mov  %rsp, %rdi
    add  $0x8, %rdi
    mov  $0x10, %rcx
    rep  movsq
    
    # build new paramater calling convention
    mov  0x18(%rsp), %r9
    mov  0x10(%rsp), %r8
    mov  0x8(%rsp), %rdx
    mov  %r10, %rcx

    # call C-code
    call ASM_PFX(EbcInterpret)
    add  $0x88, %esp
    pop  %rbx
    pop  %rdi
    pop  %rsi
    pop  %rbp
    ret

ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint);
ASM_PFX(EbcLLExecuteEbcImageEntryPoint):
    # build new paramater calling convention
    mov  %rdx, %r8
    mov  %rcx, %rdx
    mov  %r10, %rcx

    # call C-code
    sub  $0x28, %rsp
    call ASM_PFX(ExecuteEbcImageEntryPoint)
    add  $0x28, %rsp
    ret