| ;/** @file | |
| ; | |
| ; This code provides low level routines that support the Virtual Machine. | |
| ; for option ROMs. | |
| ; | |
| ; Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR> | |
| ; Copyright (c) 2014 Hewlett-Packard Development Company, L.P.<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. | |
| ; | |
| ;**/ | |
| page ,132 | |
| title VM ASSEMBLY LANGUAGE ROUTINES | |
| ;--------------------------------------------------------------------------- | |
| ; Equate files needed. | |
| ;--------------------------------------------------------------------------- | |
| .CODE | |
| CopyMem PROTO Destination:PTR DWORD, Source:PTR DWORD, Count:DWORD | |
| EbcInterpret PROTO | |
| ExecuteEbcImageEntryPoint PROTO | |
| ;**************************************************************************** | |
| ; 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. | |
| ;**************************************************************************** | |
| ; INT64 EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr) | |
| EbcLLCALLEXNative PROC PUBLIC | |
| push rbp | |
| push rbx | |
| mov rbp, rsp | |
| ; Function prolog | |
| ; Copy FuncAddr to a preserved register. | |
| mov rbx, rcx | |
| ; Set stack pointer to new value | |
| sub r8, rdx | |
| ; | |
| ; Fix X64 native function call prolog. Prepare space for at least 4 arguments, | |
| ; even if the native function's arguments are less than 4. | |
| ; | |
| ; From MSDN x64 Software Conventions, Overview of x64 Calling Conventions: | |
| ; "The caller is responsible for allocating space for parameters to the | |
| ; callee, and must always allocate sufficient space for the 4 register | |
| ; parameters, even if the callee doesn't have that many parameters. | |
| ; This aids in the simplicity of supporting C unprototyped functions, | |
| ; and vararg C/C++ functions." | |
| ; | |
| cmp r8, 20h | |
| jae skip_expansion | |
| mov r8, 20h | |
| skip_expansion: | |
| sub rsp, r8 | |
| ; | |
| ; Fix X64 native function call 16-byte alignment. | |
| ; | |
| ; From MSDN x64 Software Conventions, Stack Usage: | |
| ; "The stack will always be maintained 16-byte aligned, except within | |
| ; the prolog (for example, after the return address is pushed)." | |
| ; | |
| and rsp, NOT 0fh | |
| mov rcx, rsp | |
| sub rsp, 20h | |
| call CopyMem | |
| add rsp, 20h | |
| ; Considering the worst case, load 4 potiential arguments | |
| ; into registers. | |
| mov rcx, qword ptr [rsp] | |
| mov rdx, qword ptr [rsp+8h] | |
| mov r8, qword ptr [rsp+10h] | |
| mov r9, qword ptr [rsp+18h] | |
| ; Now call the external routine | |
| call rbx | |
| ; Function epilog | |
| mov rsp, rbp | |
| pop rbx | |
| pop rbp | |
| ret | |
| EbcLLCALLEXNative ENDP | |
| ;**************************************************************************** | |
| ; EbcLLEbcInterpret | |
| ; | |
| ; Begin executing an EBC image. | |
| ;**************************************************************************** | |
| ; UINT64 EbcLLEbcInterpret(VOID) | |
| EbcLLEbcInterpret PROC PUBLIC | |
| ; | |
| ;; mov rax, ca112ebccall2ebch | |
| ;; mov r10, EbcEntryPoint | |
| ;; mov r11, EbcLLEbcInterpret | |
| ;; jmp r11 | |
| ; | |
| ; Caller uses above instruction to jump here | |
| ; The stack is below: | |
| ; +-----------+ | |
| ; | RetAddr | | |
| ; +-----------+ | |
| ; |EntryPoint | (R10) | |
| ; +-----------+ | |
| ; | Arg1 | <- RDI | |
| ; +-----------+ | |
| ; | Arg2 | | |
| ; +-----------+ | |
| ; | ... | | |
| ; +-----------+ | |
| ; | Arg16 | | |
| ; +-----------+ | |
| ; | Dummy | | |
| ; +-----------+ | |
| ; | RDI | | |
| ; +-----------+ | |
| ; | RSI | | |
| ; +-----------+ | |
| ; | RBP | <- RBP | |
| ; +-----------+ | |
| ; | RetAddr | <- RSP is here | |
| ; +-----------+ | |
| ; | Scratch1 | (RCX) <- RSI | |
| ; +-----------+ | |
| ; | Scratch2 | (RDX) | |
| ; +-----------+ | |
| ; | Scratch3 | (R8) | |
| ; +-----------+ | |
| ; | Scratch4 | (R9) | |
| ; +-----------+ | |
| ; | Arg5 | | |
| ; +-----------+ | |
| ; | Arg6 | | |
| ; +-----------+ | |
| ; | ... | | |
| ; +-----------+ | |
| ; | Arg16 | | |
| ; +-----------+ | |
| ; | |
| ; save old parameter to stack | |
| mov [rsp + 08h], rcx | |
| mov [rsp + 10h], rdx | |
| mov [rsp + 18h], r8 | |
| mov [rsp + 20h], r9 | |
| ; Construct new stack | |
| push rbp | |
| mov rbp, rsp | |
| push rsi | |
| push rdi | |
| push rbx | |
| sub rsp, 80h | |
| push r10 | |
| mov rsi, rbp | |
| add rsi, 10h | |
| mov rdi, rsp | |
| add rdi, 8 | |
| mov rcx, 16 | |
| rep movsq | |
| ; build new paramater calling convention | |
| mov r9, [rsp + 18h] | |
| mov r8, [rsp + 10h] | |
| mov rdx, [rsp + 08h] | |
| mov rcx, r10 | |
| ; call C-code | |
| call EbcInterpret | |
| add rsp, 88h | |
| pop rbx | |
| pop rdi | |
| pop rsi | |
| pop rbp | |
| ret | |
| EbcLLEbcInterpret ENDP | |
| ;**************************************************************************** | |
| ; EbcLLExecuteEbcImageEntryPoint | |
| ; | |
| ; Begin executing an EBC image. | |
| ;**************************************************************************** | |
| ; UINT64 EbcLLExecuteEbcImageEntryPoint(VOID) | |
| EbcLLExecuteEbcImageEntryPoint PROC PUBLIC | |
| ; | |
| ;; mov rax, ca112ebccall2ebch | |
| ;; mov r10, EbcEntryPoint | |
| ;; mov r11, EbcLLExecuteEbcImageEntryPoint | |
| ;; jmp r11 | |
| ; | |
| ; Caller uses above instruction to jump here | |
| ; The stack is below: | |
| ; +-----------+ | |
| ; | RetAddr | | |
| ; +-----------+ | |
| ; |EntryPoint | (R10) | |
| ; +-----------+ | |
| ; |ImageHandle| | |
| ; +-----------+ | |
| ; |SystemTable| | |
| ; +-----------+ | |
| ; | Dummy | | |
| ; +-----------+ | |
| ; | Dummy | | |
| ; +-----------+ | |
| ; | RetAddr | <- RSP is here | |
| ; +-----------+ | |
| ; |ImageHandle| (RCX) | |
| ; +-----------+ | |
| ; |SystemTable| (RDX) | |
| ; +-----------+ | |
| ; | |
| ; build new paramater calling convention | |
| mov r8, rdx | |
| mov rdx, rcx | |
| mov rcx, r10 | |
| ; call C-code | |
| sub rsp, 28h | |
| call ExecuteEbcImageEntryPoint | |
| add rsp, 28h | |
| ret | |
| EbcLLExecuteEbcImageEntryPoint ENDP | |
| END | |