--- /dev/null
+ page ,132\r
+ title VM ASSEMBLY LANGUAGE ROUTINES\r
+;****************************************************************************\r
+;* \r
+;* Copyright (c) 2006, Intel Corporation \r
+;* All rights reserved. This program and the accompanying materials \r
+;* are licensed and made available under the terms and conditions of the BSD License \r
+;* which accompanies this distribution. The full text of the license may be found at \r
+;* http://opensource.org/licenses/bsd-license.php \r
+;* \r
+;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+;* \r
+;****************************************************************************\r
+;****************************************************************************\r
+; REV 1.0\r
+;****************************************************************************\r
+;\r
+; Rev Date Description\r
+; --- -------- ------------------------------------------------------------\r
+; 1.0 05/09/12 Initial creation of file.\r
+;\r
+;****************************************************************************\r
+ \r
+;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\r
+; This code provides low level routines that support the Virtual Machine\r
+; for option ROMs. \r
+;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\r
+\r
+;---------------------------------------------------------------------------\r
+; Equate files needed.\r
+;---------------------------------------------------------------------------\r
+\r
+text SEGMENT\r
+\r
+;---------------------------------------------------------------------------\r
+;;GenericPostSegment SEGMENT USE16\r
+;---------------------------------------------------------------------------\r
+\r
+;****************************************************************************\r
+; EbcLLCALLEX\r
+;\r
+; This function is called to execute an EBC CALLEX instruction. \r
+; This instruction requires that we thunk out to external native\r
+; code. For x64, we switch stacks, copy the arguments to the stack\r
+; and jump to the specified function. \r
+; On return, we restore the stack pointer to its original location.\r
+;\r
+; Destroys no working registers.\r
+;****************************************************************************\r
+; VOID EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)\r
+\r
+CopyMem PROTO Destination:PTR DWORD, Source:PTR DWORD, Count:DWORD\r
+\r
+\r
+EbcLLCALLEXNative PROC NEAR PUBLIC\r
+ push rbp\r
+ push rbx\r
+ mov rbp, rsp\r
+ ; Function prolog\r
+ \r
+ ; Copy FuncAddr to a preserved register.\r
+ mov rbx, rcx\r
+\r
+ ; Set stack pointer to new value\r
+ sub r8, rdx\r
+ sub rsp, r8\r
+ mov rcx, rsp\r
+ sub rsp, 20h\r
+ call CopyMem \r
+ add rsp, 20h\r
+ \r
+ ; Considering the worst case, load 4 potiential arguments\r
+ ; into registers.\r
+ mov rcx, qword ptr [rsp]\r
+ mov rdx, qword ptr [rsp+8h]\r
+ mov r8, qword ptr [rsp+10h]\r
+ mov r9, qword ptr [rsp+18h]\r
+\r
+ ; Now call the external routine\r
+ call rbx\r
+ \r
+ ; Function epilog\r
+ mov rsp, rbp\r
+ pop rbx\r
+ pop rbp\r
+ ret\r
+EbcLLCALLEXNative ENDP\r
+\r
+\r
+; UINTN EbcLLGetEbcEntryPoint(VOID);\r
+; Routine Description:\r
+; The VM thunk code stuffs an EBC entry point into a processor\r
+; register. Since we can't use inline assembly to get it from\r
+; the interpreter C code, stuff it into the return value \r
+; register and return.\r
+;\r
+; Arguments:\r
+; None.\r
+;\r
+; Returns:\r
+; The contents of the register in which the entry point is passed.\r
+;\r
+EbcLLGetEbcEntryPoint PROC NEAR PUBLIC\r
+ ret\r
+EbcLLGetEbcEntryPoint ENDP\r
+\r
+;/*++\r
+;\r
+;Routine Description:\r
+; \r
+; Return the caller's value of the stack pointer.\r
+;\r
+;Arguments:\r
+;\r
+; None.\r
+;\r
+;Returns:\r
+;\r
+; The current value of the stack pointer for the caller. We\r
+; adjust it by 4 here because when they called us, the return address\r
+; is put on the stack, thereby lowering it by 4 bytes.\r
+;\r
+;--*/\r
+\r
+; UINTN EbcLLGetStackPointer() \r
+EbcLLGetStackPointer PROC NEAR PUBLIC\r
+ mov rax, rsp ; get current stack pointer\r
+ ; Stack adjusted by this much when we were called,\r
+ ; For this function, it's 4.\r
+ add rax, 4\r
+ ret\r
+EbcLLGetStackPointer ENDP\r
+\r
+; UINT64 EbcLLGetReturnValue(VOID);\r
+; Routine Description:\r
+; When EBC calls native, on return the VM has to stuff the return\r
+; value into a VM register. It's assumed here that the value is still\r
+; in the register, so simply return and the caller should get the\r
+; return result properly.\r
+;\r
+; Arguments:\r
+; None.\r
+;\r
+; Returns:\r
+; The unmodified value returned by the native code.\r
+;\r
+EbcLLGetReturnValue PROC NEAR PUBLIC\r
+ ret\r
+EbcLLGetReturnValue ENDP\r
+\r
+text ENDS\r
+END\r
+\r