mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 11:13:53 +01:00 
			
		
		
		
	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.” Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Samer El-Haj-Mahmoud elhaj@hp.com Reviewed by: Jiewen Yao <Jiewen.Yao@intel.com> Reviewed by: Feng Tian <Feng.Tian@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16152 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			247 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			247 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
| ;/** @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
 | |
| 
 |