MdeModulePkg EbcDxe: Convert X64/EbcLowLevel.asm to NASM

The BaseTools/Scripts/ConvertMasmToNasm.py script was used to convert
X64/EbcLowLevel.asm to X64/EbcLowLevel.nasm

And, manually update nasm code to use mov rcx, dword value and generate
the same assembly code with rcx register to asm code.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf b/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
index 44558aa..15dc01c 100644
--- a/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
@@ -45,6 +45,7 @@
 

 [Sources.X64]

   X64/EbcSupport.c

+  X64/EbcLowLevel.nasm

   X64/EbcLowLevel.S

   X64/EbcLowLevel.asm

 

diff --git a/MdeModulePkg/Universal/EbcDxe/X64/EbcLowLevel.nasm b/MdeModulePkg/Universal/EbcDxe/X64/EbcLowLevel.nasm
new file mode 100644
index 0000000..19299a7
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/X64/EbcLowLevel.nasm
@@ -0,0 +1,242 @@
+;/** @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.

+;

+;**/

+

+;---------------------------------------------------------------------------

+; Equate files needed.

+;---------------------------------------------------------------------------

+

+DEFAULT REL

+SECTION .text

+

+extern ASM_PFX(CopyMem)

+extern ASM_PFX(EbcInterpret)

+extern ASM_PFX(ExecuteEbcImageEntryPoint)

+

+;****************************************************************************

+; 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)

+global ASM_PFX(EbcLLCALLEXNative)

+ASM_PFX(EbcLLCALLEXNative):

+      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, 0x20

+      jae    skip_expansion

+      mov    r8, dword 0x20

+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, ~ 0xf

+

+      mov    rcx, rsp

+      sub    rsp, 0x20

+      call   ASM_PFX(CopyMem)

+      add    rsp, 0x20

+

+      ; Considering the worst case, load 4 potiential arguments

+      ; into registers.

+      mov    rcx, qword [rsp]

+      mov    rdx, qword [rsp+0x8]

+      mov    r8,  qword [rsp+0x10]

+      mov    r9,  qword [rsp+0x18]

+

+      ; Now call the external routine

+      call  rbx

+

+      ; Function epilog

+      mov      rsp, rbp

+      pop      rbx

+      pop      rbp

+      ret

+

+;****************************************************************************

+; EbcLLEbcInterpret

+;

+; Begin executing an EBC image.

+;****************************************************************************

+; UINT64 EbcLLEbcInterpret(VOID)

+global ASM_PFX(EbcLLEbcInterpret)

+ASM_PFX(EbcLLEbcInterpret):

+    ;

+    ;; 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 + 0x8], rcx

+    mov  [rsp + 0x10], rdx

+    mov  [rsp + 0x18], r8

+    mov  [rsp + 0x20], r9

+

+    ; Construct new stack

+    push rbp

+    mov  rbp, rsp

+    push rsi

+    push rdi

+    push rbx

+    sub  rsp, 0x80

+    push r10

+    mov  rsi, rbp

+    add  rsi, 0x10

+    mov  rdi, rsp

+    add  rdi, 8

+    mov  rcx, dword 16

+    rep  movsq

+

+    ; build new paramater calling convention

+    mov  r9,  [rsp + 0x18]

+    mov  r8,  [rsp + 0x10]

+    mov  rdx, [rsp + 0x8]

+    mov  rcx, r10

+

+    ; call C-code

+    call ASM_PFX(EbcInterpret)

+    add  rsp, 0x88

+    pop  rbx

+    pop  rdi

+    pop  rsi

+    pop  rbp

+    ret

+

+;****************************************************************************

+; EbcLLExecuteEbcImageEntryPoint

+;

+; Begin executing an EBC image.

+;****************************************************************************

+; UINT64 EbcLLExecuteEbcImageEntryPoint(VOID)

+global ASM_PFX(EbcLLExecuteEbcImageEntryPoint)

+ASM_PFX(EbcLLExecuteEbcImageEntryPoint):

+    ;

+    ;; 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, 0x28

+    call ASM_PFX(ExecuteEbcImageEntryPoint)

+    add  rsp, 0x28

+    ret

+