]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/EbcDxe/Ipf/EbcLowLevel.s
Update the copyright notice format
[mirror_edk2.git] / MdeModulePkg / Universal / EbcDxe / Ipf / EbcLowLevel.s
CommitLineData
f45af90b 1///** @file\r
2// \r
3// Contains low level routines for the Virtual Machine implementation\r
4// on an Itanium-based platform.\r
5//\r
e5eed7d3
HT
6// Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>\r
7// This program and the accompanying materials\r
f45af90b 8// are licensed and made available under the terms and conditions of the BSD License\r
9// which accompanies this distribution. The full text of the license may be found at\r
10// http://opensource.org/licenses/bsd-license.php\r
11// \r
12// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14// \r
15//**/\r
53c71d09 16\r
17.file "EbcLowLevel.s"\r
18\r
19#define PROCEDURE_ENTRY(name) .##text; \\r
20 .##type name, @function; \\r
21 .##proc name; \\r
22name::\r
23\r
24#define PROCEDURE_EXIT(name) .##endp name\r
25\r
26// Note: use of NESTED_SETUP requires number of locals (l) >= 3\r
27\r
28#define NESTED_SETUP(i,l,o,r) \\r
29 alloc loc1=ar##.##pfs,i,l,o,r ;\\r
30 mov loc0=b0\r
31\r
32#define NESTED_RETURN \\r
33 mov b0=loc0 ;\\r
34 mov ar##.##pfs=loc1 ;;\\r
35 br##.##ret##.##dpnt b0;;\r
36\r
7b414b4e 37.type CopyMem, @function;\r
53c71d09 38\r
39//-----------------------------------------------------------------------------\r
40//++\r
41// EbcAsmLLCALLEX\r
42//\r
43// Implements the low level EBC CALLEX instruction. Sets up the\r
44// stack pointer, does the spill of function arguments, and\r
45// calls the native function. On return it restores the original\r
46// stack pointer and returns to the caller.\r
47//\r
7b414b4e 48// Arguments :\r
53c71d09 49//\r
50// On Entry :\r
51// in0 = Address of native code to call\r
52// in1 = New stack pointer\r
53//\r
7b414b4e 54// Return Value:\r
55//\r
56// As per static calling conventions.\r
57//\r
53c71d09 58//--\r
59//---------------------------------------------------------------------------\r
60;// void EbcAsmLLCALLEX (UINTN FunctionAddr, UINTN EbcStackPointer)\r
61PROCEDURE_ENTRY(EbcAsmLLCALLEX)\r
62 NESTED_SETUP (2,6,8,0)\r
63\r
64 // NESTED_SETUP uses loc0 and loc1 for context save\r
65\r
66 //\r
67 // Save a copy of the EBC VM stack pointer\r
68 //\r
69 mov r8 = in1;;\r
70\r
71 //\r
7b414b4e 72 // Copy stack arguments from EBC stack into registers.\r
53c71d09 73 // Assume worst case and copy 8.\r
74 //\r
75 ld8 out0 = [r8], 8;;\r
76 ld8 out1 = [r8], 8;;\r
77 ld8 out2 = [r8], 8;;\r
78 ld8 out3 = [r8], 8;;\r
79 ld8 out4 = [r8], 8;;\r
80 ld8 out5 = [r8], 8;;\r
81 ld8 out6 = [r8], 8;;\r
82 ld8 out7 = [r8], 8;;\r
83\r
84 //\r
85 // Save the original stack pointer\r
86 //\r
87 mov loc2 = r12;\r
88\r
89 //\r
90 // Save the gp\r
91 //\r
92 or loc3 = r1, r0\r
93\r
94 //\r
7b414b4e 95 // Set the new aligned stack pointer. Reserve space for the required\r
53c71d09 96 // 16-bytes of scratch area as well.\r
97 //\r
98 add r12 = 48, in1\r
99\r
100 //\r
101 // Now call the function. Load up the function address from the descriptor\r
102 // pointed to by in0. Then get the gp from the descriptor at the following\r
103 // address in the descriptor.\r
104 //\r
105 ld8 r31 = [in0], 8;;\r
106 ld8 r30 = [in0];;\r
107 mov b1 = r31\r
108 mov r1 = r30\r
109 (p0) br.call.dptk.many b0 = b1;;\r
110\r
111 //\r
112 // Restore the original stack pointer and gp\r
113 //\r
114 mov r12 = loc2\r
115 or r1 = loc3, r0\r
116\r
117 //\r
118 // Now return\r
119 //\r
120 NESTED_RETURN\r
121\r
122PROCEDURE_EXIT(EbcAsmLLCALLEX)\r
123\r
62ba2e4a 124//-----------------------------------------------------------------------------\r
125//++\r
126// EbcLLCALLEXNative\r
127//\r
128// This function is called to execute an EBC CALLEX instruction.\r
129// This instruction requires that we thunk out to external native\r
130// code. On return, we restore the stack pointer to its original location.\r
131// Destroys no working registers. For IPF, at least 8 register slots\r
132// must be allocated on the stack frame to support any number of \r
133// arguments beiung passed to the external native function. The\r
134// size of the stack frame is FramePtr - EbcSp. If this size is less\r
135// than 64-bytes, the amount of stack frame allocated is rounded up\r
136// to 64-bytes \r
137//\r
138// Arguments On Entry :\r
139// in0 = CallAddr The function address.\r
140// in1 = EbcSp The new EBC stack pointer.\r
141// in2 = FramePtr The frame pointer.\r
142//\r
143// Return Value:\r
144// None\r
145//\r
146// C Function Prototype:\r
147// VOID\r
148// EFIAPI\r
149// EbcLLCALLEXNative (\r
150// IN UINTN CallAddr,\r
151// IN UINTN EbcSp,\r
152// IN VOID *FramePtr\r
153// );\r
154//--\r
155//---------------------------------------------------------------------------\r
156\r
53c71d09 157PROCEDURE_ENTRY(EbcLLCALLEXNative)\r
158 NESTED_SETUP (3,6,3,0)\r
7b414b4e 159\r
62ba2e4a 160 mov loc2 = in2;; // loc2 = in2 = FramePtr\r
161 mov loc3 = in1;; // loc3 = in1 = EbcSp\r
162 sub loc2 = loc2, loc3;; // loc2 = loc2 - loc3 = FramePtr - EbcSp\r
163 mov out2 = loc2;; // out2 = loc2 = FramePtr - EbcSp\r
164 mov loc4 = 0x40;; // loc4 = 0x40\r
165 cmp.leu p6 = out2, loc4;; // IF out2 < loc4 THEN P6=1 ELSE P6=0; IF (FramePtr - EbcSp) < 0x40 THEN P6 = 1 ELSE P6=0\r
166 (p6) mov loc2 = loc4;; // IF P6==1 THEN loc2 = loc4 = 0x40\r
167 mov loc4 = r12;; // save sp\r
168 or loc5 = r1, r0 // save gp\r
169\r
170 sub r12 = r12, loc2;; // sp = sp - loc2 = sp - MAX (0x40, FramePtr - EbcSp)\r
171\r
172 and r12 = -0x10, r12 // Round sp down to the nearest 16-byte boundary\r
173 mov out1 = in1;; // out1 = EbcSp\r
174 mov out0 = r12;; // out0 = sp\r
175 adds r12 = -0x8, r12 \r
176 (p0) br.call.dptk.many b0 = CopyMem;; // CopyMem (sp, EbcSp, (FramePtr - EbcSp))\r
177 adds r12 = 0x8, r12 \r
178\r
179 mov out0 = in0;; // out0 = CallAddr\r
180 mov out1 = r12;; // out1 = sp\r
181 (p0) br.call.dptk.many b0 = EbcAsmLLCALLEX;; // EbcAsmLLCALLEX (CallAddr, sp)\r
182 mov r12 = loc4;; // restore sp\r
183 or r1 = loc5, r0 // restore gp\r
7b414b4e 184\r
53c71d09 185 NESTED_RETURN\r
186PROCEDURE_EXIT(EbcLLCALLEXNative)\r
187\r
188\r
189//\r
190// UINTN EbcLLGetEbcEntryPoint(VOID)\r
191//\r
192// Description:\r
193// Simply return, so that the caller retrieves the return register\r
194// contents (R8). That's where the thunk-to-ebc code stuffed the\r
195// EBC entry point.\r
196//\r
197PROCEDURE_ENTRY(EbcLLGetEbcEntryPoint)\r
198 br.ret.sptk b0 ;;\r
199PROCEDURE_EXIT(EbcLLGetEbcEntryPoint)\r
200\r
201//\r
202// INT64 EbcLLGetReturnValue(VOID)\r
203//\r
204// Description:\r
205// This function is called to get the value returned by native code\r
206// to EBC. It simply returns because the return value should still\r
207// be in the register, so the caller just gets the unmodified value.\r
208//\r
209PROCEDURE_ENTRY(EbcLLGetReturnValue)\r
210 br.ret.sptk b0 ;;\r
211PROCEDURE_EXIT(EbcLLGetReturnValue)\r
212\r
213//\r
214// UINTN EbcLLGetStackPointer(VOID)\r
215//\r
216PROCEDURE_ENTRY(EbcLLGetStackPointer)\r
217 mov r8 = r12 ;;\r
218 br.ret.sptk b0 ;;\r
7b414b4e 219 br.sptk.few b6\r
53c71d09 220PROCEDURE_EXIT(EbcLLGetStackPointer)\r
221\r
222\r
223\r
224\r
225\r
226\r
227\r