Add missing EFIPAI for EbcInterpret and ExecuteEbcImageEntryPoint(). Get return value in EbcLLCALLEXNative(), remove EbcLLGetReturnValue(). 2) Fix IA32 EBC interpreter bug on MOVsnw and MOVsnd. 3) Some cleanup Add missing ReturnEBCStack() for IA32 build. Remove unnecessary EbcLLGetStackPointer() for X64 and IPF build. Remove deadcode EbcLLGetStackPointer() and EbcLLGetReturnValue() in IA32/X64/IPF ASM code. Dump more info in CommonEbcExceptionHandler(). Signed-off-by: jyao1 Reviewed-by: Elvinli git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12745 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			207 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			207 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| ///** @file
 | |
| //  
 | |
| //  Contains low level routines for the Virtual Machine implementation
 | |
| //  on an Itanium-based platform.
 | |
| //
 | |
| //  Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<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.
 | |
| //  
 | |
| //**/
 | |
| 
 | |
| .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)
 | |
| 
 | |
| //-----------------------------------------------------------------------------
 | |
| //++
 | |
| // EbcLLCALLEXNative
 | |
| //
 | |
| //  This function is called to execute an EBC CALLEX instruction.
 | |
| //  This instruction requires that we thunk out to external native
 | |
| //  code. On return, we restore the stack pointer to its original location.
 | |
| //  Destroys no working registers.  For IPF, at least 8 register slots
 | |
| //  must be allocated on the stack frame to support any number of 
 | |
| //  arguments beiung passed to the external native function.  The
 | |
| //  size of the stack frame is FramePtr - EbcSp.  If this size is less
 | |
| //  than 64-bytes, the amount of stack frame allocated is rounded up
 | |
| //  to 64-bytes 
 | |
| //
 | |
| // Arguments On Entry :
 | |
| //    in0 = CallAddr     The function address.
 | |
| //    in1 = EbcSp        The new EBC stack pointer.
 | |
| //    in2 = FramePtr     The frame pointer.
 | |
| //
 | |
| // Return Value:
 | |
| //    None
 | |
| //
 | |
| // C Function Prototype:
 | |
| //    VOID
 | |
| //    EFIAPI
 | |
| //    EbcLLCALLEXNative (
 | |
| //      IN UINTN        CallAddr,
 | |
| //      IN UINTN        EbcSp,
 | |
| //      IN VOID         *FramePtr
 | |
| //      );
 | |
| //--
 | |
| //---------------------------------------------------------------------------
 | |
| 
 | |
| PROCEDURE_ENTRY(EbcLLCALLEXNative)
 | |
|   NESTED_SETUP (3,6,3,0)
 | |
| 
 | |
|   mov   loc2 = in2;;              // loc2 = in2 = FramePtr
 | |
|   mov   loc3 = in1;;              // loc3 = in1 = EbcSp
 | |
|   sub   loc2 = loc2, loc3;;       // loc2 = loc2 - loc3 = FramePtr - EbcSp
 | |
|   mov   out2 = loc2;;             // out2 = loc2 = FramePtr - EbcSp
 | |
|   mov   loc4 = 0x40;;             // loc4 = 0x40
 | |
|   cmp.leu p6  = out2, loc4;;      // IF out2 < loc4 THEN P6=1 ELSE P6=0; IF (FramePtr - EbcSp) < 0x40 THEN P6 = 1 ELSE P6=0
 | |
|   (p6) mov   loc2 = loc4;;        // IF P6==1 THEN loc2 = loc4 = 0x40
 | |
|   mov   loc4 = r12;;              // save sp
 | |
|   or    loc5 = r1, r0             // save gp
 | |
| 
 | |
|   sub   r12 = r12, loc2;;         // sp = sp - loc2 = sp - MAX (0x40, FramePtr - EbcSp)
 | |
| 
 | |
|   and   r12 = -0x10, r12          // Round sp down to the nearest 16-byte boundary
 | |
|   mov   out1 = in1;;              // out1 = EbcSp
 | |
|   mov   out0 = r12;;              // out0 = sp
 | |
|   adds  r12 = -0x8, r12           
 | |
|   (p0) br.call.dptk.many b0 = CopyMem;;      // CopyMem (sp, EbcSp, (FramePtr - EbcSp))
 | |
|   adds  r12 = 0x8, r12            
 | |
| 
 | |
|   mov   out0 = in0;;              // out0 = CallAddr
 | |
|   mov   out1 = r12;;              // out1 = sp
 | |
|   (p0) br.call.dptk.many b0 = EbcAsmLLCALLEX;;    // EbcAsmLLCALLEX (CallAddr, sp)
 | |
|   mov   r12 = loc4;;              // restore sp
 | |
|   or    r1 = loc5, r0             // restore gp
 | |
| 
 | |
|   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)
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |