]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/EbcDxe/AArch64/EbcLowLevel.S
MdeModulePkg/EbcDxe AARCH64: simplify interpreter entry point thunks
[mirror_edk2.git] / MdeModulePkg / Universal / EbcDxe / AArch64 / EbcLowLevel.S
CommitLineData
72b0eaa0
AB
1///** @file\r
2//\r
3// This code provides low level routines that support the Virtual Machine\r
4// for option ROMs.\r
5//\r
4d1f5a21
AB
6// Copyright (c) 2016, Linaro, Ltd. All rights reserved.<BR>\r
7// Copyright (c) 2015, The Linux Foundation. All rights reserved.<BR>\r
72b0eaa0 8// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
4d1f5a21 9//\r
72b0eaa0
AB
10// This program and the accompanying materials\r
11// are licensed and made available under the terms and conditions of the BSD License\r
12// which accompanies this distribution. The full text of the license may be found at\r
13// http://opensource.org/licenses/bsd-license.php\r
14//\r
15// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
16// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
17//\r
18//**/\r
19\r
20ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative)\r
21ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret)\r
22ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint)\r
23\r
4d1f5a21
AB
24ASM_GLOBAL ASM_PFX(mEbcInstructionBufferTemplate)\r
25\r
72b0eaa0
AB
26//****************************************************************************\r
27// EbcLLCALLEX\r
28//\r
29// This function is called to execute an EBC CALLEX instruction.\r
30// This instruction requires that we thunk out to external native\r
31// code. For AArch64, we copy the VM stack into the main stack and then pop\r
32// the first 8 arguments off according to the AArch64 Procedure Call Standard\r
33// On return, we restore the stack pointer to its original location.\r
34//\r
35//****************************************************************************\r
36// UINTN EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)\r
a15e5bc2 37ASM_PFX(EbcLLCALLEXNative):\r
3226e315
AB
38 mov x8, x0 // Preserve x0\r
39 mov x9, x1 // Preserve x1\r
a15e5bc2 40\r
3226e315
AB
41 //\r
42 // If the EBC stack frame is smaller than or equal to 64 bytes, we know there\r
43 // are no stacked arguments #9 and beyond that we need to copy to the native\r
44 // stack. In this case, we can perform a tail call which is much more\r
45 // efficient, since there is no need to touch the native stack at all.\r
46 //\r
47 sub x3, x2, x1 // Length = NewStackPointer - FramePtr\r
48 cmp x3, #64\r
49 b.gt 1f\r
a15e5bc2 50\r
3226e315
AB
51 //\r
52 // While probably harmless in practice, we should not access the VM stack\r
53 // outside of the interval [NewStackPointer, FramePtr), which means we\r
54 // should not blindly fill all 8 argument registers with VM stack data.\r
55 // So instead, calculate how many argument registers we can fill based on\r
56 // the size of the VM stack frame, and skip the remaining ones.\r
57 //\r
58 adr x0, 0f // Take address of 'br' instruction below\r
59 bic x3, x3, #7 // Ensure correct alignment\r
60 sub x0, x0, x3, lsr #1 // Subtract 4 bytes for each arg to unstack\r
61 br x0 // Skip remaining argument registers\r
a15e5bc2 62\r
3226e315
AB
63 ldr x7, [x9, #56] // Call with 8 arguments\r
64 ldr x6, [x9, #48] // |\r
65 ldr x5, [x9, #40] // |\r
66 ldr x4, [x9, #32] // |\r
67 ldr x3, [x9, #24] // |\r
68 ldr x2, [x9, #16] // |\r
69 ldr x1, [x9, #8] // V\r
70 ldr x0, [x9] // Call with 1 argument\r
a15e5bc2 71\r
3226e315 720: br x8 // Call with no arguments\r
a15e5bc2 73\r
3226e315
AB
74 //\r
75 // More than 64 bytes: we need to build the full native stack frame and copy\r
76 // the part of the VM stack exceeding 64 bytes (which may contain stacked\r
77 // arguments) to the native stack\r
78 //\r
791: stp x29, x30, [sp, #-16]!\r
80 mov x29, sp\r
a15e5bc2 81\r
3226e315
AB
82 //\r
83 // Ensure that the stack pointer remains 16 byte aligned,\r
84 // even if the size of the VM stack frame is not a multiple of 16\r
85 //\r
86 add x1, x1, #64 // Skip over [potential] reg params\r
87 tbz x3, #3, 2f // Multiple of 16?\r
88 ldr x4, [x2, #-8]! // No? Then push one word\r
89 str x4, [sp, #-16]! // ... but use two slots\r
90 b 3f\r
91\r
922: ldp x4, x5, [x2, #-16]!\r
93 stp x4, x5, [sp, #-16]!\r
943: cmp x2, x1\r
95 b.gt 2b\r
96\r
97 ldp x0, x1, [x9]\r
98 ldp x2, x3, [x9, #16]\r
99 ldp x4, x5, [x9, #32]\r
100 ldp x6, x7, [x9, #48]\r
101\r
102 blr x8\r
103\r
104 mov sp, x29\r
105 ldp x29, x30, [sp], #16\r
106 ret\r
a15e5bc2 107\r
72b0eaa0
AB
108//****************************************************************************\r
109// EbcLLEbcInterpret\r
110//\r
111// This function is called by the thunk code to handle an Native to EBC call\r
112// This can handle up to 16 arguments (1-8 on in x0-x7, 9-16 are on the stack)\r
4a2aaff2 113// x16 contains the Entry point that will be the first stacked argument when\r
72b0eaa0
AB
114// EBCInterpret is called.\r
115//\r
116//****************************************************************************\r
a15e5bc2 117ASM_PFX(EbcLLEbcInterpret):\r
4a2aaff2
AB
118 stp x29, x30, [sp, #-16]!\r
119 mov x29, sp\r
a15e5bc2 120\r
4a2aaff2
AB
121 // push the entry point and the address of args #9 - #16 onto the stack\r
122 add x17, sp, #16\r
123 stp x16, x17, [sp, #-16]!\r
a15e5bc2 124\r
4a2aaff2
AB
125 // call C-code\r
126 bl ASM_PFX(EbcInterpret)\r
a15e5bc2 127\r
4a2aaff2
AB
128 add sp, sp, #16\r
129 ldp x29, x30, [sp], #16\r
a15e5bc2
JB
130 ret\r
131\r
72b0eaa0
AB
132//****************************************************************************\r
133// EbcLLExecuteEbcImageEntryPoint\r
134//\r
135// This function is called by the thunk code to handle the image entry point\r
4d1f5a21 136// x16 contains the Entry point that will be the third argument when\r
72b0eaa0
AB
137// ExecuteEbcImageEntryPoint is called.\r
138//\r
139//****************************************************************************\r
a15e5bc2 140ASM_PFX(EbcLLExecuteEbcImageEntryPoint):\r
4a2aaff2 141 mov x2, x16\r
a15e5bc2 142\r
4a2aaff2
AB
143 // tail call to C code\r
144 b ASM_PFX(ExecuteEbcImageEntryPoint)\r
4d1f5a21
AB
145\r
146//****************************************************************************\r
147// mEbcInstructionBufferTemplate\r
148//****************************************************************************\r
149 .section ".rodata", "a"\r
150 .align 3\r
151ASM_PFX(mEbcInstructionBufferTemplate):\r
152 adr x17, 0f\r
153 ldp x16, x17, [x17]\r
154 br x17\r
155\r
156 //\r
157 // Add a magic code here to help the VM recognize the thunk.\r
158 //\r
159 hlt #0xEBC\r
160\r
1610: .quad 0 // EBC_ENTRYPOINT_SIGNATURE\r
162 .quad 0 // EBC_LL_EBC_ENTRYPOINT_SIGNATURE\r