3 // This code provides low level routines that support the Virtual Machine
6 // Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR>
7 // Copyright (c) 2015, The Linux Foundation. All rights reserved.<BR>
8 // Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
10 // This program and the accompanying materials
11 // are licensed and made available under the terms and conditions of the BSD License
12 // which accompanies this distribution. The full text of the license may be found at
13 // http://opensource.org/licenses/bsd-license.php
15 // THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16 // WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative)
21 ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret)
22 ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint)
24 ASM_GLOBAL ASM_PFX(mEbcInstructionBufferTemplate)
26 //****************************************************************************
29 // This function is called to execute an EBC CALLEX instruction.
30 // This instruction requires that we thunk out to external native
31 // code. For AArch64, we copy the VM stack into the main stack and then pop
32 // the first 8 arguments off according to the AArch64 Procedure Call Standard
33 // On return, we restore the stack pointer to its original location.
35 //****************************************************************************
36 // UINTN EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)
37 ASM_PFX(EbcLLCALLEXNative):
38 mov x8, x0 // Preserve x0
39 mov x9, x1 // Preserve x1
42 // If the EBC stack frame is smaller than or equal to 64 bytes, we know there
43 // are no stacked arguments #9 and beyond that we need to copy to the native
44 // stack. In this case, we can perform a tail call which is much more
45 // efficient, since there is no need to touch the native stack at all.
47 sub x3, x2, x1 // Length = NewStackPointer - FramePtr
52 // While probably harmless in practice, we should not access the VM stack
53 // outside of the interval [NewStackPointer, FramePtr), which means we
54 // should not blindly fill all 8 argument registers with VM stack data.
55 // So instead, calculate how many argument registers we can fill based on
56 // the size of the VM stack frame, and skip the remaining ones.
58 adr x0, 0f // Take address of 'br' instruction below
59 bic x3, x3, #7 // Ensure correct alignment
60 sub x0, x0, x3, lsr #1 // Subtract 4 bytes for each arg to unstack
61 br x0 // Skip remaining argument registers
63 ldr x7, [x9, #56] // Call with 8 arguments
64 ldr x6, [x9, #48] // |
65 ldr x5, [x9, #40] // |
66 ldr x4, [x9, #32] // |
67 ldr x3, [x9, #24] // |
68 ldr x2, [x9, #16] // |
70 ldr x0, [x9] // Call with 1 argument
72 0: br x8 // Call with no arguments
75 // More than 64 bytes: we need to build the full native stack frame and copy
76 // the part of the VM stack exceeding 64 bytes (which may contain stacked
77 // arguments) to the native stack
79 1: stp x29, x30, [sp, #-16]!
83 // Ensure that the stack pointer remains 16 byte aligned,
84 // even if the size of the VM stack frame is not a multiple of 16
86 add x1, x1, #64 // Skip over [potential] reg params
87 tbz x3, #3, 2f // Multiple of 16?
88 ldr x4, [x2, #-8]! // No? Then push one word
89 str x4, [sp, #-16]! // ... but use two slots
92 2: ldp x4, x5, [x2, #-16]!
93 stp x4, x5, [sp, #-16]!
100 ldp x6, x7, [x9, #48]
105 ldp x29, x30, [sp], #16
108 //****************************************************************************
111 // This function is called by the thunk code to handle an Native to EBC call
112 // This can handle up to 16 arguments (1-8 on in x0-x7, 9-16 are on the stack)
113 // x16 contains the Entry point that will be the first argument when
114 // EBCInterpret is called.
116 //****************************************************************************
117 ASM_PFX(EbcLLEbcInterpret):
118 stp x29, x30, [sp, #-16]!
120 // copy the current arguments 9-16 from old location and add arg 7 to stack
121 // keeping 16 byte stack alignment
141 // Shift arguments and add entry point and as argument 1
152 bl ASM_PFX(EbcInterpret)
155 ldp x29, x30, [sp], #16
159 //****************************************************************************
160 // EbcLLExecuteEbcImageEntryPoint
162 // This function is called by the thunk code to handle the image entry point
163 // x16 contains the Entry point that will be the third argument when
164 // ExecuteEbcImageEntryPoint is called.
166 //****************************************************************************
167 ASM_PFX(EbcLLExecuteEbcImageEntryPoint):
168 stp x29, x30, [sp, #-16]!
169 // build new parameter calling convention
175 bl ASM_PFX(ExecuteEbcImageEntryPoint)
176 ldp x29, x30, [sp], #16
179 //****************************************************************************
180 // mEbcInstructionBufferTemplate
181 //****************************************************************************
182 .section ".rodata", "a"
184 ASM_PFX(mEbcInstructionBufferTemplate):
190 // Add a magic code here to help the VM recognize the thunk.
194 0: .quad 0 // EBC_ENTRYPOINT_SIGNATURE
195 .quad 0 // EBC_LL_EBC_ENTRYPOINT_SIGNATURE