]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/EbcDxe/X64/EbcLowLevel.nasm
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / EbcDxe / X64 / EbcLowLevel.nasm
CommitLineData
92bcfd37
JJ
1;/** @file\r
2;\r
3; This code provides low level routines that support the Virtual Machine.\r
4; for option ROMs.\r
5;\r
6; Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
7; Copyright (c) 2014 Hewlett-Packard Development Company, L.P.<BR>\r
9d510e61 8; SPDX-License-Identifier: BSD-2-Clause-Patent\r
92bcfd37
JJ
9;\r
10;**/\r
11\r
12;---------------------------------------------------------------------------\r
13; Equate files needed.\r
14;---------------------------------------------------------------------------\r
15\r
16DEFAULT REL\r
17SECTION .text\r
18\r
19extern ASM_PFX(CopyMem)\r
20extern ASM_PFX(EbcInterpret)\r
21extern ASM_PFX(ExecuteEbcImageEntryPoint)\r
22\r
23;****************************************************************************\r
24; EbcLLCALLEX\r
25;\r
26; This function is called to execute an EBC CALLEX instruction.\r
27; This instruction requires that we thunk out to external native\r
28; code. For x64, we switch stacks, copy the arguments to the stack\r
29; and jump to the specified function.\r
30; On return, we restore the stack pointer to its original location.\r
31;\r
32; Destroys no working registers.\r
33;****************************************************************************\r
34; INT64 EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)\r
35global ASM_PFX(EbcLLCALLEXNative)\r
36ASM_PFX(EbcLLCALLEXNative):\r
37 push rbp\r
38 push rbx\r
39 mov rbp, rsp\r
40 ; Function prolog\r
41\r
42 ; Copy FuncAddr to a preserved register.\r
43 mov rbx, rcx\r
44\r
45 ; Set stack pointer to new value\r
46 sub r8, rdx\r
47\r
48 ;\r
49 ; Fix X64 native function call prolog. Prepare space for at least 4 arguments,\r
50 ; even if the native function's arguments are less than 4.\r
51 ;\r
52 ; From MSDN x64 Software Conventions, Overview of x64 Calling Conventions:\r
53 ; "The caller is responsible for allocating space for parameters to the\r
54 ; callee, and must always allocate sufficient space for the 4 register\r
55 ; parameters, even if the callee doesn't have that many parameters.\r
56 ; This aids in the simplicity of supporting C unprototyped functions,\r
57 ; and vararg C/C++ functions."\r
58 ;\r
59 cmp r8, 0x20\r
60 jae skip_expansion\r
61 mov r8, dword 0x20\r
62skip_expansion:\r
63\r
64 sub rsp, r8\r
65\r
66 ;\r
67 ; Fix X64 native function call 16-byte alignment.\r
68 ;\r
69 ; From MSDN x64 Software Conventions, Stack Usage:\r
70 ; "The stack will always be maintained 16-byte aligned, except within\r
71 ; the prolog (for example, after the return address is pushed)."\r
72 ;\r
73 and rsp, ~ 0xf\r
74\r
75 mov rcx, rsp\r
76 sub rsp, 0x20\r
77 call ASM_PFX(CopyMem)\r
78 add rsp, 0x20\r
79\r
80 ; Considering the worst case, load 4 potiential arguments\r
81 ; into registers.\r
82 mov rcx, qword [rsp]\r
83 mov rdx, qword [rsp+0x8]\r
84 mov r8, qword [rsp+0x10]\r
85 mov r9, qword [rsp+0x18]\r
86\r
87 ; Now call the external routine\r
88 call rbx\r
89\r
90 ; Function epilog\r
91 mov rsp, rbp\r
92 pop rbx\r
93 pop rbp\r
94 ret\r
95\r
96;****************************************************************************\r
97; EbcLLEbcInterpret\r
98;\r
99; Begin executing an EBC image.\r
100;****************************************************************************\r
101; UINT64 EbcLLEbcInterpret(VOID)\r
102global ASM_PFX(EbcLLEbcInterpret)\r
103ASM_PFX(EbcLLEbcInterpret):\r
104 ;\r
105 ;; mov rax, ca112ebccall2ebch\r
106 ;; mov r10, EbcEntryPoint\r
107 ;; mov r11, EbcLLEbcInterpret\r
108 ;; jmp r11\r
109 ;\r
110 ; Caller uses above instruction to jump here\r
111 ; The stack is below:\r
112 ; +-----------+\r
113 ; | RetAddr |\r
114 ; +-----------+\r
115 ; |EntryPoint | (R10)\r
116 ; +-----------+\r
117 ; | Arg1 | <- RDI\r
118 ; +-----------+\r
119 ; | Arg2 |\r
120 ; +-----------+\r
121 ; | ... |\r
122 ; +-----------+\r
123 ; | Arg16 |\r
124 ; +-----------+\r
125 ; | Dummy |\r
126 ; +-----------+\r
127 ; | RDI |\r
128 ; +-----------+\r
129 ; | RSI |\r
130 ; +-----------+\r
131 ; | RBP | <- RBP\r
132 ; +-----------+\r
133 ; | RetAddr | <- RSP is here\r
134 ; +-----------+\r
135 ; | Scratch1 | (RCX) <- RSI\r
136 ; +-----------+\r
137 ; | Scratch2 | (RDX)\r
138 ; +-----------+\r
139 ; | Scratch3 | (R8)\r
140 ; +-----------+\r
141 ; | Scratch4 | (R9)\r
142 ; +-----------+\r
143 ; | Arg5 |\r
144 ; +-----------+\r
145 ; | Arg6 |\r
146 ; +-----------+\r
147 ; | ... |\r
148 ; +-----------+\r
149 ; | Arg16 |\r
150 ; +-----------+\r
151 ;\r
152\r
153 ; save old parameter to stack\r
154 mov [rsp + 0x8], rcx\r
155 mov [rsp + 0x10], rdx\r
156 mov [rsp + 0x18], r8\r
157 mov [rsp + 0x20], r9\r
158\r
159 ; Construct new stack\r
160 push rbp\r
161 mov rbp, rsp\r
162 push rsi\r
163 push rdi\r
164 push rbx\r
165 sub rsp, 0x80\r
166 push r10\r
167 mov rsi, rbp\r
168 add rsi, 0x10\r
169 mov rdi, rsp\r
170 add rdi, 8\r
171 mov rcx, dword 16\r
172 rep movsq\r
173\r
174 ; build new paramater calling convention\r
175 mov r9, [rsp + 0x18]\r
176 mov r8, [rsp + 0x10]\r
177 mov rdx, [rsp + 0x8]\r
178 mov rcx, r10\r
179\r
180 ; call C-code\r
181 call ASM_PFX(EbcInterpret)\r
182 add rsp, 0x88\r
183 pop rbx\r
184 pop rdi\r
185 pop rsi\r
186 pop rbp\r
187 ret\r
188\r
189;****************************************************************************\r
190; EbcLLExecuteEbcImageEntryPoint\r
191;\r
192; Begin executing an EBC image.\r
193;****************************************************************************\r
194; UINT64 EbcLLExecuteEbcImageEntryPoint(VOID)\r
195global ASM_PFX(EbcLLExecuteEbcImageEntryPoint)\r
196ASM_PFX(EbcLLExecuteEbcImageEntryPoint):\r
197 ;\r
198 ;; mov rax, ca112ebccall2ebch\r
199 ;; mov r10, EbcEntryPoint\r
200 ;; mov r11, EbcLLExecuteEbcImageEntryPoint\r
201 ;; jmp r11\r
202 ;\r
203 ; Caller uses above instruction to jump here\r
204 ; The stack is below:\r
205 ; +-----------+\r
206 ; | RetAddr |\r
207 ; +-----------+\r
208 ; |EntryPoint | (R10)\r
209 ; +-----------+\r
210 ; |ImageHandle|\r
211 ; +-----------+\r
212 ; |SystemTable|\r
213 ; +-----------+\r
214 ; | Dummy |\r
215 ; +-----------+\r
216 ; | Dummy |\r
217 ; +-----------+\r
218 ; | RetAddr | <- RSP is here\r
219 ; +-----------+\r
220 ; |ImageHandle| (RCX)\r
221 ; +-----------+\r
222 ; |SystemTable| (RDX)\r
223 ; +-----------+\r
224 ;\r
225\r
226 ; build new paramater calling convention\r
227 mov r8, rdx\r
228 mov rdx, rcx\r
229 mov rcx, r10\r
230\r
231 ; call C-code\r
232 sub rsp, 0x28\r
233 call ASM_PFX(ExecuteEbcImageEntryPoint)\r
234 add rsp, 0x28\r
235 ret\r
236\r