Reenable Gigacage on ARM64.
[WebKit-https.git] / Source / JavaScriptCore / assembler / MacroAssemblerARM64E.h
1 /*
2  * Copyright (C) 2018-2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #if ENABLE(ASSEMBLER) && CPU(ARM64E)
29
30 // We need to include this before MacroAssemblerARM64.h because MacroAssemblerARM64
31 // will be defined in terms of ARM64EAssembler for ARM64E.
32 #include "ARM64EAssembler.h"
33 #include "JSCPtrTag.h"
34 #include "MacroAssemblerARM64.h"
35
36 namespace JSC {
37
38 using Assembler = TARGET_ASSEMBLER;
39
40 class MacroAssemblerARM64E : public MacroAssemblerARM64 {
41 public:
42     static constexpr unsigned numberOfPACBits = 25;
43
44     ALWAYS_INLINE void tagReturnAddress()
45     {
46         tagPtr(ARM64Registers::sp, ARM64Registers::lr);
47     }
48
49     ALWAYS_INLINE void untagReturnAddress()
50     {
51         untagPtr(ARM64Registers::sp, ARM64Registers::lr);
52     }
53
54     ALWAYS_INLINE void tagPtr(PtrTag tag, RegisterID target)
55     {
56         auto tagGPR = getCachedDataTempRegisterIDAndInvalidate();
57         move(TrustedImm64(tag), tagGPR);
58         m_assembler.pacib(target, tagGPR);
59     }
60
61     ALWAYS_INLINE void tagPtr(RegisterID tag, RegisterID target)
62     {
63         if (target == ARM64Registers::lr && tag == ARM64Registers::sp) {
64             m_assembler.pacibsp();
65             return;
66         }
67         m_assembler.pacib(target, tag);
68     }
69
70     ALWAYS_INLINE void untagPtr(PtrTag tag, RegisterID target)
71     {
72         auto tagGPR = getCachedDataTempRegisterIDAndInvalidate();
73         move(TrustedImm64(tag), tagGPR);
74         m_assembler.autib(target, tagGPR);
75     }
76
77     ALWAYS_INLINE void untagPtr(RegisterID tag, RegisterID target)
78     {
79         m_assembler.autib(target, tag);
80     }
81
82     ALWAYS_INLINE void removePtrTag(RegisterID target)
83     {
84         m_assembler.xpaci(target);
85     }
86
87     ALWAYS_INLINE void tagArrayPtr(RegisterID length, RegisterID target)
88     {
89         m_assembler.pacdb(target, length);
90     }
91
92     ALWAYS_INLINE void untagArrayPtr(RegisterID length, RegisterID target)
93     {
94         m_assembler.autdb(target, length);
95     }
96
97     ALWAYS_INLINE void untagArrayPtr(Address length, RegisterID target)
98     {
99         auto lengthGPR = getCachedDataTempRegisterIDAndInvalidate();
100         load32(length, lengthGPR);
101         m_assembler.autdb(target, lengthGPR);
102     }
103
104     ALWAYS_INLINE void removeArrayPtrTag(RegisterID target)
105     {
106         m_assembler.xpacd(target);
107     }
108
109     static const RegisterID InvalidGPR  = static_cast<RegisterID>(-1);
110
111     enum class CallSignatureType {
112         CFunctionCall,
113         OtherCall
114     };
115
116     template<CallSignatureType type>
117     ALWAYS_INLINE Call callTrustedPtr(RegisterID tagGPR = InvalidGPR)
118     {
119         ASSERT(tagGPR != dataTempRegister);
120         AssemblerLabel pointerLabel = m_assembler.label();
121         moveWithFixedWidth(TrustedImmPtr(nullptr), getCachedDataTempRegisterIDAndInvalidate());
122         invalidateAllTempRegisters();
123         if (type == CallSignatureType::CFunctionCall)
124             m_assembler.blraaz(dataTempRegister);
125         else
126             m_assembler.blrab(dataTempRegister, tagGPR);
127         AssemblerLabel callLabel = m_assembler.label();
128         ASSERT_UNUSED(pointerLabel, ARM64Assembler::getDifferenceBetweenLabels(callLabel, pointerLabel) == REPATCH_OFFSET_CALL_TO_POINTER);
129         return Call(callLabel, Call::Linkable);
130     }
131
132     ALWAYS_INLINE Call call(PtrTag tag)
133     {
134         if (tag == NoPtrTag)
135             return MacroAssemblerARM64::call(tag);
136         if (tag == CFunctionPtrTag)
137             return callTrustedPtr<CallSignatureType::CFunctionCall>();
138         move(TrustedImm64(tag), ARM64Registers::lr);
139         return callTrustedPtr<CallSignatureType::OtherCall>(ARM64Registers::lr);
140     }
141
142     ALWAYS_INLINE Call call(RegisterID tagGPR)
143     {
144         return callTrustedPtr<CallSignatureType::OtherCall>(tagGPR);
145     }
146
147     template<CallSignatureType type>
148     ALWAYS_INLINE Call callRegister(RegisterID targetGPR, RegisterID tagGPR = InvalidGPR)
149     {
150         ASSERT(tagGPR != targetGPR);
151         invalidateAllTempRegisters();
152         if (type == CallSignatureType::CFunctionCall)
153             m_assembler.blraaz(targetGPR);
154         else
155             m_assembler.blrab(targetGPR, tagGPR);
156         return Call(m_assembler.label(), Call::None);
157     }
158
159     ALWAYS_INLINE Call call(RegisterID targetGPR, PtrTag tag)
160     {
161         if (tag == NoPtrTag)
162             return MacroAssemblerARM64::call(targetGPR, tag);
163         if (tag == CFunctionPtrTag)
164             return callRegister<CallSignatureType::CFunctionCall>(targetGPR);
165         move(TrustedImm64(tag), ARM64Registers::lr);
166         return callRegister<CallSignatureType::OtherCall>(targetGPR, ARM64Registers::lr);
167     }
168
169     ALWAYS_INLINE Call call(RegisterID targetGPR, RegisterID tagGPR)
170     {
171         return callRegister<CallSignatureType::OtherCall>(targetGPR, tagGPR);
172     }
173
174     ALWAYS_INLINE Call call(Address address, PtrTag tag)
175     {
176         if (tag == NoPtrTag)
177             return MacroAssemblerARM64::call(address, tag);
178
179         load64(address, getCachedDataTempRegisterIDAndInvalidate());
180         return call(dataTempRegister, tag);
181     }
182
183     ALWAYS_INLINE Call call(Address address, RegisterID tag)
184     {
185         ASSERT(tag != dataTempRegister);
186         load64(address, getCachedDataTempRegisterIDAndInvalidate());
187         return call(dataTempRegister, tag);
188     }
189
190     ALWAYS_INLINE Jump jump() { return MacroAssemblerARM64::jump(); }
191
192     void jump(RegisterID target, PtrTag tag)
193     {
194         if (tag == NoPtrTag)
195             return MacroAssemblerARM64::jump(target, tag);
196
197         ASSERT(tag != CFunctionPtrTag);
198         RegisterID diversityGPR = getCachedDataTempRegisterIDAndInvalidate();
199         move(TrustedImm64(tag), diversityGPR);
200         jump(target, diversityGPR);
201     }
202
203     void jump(RegisterID target, RegisterID tag)
204     {
205         ASSERT(tag != target);
206         m_assembler.brab(target, tag);
207     }
208
209     void jump(Address address, PtrTag tag)
210     {
211         if (tag == NoPtrTag)
212             return MacroAssemblerARM64::jump(address, tag);
213
214         ASSERT(tag != CFunctionPtrTag);
215         RegisterID targetGPR = getCachedDataTempRegisterIDAndInvalidate();
216         RegisterID diversityGPR = getCachedMemoryTempRegisterIDAndInvalidate();
217         load64(address, targetGPR);
218         move(TrustedImm64(tag), diversityGPR);
219         m_assembler.brab(targetGPR, diversityGPR);
220     }
221
222     void jump(Address address, RegisterID tag)
223     {
224         RegisterID targetGPR = getCachedDataTempRegisterIDAndInvalidate();
225         ASSERT(tag != targetGPR);
226         load64(address, targetGPR);
227         m_assembler.brab(targetGPR, tag);
228     }
229
230     void jump(BaseIndex address, PtrTag tag)
231     {
232         if (tag == NoPtrTag)
233             return MacroAssemblerARM64::jump(address, tag);
234
235         ASSERT(tag != CFunctionPtrTag);
236         RegisterID targetGPR = getCachedDataTempRegisterIDAndInvalidate();
237         RegisterID diversityGPR = getCachedMemoryTempRegisterIDAndInvalidate();
238         load64(address, targetGPR);
239         move(TrustedImm64(tag), diversityGPR);
240         m_assembler.brab(targetGPR, diversityGPR);
241     }
242
243     void jump(BaseIndex address, RegisterID tag)
244     {
245         RegisterID targetGPR = getCachedDataTempRegisterIDAndInvalidate();
246         ASSERT(tag != targetGPR);
247         load64(address, targetGPR);
248         m_assembler.brab(targetGPR, tag);
249     }
250
251     void jump(AbsoluteAddress address, PtrTag tag)
252     {
253         if (tag == NoPtrTag)
254             return MacroAssemblerARM64::jump(address, tag);
255
256         RegisterID targetGPR = getCachedDataTempRegisterIDAndInvalidate();
257         RegisterID diversityGPR = getCachedMemoryTempRegisterIDAndInvalidate();
258         move(TrustedImmPtr(address.m_ptr), targetGPR);
259         load64(Address(targetGPR), targetGPR);
260         move(TrustedImm64(tag), diversityGPR);
261         m_assembler.brab(targetGPR, diversityGPR);
262     }
263
264     void jump(AbsoluteAddress address, RegisterID tag)
265     {
266         RegisterID targetGPR = getCachedDataTempRegisterIDAndInvalidate();
267         ASSERT(tag != targetGPR);
268         move(TrustedImmPtr(address.m_ptr), targetGPR);
269         load64(Address(targetGPR), targetGPR);
270         m_assembler.brab(targetGPR, tag);
271     }
272 };
273
274 } // namespace JSC
275
276 #endif // ENABLE(ASSEMBLER) && CPU(ARM64E)