]> git.saurik.com Git - apple/javascriptcore.git/blame - assembler/MacroAssemblerX86.h
JavaScriptCore-7600.1.4.15.12.tar.gz
[apple/javascriptcore.git] / assembler / MacroAssemblerX86.h
CommitLineData
ba379fdc 1/*
81345200 2 * Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
ba379fdc
A
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#ifndef MacroAssemblerX86_h
27#define MacroAssemblerX86_h
28
f9bf01c6 29#if ENABLE(ASSEMBLER) && CPU(X86)
ba379fdc
A
30
31#include "MacroAssemblerX86Common.h"
32
81345200
A
33#if USE(MASM_PROBE)
34#include <wtf/StdLibExtras.h>
35#endif
36
ba379fdc
A
37namespace JSC {
38
39class MacroAssemblerX86 : public MacroAssemblerX86Common {
40public:
ba379fdc
A
41 static const Scale ScalePtr = TimesFour;
42
43 using MacroAssemblerX86Common::add32;
44 using MacroAssemblerX86Common::and32;
6fe7ccc8
A
45 using MacroAssemblerX86Common::branchAdd32;
46 using MacroAssemblerX86Common::branchSub32;
ba379fdc
A
47 using MacroAssemblerX86Common::sub32;
48 using MacroAssemblerX86Common::or32;
49 using MacroAssemblerX86Common::load32;
81345200 50 using MacroAssemblerX86Common::load8;
ba379fdc 51 using MacroAssemblerX86Common::store32;
93a37866 52 using MacroAssemblerX86Common::store8;
ba379fdc
A
53 using MacroAssemblerX86Common::branch32;
54 using MacroAssemblerX86Common::call;
6fe7ccc8
A
55 using MacroAssemblerX86Common::jump;
56 using MacroAssemblerX86Common::addDouble;
ba379fdc 57 using MacroAssemblerX86Common::loadDouble;
6fe7ccc8 58 using MacroAssemblerX86Common::storeDouble;
ba379fdc 59 using MacroAssemblerX86Common::convertInt32ToDouble;
81345200 60 using MacroAssemblerX86Common::branch8;
93a37866 61 using MacroAssemblerX86Common::branchTest8;
ba379fdc 62
14957cd0 63 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
ba379fdc
A
64 {
65 m_assembler.leal_mr(imm.m_value, src, dest);
66 }
67
14957cd0 68 void add32(TrustedImm32 imm, AbsoluteAddress address)
ba379fdc
A
69 {
70 m_assembler.addl_im(imm.m_value, address.m_ptr);
71 }
72
93a37866
A
73 void add32(AbsoluteAddress address, RegisterID dest)
74 {
75 m_assembler.addl_mr(address.m_ptr, dest);
76 }
77
6fe7ccc8 78 void add64(TrustedImm32 imm, AbsoluteAddress address)
ba379fdc 79 {
6fe7ccc8
A
80 m_assembler.addl_im(imm.m_value, address.m_ptr);
81 m_assembler.adcl_im(imm.m_value >> 31, reinterpret_cast<const char*>(address.m_ptr) + sizeof(int32_t));
ba379fdc 82 }
6fe7ccc8 83
14957cd0 84 void and32(TrustedImm32 imm, AbsoluteAddress address)
ba379fdc
A
85 {
86 m_assembler.andl_im(imm.m_value, address.m_ptr);
87 }
88
14957cd0 89 void or32(TrustedImm32 imm, AbsoluteAddress address)
ba379fdc
A
90 {
91 m_assembler.orl_im(imm.m_value, address.m_ptr);
92 }
93a37866
A
93
94 void or32(RegisterID reg, AbsoluteAddress address)
95 {
96 m_assembler.orl_rm(reg, address.m_ptr);
97 }
98
14957cd0 99 void sub32(TrustedImm32 imm, AbsoluteAddress address)
ba379fdc
A
100 {
101 m_assembler.subl_im(imm.m_value, address.m_ptr);
102 }
103
6fe7ccc8 104 void load32(const void* address, RegisterID dest)
ba379fdc
A
105 {
106 m_assembler.movl_mr(address, dest);
107 }
81345200
A
108
109 void load8(const void* address, RegisterID dest)
110 {
111 m_assembler.movzbl_mr(address, dest);
112 }
113
114 void abortWithReason(AbortReason reason)
115 {
116 move(TrustedImm32(reason), X86Registers::eax);
117 breakpoint();
118 }
119
120 void abortWithReason(AbortReason reason, intptr_t misc)
121 {
122 move(TrustedImm32(misc), X86Registers::edx);
123 abortWithReason(reason);
124 }
ba379fdc 125
93a37866
A
126 ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
127 {
128 ConvertibleLoadLabel result = ConvertibleLoadLabel(this);
129 m_assembler.movl_mr(address.offset, address.base, dest);
130 return result;
131 }
132
6fe7ccc8
A
133 void addDouble(AbsoluteAddress address, FPRegisterID dest)
134 {
135 m_assembler.addsd_mr(address.m_ptr, dest);
136 }
137
81345200 138 void storeDouble(FPRegisterID src, TrustedImmPtr address)
ba379fdc
A
139 {
140 ASSERT(isSSE2Present());
81345200
A
141 ASSERT(address.m_value);
142 m_assembler.movsd_rm(src, address.m_value);
ba379fdc
A
143 }
144
145 void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
146 {
147 m_assembler.cvtsi2sd_mr(src.m_ptr, dest);
148 }
149
14957cd0 150 void store32(TrustedImm32 imm, void* address)
ba379fdc
A
151 {
152 m_assembler.movl_i32m(imm.m_value, address);
153 }
154
155 void store32(RegisterID src, void* address)
156 {
157 m_assembler.movl_rm(src, address);
158 }
81345200
A
159
160 void store8(RegisterID src, void* address)
161 {
162 m_assembler.movb_rm(src, address);
163 }
ba379fdc 164
93a37866
A
165 void store8(TrustedImm32 imm, void* address)
166 {
167 ASSERT(-128 <= imm.m_value && imm.m_value < 128);
168 m_assembler.movb_i8m(imm.m_value, address);
169 }
170
171 // Possibly clobbers src.
81345200
A
172 // FIXME: Don't do that.
173 // https://bugs.webkit.org/show_bug.cgi?id=131690
93a37866
A
174 void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2)
175 {
176 movePackedToInt32(src, dest1);
177 rshiftPacked(TrustedImm32(32), src);
178 movePackedToInt32(src, dest2);
179 }
180
181 void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID scratch)
182 {
183 moveInt32ToPacked(src1, dest);
184 moveInt32ToPacked(src2, scratch);
185 lshiftPacked(TrustedImm32(32), scratch);
186 orPacked(scratch, dest);
187 }
188
6fe7ccc8
A
189 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
190 {
191 m_assembler.addl_im(imm.m_value, dest.m_ptr);
192 return Jump(m_assembler.jCC(x86Condition(cond)));
193 }
194
195 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
196 {
197 m_assembler.subl_im(imm.m_value, dest.m_ptr);
198 return Jump(m_assembler.jCC(x86Condition(cond)));
199 }
200
14957cd0 201 Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
ba379fdc
A
202 {
203 m_assembler.cmpl_rm(right, left.m_ptr);
204 return Jump(m_assembler.jCC(x86Condition(cond)));
205 }
206
14957cd0 207 Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
ba379fdc
A
208 {
209 m_assembler.cmpl_im(right.m_value, left.m_ptr);
210 return Jump(m_assembler.jCC(x86Condition(cond)));
211 }
212
213 Call call()
214 {
215 return Call(m_assembler.call(), Call::Linkable);
216 }
217
6fe7ccc8
A
218 // Address is a memory location containing the address to jump to
219 void jump(AbsoluteAddress address)
220 {
221 m_assembler.jmp_m(address.m_ptr);
222 }
223
ba379fdc
A
224 Call tailRecursiveCall()
225 {
226 return Call::fromTailJump(jump());
227 }
228
229 Call makeTailRecursiveCall(Jump oldJump)
230 {
231 return Call::fromTailJump(oldJump);
232 }
233
234
14957cd0 235 DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
ba379fdc 236 {
93a37866 237 padBeforePatch();
ba379fdc
A
238 m_assembler.movl_i32r(initialValue.asIntptr(), dest);
239 return DataLabelPtr(this);
240 }
93a37866 241
81345200
A
242 Jump branch8(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
243 {
244 m_assembler.cmpb_im(right.m_value, left.m_ptr);
245 return Jump(m_assembler.jCC(x86Condition(cond)));
246 }
247
93a37866
A
248 Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
249 {
250 ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
251 if (mask.m_value == -1)
252 m_assembler.cmpb_im(0, address.m_ptr);
253 else
254 m_assembler.testb_im(mask.m_value, address.m_ptr);
255 return Jump(m_assembler.jCC(x86Condition(cond)));
256 }
ba379fdc 257
14957cd0 258 Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
ba379fdc 259 {
93a37866 260 padBeforePatch();
ba379fdc
A
261 m_assembler.cmpl_ir_force32(initialRightValue.asIntptr(), left);
262 dataLabel = DataLabelPtr(this);
263 return Jump(m_assembler.jCC(x86Condition(cond)));
264 }
265
14957cd0 266 Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
ba379fdc 267 {
93a37866 268 padBeforePatch();
ba379fdc
A
269 m_assembler.cmpl_im_force32(initialRightValue.asIntptr(), left.offset, left.base);
270 dataLabel = DataLabelPtr(this);
271 return Jump(m_assembler.jCC(x86Condition(cond)));
272 }
273
81345200
A
274 Jump branch32WithPatch(RelationalCondition cond, Address left, DataLabel32& dataLabel, TrustedImm32 initialRightValue = TrustedImm32(0))
275 {
276 padBeforePatch();
277 m_assembler.cmpl_im_force32(initialRightValue.m_value, left.offset, left.base);
278 dataLabel = DataLabel32(this);
279 return Jump(m_assembler.jCC(x86Condition(cond)));
280 }
281
14957cd0 282 DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
ba379fdc 283 {
93a37866 284 padBeforePatch();
ba379fdc
A
285 m_assembler.movl_i32m(initialValue.asIntptr(), address.offset, address.base);
286 return DataLabelPtr(this);
287 }
288
6fe7ccc8 289 static bool supportsFloatingPoint() { return isSSE2Present(); }
ba379fdc 290 // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
6fe7ccc8
A
291 static bool supportsFloatingPointTruncate() { return isSSE2Present(); }
292 static bool supportsFloatingPointSqrt() { return isSSE2Present(); }
293 static bool supportsFloatingPointAbs() { return isSSE2Present(); }
294
295 static FunctionPtr readCallTarget(CodeLocationCall call)
296 {
297 intptr_t offset = reinterpret_cast<int32_t*>(call.dataLocation())[-1];
298 return FunctionPtr(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(call.dataLocation()) + offset));
299 }
ba379fdc 300
93a37866 301 static bool canJumpReplacePatchableBranchPtrWithPatch() { return true; }
81345200 302 static bool canJumpReplacePatchableBranch32WithPatch() { return true; }
93a37866
A
303
304 static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label)
305 {
306 const int opcodeBytes = 1;
307 const int modRMBytes = 1;
308 const int immediateBytes = 4;
309 const int totalBytes = opcodeBytes + modRMBytes + immediateBytes;
310 ASSERT(totalBytes >= maxJumpReplacementSize());
311 return label.labelAtOffset(-totalBytes);
312 }
313
314 static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr label)
315 {
316 const int opcodeBytes = 1;
317 const int modRMBytes = 1;
318 const int offsetBytes = 0;
319 const int immediateBytes = 4;
320 const int totalBytes = opcodeBytes + modRMBytes + offsetBytes + immediateBytes;
321 ASSERT(totalBytes >= maxJumpReplacementSize());
322 return label.labelAtOffset(-totalBytes);
323 }
324
81345200
A
325 static CodeLocationLabel startOfPatchableBranch32WithPatchOnAddress(CodeLocationDataLabel32 label)
326 {
327 const int opcodeBytes = 1;
328 const int modRMBytes = 1;
329 const int offsetBytes = 0;
330 const int immediateBytes = 4;
331 const int totalBytes = opcodeBytes + modRMBytes + offsetBytes + immediateBytes;
332 ASSERT(totalBytes >= maxJumpReplacementSize());
333 return label.labelAtOffset(-totalBytes);
334 }
335
93a37866
A
336 static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID reg, void* initialValue)
337 {
338 X86Assembler::revertJumpTo_cmpl_ir_force32(instructionStart.executableAddress(), reinterpret_cast<intptr_t>(initialValue), reg);
339 }
340
341 static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, Address address, void* initialValue)
342 {
343 ASSERT(!address.offset);
344 X86Assembler::revertJumpTo_cmpl_im_force32(instructionStart.executableAddress(), reinterpret_cast<intptr_t>(initialValue), 0, address.base);
345 }
346
81345200
A
347 static void revertJumpReplacementToPatchableBranch32WithPatch(CodeLocationLabel instructionStart, Address address, int32_t initialValue)
348 {
349 ASSERT(!address.offset);
350 X86Assembler::revertJumpTo_cmpl_im_force32(instructionStart.executableAddress(), initialValue, 0, address.base);
351 }
352
353#if USE(MASM_PROBE)
354 // For details about probe(), see comment in MacroAssemblerX86_64.h.
355 void probe(ProbeFunction, void* arg1 = 0, void* arg2 = 0);
356#endif // USE(MASM_PROBE)
357
ba379fdc 358private:
ba379fdc
A
359 friend class LinkBuffer;
360 friend class RepatchBuffer;
361
362 static void linkCall(void* code, Call call, FunctionPtr function)
363 {
6fe7ccc8 364 X86Assembler::linkCall(code, call.m_label, function.value());
ba379fdc
A
365 }
366
367 static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
368 {
369 X86Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
370 }
371
372 static void repatchCall(CodeLocationCall call, FunctionPtr destination)
373 {
374 X86Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
375 }
81345200
A
376
377#if USE(MASM_PROBE)
378 inline TrustedImm32 trustedImm32FromPtr(void* ptr)
379 {
380 return TrustedImm32(TrustedImmPtr(ptr));
381 }
382
383 inline TrustedImm32 trustedImm32FromPtr(ProbeFunction function)
384 {
385 return TrustedImm32(TrustedImmPtr(reinterpret_cast<void*>(function)));
386 }
387
388 inline TrustedImm32 trustedImm32FromPtr(void (*function)())
389 {
390 return TrustedImm32(TrustedImmPtr(reinterpret_cast<void*>(function)));
391 }
392#endif
ba379fdc
A
393};
394
81345200
A
395#if USE(MASM_PROBE)
396
397extern "C" void ctiMasmProbeTrampoline();
398
399// For details on "What code is emitted for the probe?" and "What values are in
400// the saved registers?", see comment for MacroAssemblerX86::probe() in
401// MacroAssemblerX86_64.h.
402
403inline void MacroAssemblerX86::probe(MacroAssemblerX86::ProbeFunction function, void* arg1, void* arg2)
404{
405 push(RegisterID::esp);
406 push(RegisterID::eax);
407 push(trustedImm32FromPtr(arg2));
408 push(trustedImm32FromPtr(arg1));
409 push(trustedImm32FromPtr(function));
410
411 move(trustedImm32FromPtr(ctiMasmProbeTrampoline), RegisterID::eax);
412 call(RegisterID::eax);
413}
414#endif // USE(MASM_PROBE)
415
ba379fdc
A
416} // namespace JSC
417
418#endif // ENABLE(ASSEMBLER)
419
420#endif // MacroAssemblerX86_h