]> git.saurik.com Git - apple/javascriptcore.git/blob - assembler/MacroAssemblerX86.h
56416856f2c4b480c6ecc048696bc7d5111f9516
[apple/javascriptcore.git] / assembler / MacroAssemblerX86.h
1 /*
2 * Copyright (C) 2008, 2014 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 #ifndef MacroAssemblerX86_h
27 #define MacroAssemblerX86_h
28
29 #if ENABLE(ASSEMBLER) && CPU(X86)
30
31 #include "MacroAssemblerX86Common.h"
32
33 #if USE(MASM_PROBE)
34 #include <wtf/StdLibExtras.h>
35 #endif
36
37 namespace JSC {
38
39 class MacroAssemblerX86 : public MacroAssemblerX86Common {
40 public:
41 static const Scale ScalePtr = TimesFour;
42
43 using MacroAssemblerX86Common::add32;
44 using MacroAssemblerX86Common::and32;
45 using MacroAssemblerX86Common::branchAdd32;
46 using MacroAssemblerX86Common::branchSub32;
47 using MacroAssemblerX86Common::sub32;
48 using MacroAssemblerX86Common::or32;
49 using MacroAssemblerX86Common::load32;
50 using MacroAssemblerX86Common::load8;
51 using MacroAssemblerX86Common::store32;
52 using MacroAssemblerX86Common::store8;
53 using MacroAssemblerX86Common::branch32;
54 using MacroAssemblerX86Common::call;
55 using MacroAssemblerX86Common::jump;
56 using MacroAssemblerX86Common::addDouble;
57 using MacroAssemblerX86Common::loadDouble;
58 using MacroAssemblerX86Common::storeDouble;
59 using MacroAssemblerX86Common::convertInt32ToDouble;
60 using MacroAssemblerX86Common::branch8;
61 using MacroAssemblerX86Common::branchTest8;
62
63 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
64 {
65 m_assembler.leal_mr(imm.m_value, src, dest);
66 }
67
68 void add32(TrustedImm32 imm, AbsoluteAddress address)
69 {
70 m_assembler.addl_im(imm.m_value, address.m_ptr);
71 }
72
73 void add32(AbsoluteAddress address, RegisterID dest)
74 {
75 m_assembler.addl_mr(address.m_ptr, dest);
76 }
77
78 void add64(TrustedImm32 imm, AbsoluteAddress address)
79 {
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));
82 }
83
84 void and32(TrustedImm32 imm, AbsoluteAddress address)
85 {
86 m_assembler.andl_im(imm.m_value, address.m_ptr);
87 }
88
89 void or32(TrustedImm32 imm, AbsoluteAddress address)
90 {
91 m_assembler.orl_im(imm.m_value, address.m_ptr);
92 }
93
94 void or32(RegisterID reg, AbsoluteAddress address)
95 {
96 m_assembler.orl_rm(reg, address.m_ptr);
97 }
98
99 void sub32(TrustedImm32 imm, AbsoluteAddress address)
100 {
101 m_assembler.subl_im(imm.m_value, address.m_ptr);
102 }
103
104 void load32(const void* address, RegisterID dest)
105 {
106 m_assembler.movl_mr(address, dest);
107 }
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 }
125
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
133 void addDouble(AbsoluteAddress address, FPRegisterID dest)
134 {
135 m_assembler.addsd_mr(address.m_ptr, dest);
136 }
137
138 void storeDouble(FPRegisterID src, TrustedImmPtr address)
139 {
140 ASSERT(isSSE2Present());
141 ASSERT(address.m_value);
142 m_assembler.movsd_rm(src, address.m_value);
143 }
144
145 void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
146 {
147 m_assembler.cvtsi2sd_mr(src.m_ptr, dest);
148 }
149
150 void store32(TrustedImm32 imm, void* address)
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 }
159
160 void store8(RegisterID src, void* address)
161 {
162 m_assembler.movb_rm(src, address);
163 }
164
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.
172 // FIXME: Don't do that.
173 // https://bugs.webkit.org/show_bug.cgi?id=131690
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
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
201 Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
202 {
203 m_assembler.cmpl_rm(right, left.m_ptr);
204 return Jump(m_assembler.jCC(x86Condition(cond)));
205 }
206
207 Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
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
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
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
235 DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
236 {
237 padBeforePatch();
238 m_assembler.movl_i32r(initialValue.asIntptr(), dest);
239 return DataLabelPtr(this);
240 }
241
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
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 }
257
258 Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
259 {
260 padBeforePatch();
261 m_assembler.cmpl_ir_force32(initialRightValue.asIntptr(), left);
262 dataLabel = DataLabelPtr(this);
263 return Jump(m_assembler.jCC(x86Condition(cond)));
264 }
265
266 Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
267 {
268 padBeforePatch();
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
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
282 DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
283 {
284 padBeforePatch();
285 m_assembler.movl_i32m(initialValue.asIntptr(), address.offset, address.base);
286 return DataLabelPtr(this);
287 }
288
289 static bool supportsFloatingPoint() { return isSSE2Present(); }
290 // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
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 }
300
301 static bool canJumpReplacePatchableBranchPtrWithPatch() { return true; }
302 static bool canJumpReplacePatchableBranch32WithPatch() { return true; }
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
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
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
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
358 private:
359 friend class LinkBuffer;
360 friend class RepatchBuffer;
361
362 static void linkCall(void* code, Call call, FunctionPtr function)
363 {
364 X86Assembler::linkCall(code, call.m_label, function.value());
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 }
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
393 };
394
395 #if USE(MASM_PROBE)
396
397 extern "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
403 inline 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
416 } // namespace JSC
417
418 #endif // ENABLE(ASSEMBLER)
419
420 #endif // MacroAssemblerX86_h