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