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