summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/EbcDxe/Ipf/EbcLowLevel.s
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Universal/EbcDxe/Ipf/EbcLowLevel.s')
-rw-r--r--MdeModulePkg/Universal/EbcDxe/Ipf/EbcLowLevel.s197
1 files changed, 197 insertions, 0 deletions
diff --git a/MdeModulePkg/Universal/EbcDxe/Ipf/EbcLowLevel.s b/MdeModulePkg/Universal/EbcDxe/Ipf/EbcLowLevel.s
new file mode 100644
index 0000000..e329b68
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/Ipf/EbcLowLevel.s
@@ -0,0 +1,197 @@
+//++
+// Copyright (c) 2006, Intel Corporation
+// All rights reserved. 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.
+//
+// Module Name:
+//
+// EbcLowLevel.s
+//
+// Abstract:
+//
+// Contains low level routines for the Virtual Machine implementation
+// on an Itanium-based platform.
+//
+//
+//--
+
+.file "EbcLowLevel.s"
+
+#define PROCEDURE_ENTRY(name) .##text; \
+ .##type name, @function; \
+ .##proc name; \
+name::
+
+#define PROCEDURE_EXIT(name) .##endp name
+
+// Note: use of NESTED_SETUP requires number of locals (l) >= 3
+
+#define NESTED_SETUP(i,l,o,r) \
+ alloc loc1=ar##.##pfs,i,l,o,r ;\
+ mov loc0=b0
+
+#define NESTED_RETURN \
+ mov b0=loc0 ;\
+ mov ar##.##pfs=loc1 ;;\
+ br##.##ret##.##dpnt b0;;
+
+.type CopyMem, @function;
+
+//-----------------------------------------------------------------------------
+//++
+// EbcAsmLLCALLEX
+//
+// Implements the low level EBC CALLEX instruction. Sets up the
+// stack pointer, does the spill of function arguments, and
+// calls the native function. On return it restores the original
+// stack pointer and returns to the caller.
+//
+// Arguments :
+//
+// On Entry :
+// in0 = Address of native code to call
+// in1 = New stack pointer
+//
+// Return Value:
+//
+// As per static calling conventions.
+//
+//--
+//---------------------------------------------------------------------------
+;// void EbcAsmLLCALLEX (UINTN FunctionAddr, UINTN EbcStackPointer)
+PROCEDURE_ENTRY(EbcAsmLLCALLEX)
+ NESTED_SETUP (2,6,8,0)
+
+ // NESTED_SETUP uses loc0 and loc1 for context save
+
+ //
+ // Save a copy of the EBC VM stack pointer
+ //
+ mov r8 = in1;;
+
+ //
+ // Copy stack arguments from EBC stack into registers.
+ // Assume worst case and copy 8.
+ //
+ ld8 out0 = [r8], 8;;
+ ld8 out1 = [r8], 8;;
+ ld8 out2 = [r8], 8;;
+ ld8 out3 = [r8], 8;;
+ ld8 out4 = [r8], 8;;
+ ld8 out5 = [r8], 8;;
+ ld8 out6 = [r8], 8;;
+ ld8 out7 = [r8], 8;;
+
+ //
+ // Save the original stack pointer
+ //
+ mov loc2 = r12;
+
+ //
+ // Save the gp
+ //
+ or loc3 = r1, r0
+
+ //
+ // Set the new aligned stack pointer. Reserve space for the required
+ // 16-bytes of scratch area as well.
+ //
+ add r12 = 48, in1
+
+ //
+ // Now call the function. Load up the function address from the descriptor
+ // pointed to by in0. Then get the gp from the descriptor at the following
+ // address in the descriptor.
+ //
+ ld8 r31 = [in0], 8;;
+ ld8 r30 = [in0];;
+ mov b1 = r31
+ mov r1 = r30
+ (p0) br.call.dptk.many b0 = b1;;
+
+ //
+ // Restore the original stack pointer and gp
+ //
+ mov r12 = loc2
+ or r1 = loc3, r0
+
+ //
+ // Now return
+ //
+ NESTED_RETURN
+
+PROCEDURE_EXIT(EbcAsmLLCALLEX)
+
+PROCEDURE_ENTRY(EbcLLCALLEXNative)
+ NESTED_SETUP (3,6,3,0)
+
+ mov loc2 = in2;;
+ mov loc3 = in1;;
+ sub loc2 = loc2, loc3
+ mov loc4 = r12;;
+ or loc5 = r1, r0
+
+ sub r12 = r12, loc2
+ mov out2 = loc2;;
+
+ and r12 = -0x10, r12
+ mov out1 = in1;;
+ mov out0 = r12;;
+ adds r12 = -0x8, r12
+ (p0) br.call.dptk.many b0 = CopyMem;;
+ adds r12 = 0x8, r12
+
+ mov out0 = in0;;
+ mov out1 = r12;;
+ (p0) br.call.dptk.many b0 = EbcAsmLLCALLEX;;
+ mov r12 = loc4;;
+ or r1 = loc5, r0
+
+ NESTED_RETURN
+PROCEDURE_EXIT(EbcLLCALLEXNative)
+
+
+//
+// UINTN EbcLLGetEbcEntryPoint(VOID)
+//
+// Description:
+// Simply return, so that the caller retrieves the return register
+// contents (R8). That's where the thunk-to-ebc code stuffed the
+// EBC entry point.
+//
+PROCEDURE_ENTRY(EbcLLGetEbcEntryPoint)
+ br.ret.sptk b0 ;;
+PROCEDURE_EXIT(EbcLLGetEbcEntryPoint)
+
+//
+// INT64 EbcLLGetReturnValue(VOID)
+//
+// Description:
+// This function is called to get the value returned by native code
+// to EBC. It simply returns because the return value should still
+// be in the register, so the caller just gets the unmodified value.
+//
+PROCEDURE_ENTRY(EbcLLGetReturnValue)
+ br.ret.sptk b0 ;;
+PROCEDURE_EXIT(EbcLLGetReturnValue)
+
+//
+// UINTN EbcLLGetStackPointer(VOID)
+//
+PROCEDURE_ENTRY(EbcLLGetStackPointer)
+ mov r8 = r12 ;;
+ br.ret.sptk b0 ;;
+ br.sptk.few b6
+PROCEDURE_EXIT(EbcLLGetStackPointer)
+
+
+
+
+
+
+