2 * Copyright (C) 2008, 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef MacroAssemblerX86_h
27 #define MacroAssemblerX86_h
29 #if ENABLE(ASSEMBLER) && CPU(X86)
31 #include "MacroAssemblerX86Common.h"
34 #include <wtf/StdLibExtras.h>
39 class MacroAssemblerX86
: public MacroAssemblerX86Common
{
41 static const Scale ScalePtr
= TimesFour
;
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
;
63 void add32(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
65 m_assembler
.leal_mr(imm
.m_value
, src
, dest
);
68 void add32(TrustedImm32 imm
, AbsoluteAddress address
)
70 m_assembler
.addl_im(imm
.m_value
, address
.m_ptr
);
73 void add32(AbsoluteAddress address
, RegisterID dest
)
75 m_assembler
.addl_mr(address
.m_ptr
, dest
);
78 void add64(TrustedImm32 imm
, AbsoluteAddress address
)
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));
84 void and32(TrustedImm32 imm
, AbsoluteAddress address
)
86 m_assembler
.andl_im(imm
.m_value
, address
.m_ptr
);
89 void or32(TrustedImm32 imm
, AbsoluteAddress address
)
91 m_assembler
.orl_im(imm
.m_value
, address
.m_ptr
);
94 void or32(RegisterID reg
, AbsoluteAddress address
)
96 m_assembler
.orl_rm(reg
, address
.m_ptr
);
99 void sub32(TrustedImm32 imm
, AbsoluteAddress address
)
101 m_assembler
.subl_im(imm
.m_value
, address
.m_ptr
);
104 void load32(const void* address
, RegisterID dest
)
106 m_assembler
.movl_mr(address
, dest
);
109 void load8(const void* address
, RegisterID dest
)
111 m_assembler
.movzbl_mr(address
, dest
);
114 void abortWithReason(AbortReason reason
)
116 move(TrustedImm32(reason
), X86Registers::eax
);
120 void abortWithReason(AbortReason reason
, intptr_t misc
)
122 move(TrustedImm32(misc
), X86Registers::edx
);
123 abortWithReason(reason
);
126 ConvertibleLoadLabel
convertibleLoadPtr(Address address
, RegisterID dest
)
128 ConvertibleLoadLabel result
= ConvertibleLoadLabel(this);
129 m_assembler
.movl_mr(address
.offset
, address
.base
, dest
);
133 void addDouble(AbsoluteAddress address
, FPRegisterID dest
)
135 m_assembler
.addsd_mr(address
.m_ptr
, dest
);
138 void storeDouble(FPRegisterID src
, TrustedImmPtr address
)
140 ASSERT(isSSE2Present());
141 ASSERT(address
.m_value
);
142 m_assembler
.movsd_rm(src
, address
.m_value
);
145 void convertInt32ToDouble(AbsoluteAddress src
, FPRegisterID dest
)
147 m_assembler
.cvtsi2sd_mr(src
.m_ptr
, dest
);
150 void store32(TrustedImm32 imm
, void* address
)
152 m_assembler
.movl_i32m(imm
.m_value
, address
);
155 void store32(RegisterID src
, void* address
)
157 m_assembler
.movl_rm(src
, address
);
160 void store8(RegisterID src
, void* address
)
162 m_assembler
.movb_rm(src
, address
);
165 void store8(TrustedImm32 imm
, void* address
)
167 ASSERT(-128 <= imm
.m_value
&& imm
.m_value
< 128);
168 m_assembler
.movb_i8m(imm
.m_value
, address
);
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
)
176 movePackedToInt32(src
, dest1
);
177 rshiftPacked(TrustedImm32(32), src
);
178 movePackedToInt32(src
, dest2
);
181 void moveIntsToDouble(RegisterID src1
, RegisterID src2
, FPRegisterID dest
, FPRegisterID scratch
)
183 moveInt32ToPacked(src1
, dest
);
184 moveInt32ToPacked(src2
, scratch
);
185 lshiftPacked(TrustedImm32(32), scratch
);
186 orPacked(scratch
, dest
);
189 Jump
branchAdd32(ResultCondition cond
, TrustedImm32 imm
, AbsoluteAddress dest
)
191 m_assembler
.addl_im(imm
.m_value
, dest
.m_ptr
);
192 return Jump(m_assembler
.jCC(x86Condition(cond
)));
195 Jump
branchSub32(ResultCondition cond
, TrustedImm32 imm
, AbsoluteAddress dest
)
197 m_assembler
.subl_im(imm
.m_value
, dest
.m_ptr
);
198 return Jump(m_assembler
.jCC(x86Condition(cond
)));
201 Jump
branch32(RelationalCondition cond
, AbsoluteAddress left
, RegisterID right
)
203 m_assembler
.cmpl_rm(right
, left
.m_ptr
);
204 return Jump(m_assembler
.jCC(x86Condition(cond
)));
207 Jump
branch32(RelationalCondition cond
, AbsoluteAddress left
, TrustedImm32 right
)
209 m_assembler
.cmpl_im(right
.m_value
, left
.m_ptr
);
210 return Jump(m_assembler
.jCC(x86Condition(cond
)));
215 return Call(m_assembler
.call(), Call::Linkable
);
218 // Address is a memory location containing the address to jump to
219 void jump(AbsoluteAddress address
)
221 m_assembler
.jmp_m(address
.m_ptr
);
224 Call
tailRecursiveCall()
226 return Call::fromTailJump(jump());
229 Call
makeTailRecursiveCall(Jump oldJump
)
231 return Call::fromTailJump(oldJump
);
235 DataLabelPtr
moveWithPatch(TrustedImmPtr initialValue
, RegisterID dest
)
238 m_assembler
.movl_i32r(initialValue
.asIntptr(), dest
);
239 return DataLabelPtr(this);
242 Jump
branch8(RelationalCondition cond
, AbsoluteAddress left
, TrustedImm32 right
)
244 m_assembler
.cmpb_im(right
.m_value
, left
.m_ptr
);
245 return Jump(m_assembler
.jCC(x86Condition(cond
)));
248 Jump
branchTest8(ResultCondition cond
, AbsoluteAddress address
, TrustedImm32 mask
= TrustedImm32(-1))
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
);
254 m_assembler
.testb_im(mask
.m_value
, address
.m_ptr
);
255 return Jump(m_assembler
.jCC(x86Condition(cond
)));
258 Jump
branchPtrWithPatch(RelationalCondition cond
, RegisterID left
, DataLabelPtr
& dataLabel
, TrustedImmPtr initialRightValue
= TrustedImmPtr(0))
261 m_assembler
.cmpl_ir_force32(initialRightValue
.asIntptr(), left
);
262 dataLabel
= DataLabelPtr(this);
263 return Jump(m_assembler
.jCC(x86Condition(cond
)));
266 Jump
branchPtrWithPatch(RelationalCondition cond
, Address left
, DataLabelPtr
& dataLabel
, TrustedImmPtr initialRightValue
= TrustedImmPtr(0))
269 m_assembler
.cmpl_im_force32(initialRightValue
.asIntptr(), left
.offset
, left
.base
);
270 dataLabel
= DataLabelPtr(this);
271 return Jump(m_assembler
.jCC(x86Condition(cond
)));
274 Jump
branch32WithPatch(RelationalCondition cond
, Address left
, DataLabel32
& dataLabel
, TrustedImm32 initialRightValue
= TrustedImm32(0))
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
)));
282 DataLabelPtr
storePtrWithPatch(TrustedImmPtr initialValue
, ImplicitAddress address
)
285 m_assembler
.movl_i32m(initialValue
.asIntptr(), address
.offset
, address
.base
);
286 return DataLabelPtr(this);
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(); }
295 static FunctionPtr
readCallTarget(CodeLocationCall call
)
297 intptr_t offset
= reinterpret_cast<int32_t*>(call
.dataLocation())[-1];
298 return FunctionPtr(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(call
.dataLocation()) + offset
));
301 static bool canJumpReplacePatchableBranchPtrWithPatch() { return true; }
302 static bool canJumpReplacePatchableBranch32WithPatch() { return true; }
304 static CodeLocationLabel
startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label
)
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
);
314 static CodeLocationLabel
startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr label
)
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
);
325 static CodeLocationLabel
startOfPatchableBranch32WithPatchOnAddress(CodeLocationDataLabel32 label
)
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
);
336 static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart
, RegisterID reg
, void* initialValue
)
338 X86Assembler::revertJumpTo_cmpl_ir_force32(instructionStart
.executableAddress(), reinterpret_cast<intptr_t>(initialValue
), reg
);
341 static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart
, Address address
, void* initialValue
)
343 ASSERT(!address
.offset
);
344 X86Assembler::revertJumpTo_cmpl_im_force32(instructionStart
.executableAddress(), reinterpret_cast<intptr_t>(initialValue
), 0, address
.base
);
347 static void revertJumpReplacementToPatchableBranch32WithPatch(CodeLocationLabel instructionStart
, Address address
, int32_t initialValue
)
349 ASSERT(!address
.offset
);
350 X86Assembler::revertJumpTo_cmpl_im_force32(instructionStart
.executableAddress(), initialValue
, 0, address
.base
);
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)
359 friend class LinkBuffer
;
360 friend class RepatchBuffer
;
362 static void linkCall(void* code
, Call call
, FunctionPtr function
)
364 X86Assembler::linkCall(code
, call
.m_label
, function
.value());
367 static void repatchCall(CodeLocationCall call
, CodeLocationLabel destination
)
369 X86Assembler::relinkCall(call
.dataLocation(), destination
.executableAddress());
372 static void repatchCall(CodeLocationCall call
, FunctionPtr destination
)
374 X86Assembler::relinkCall(call
.dataLocation(), destination
.executableAddress());
378 inline TrustedImm32
trustedImm32FromPtr(void* ptr
)
380 return TrustedImm32(TrustedImmPtr(ptr
));
383 inline TrustedImm32
trustedImm32FromPtr(ProbeFunction function
)
385 return TrustedImm32(TrustedImmPtr(reinterpret_cast<void*>(function
)));
388 inline TrustedImm32
trustedImm32FromPtr(void (*function
)())
390 return TrustedImm32(TrustedImmPtr(reinterpret_cast<void*>(function
)));
397 extern "C" void ctiMasmProbeTrampoline();
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.
403 inline void MacroAssemblerX86::probe(MacroAssemblerX86::ProbeFunction function
, void* arg1
, void* arg2
)
405 push(RegisterID::esp
);
406 push(RegisterID::eax
);
407 push(trustedImm32FromPtr(arg2
));
408 push(trustedImm32FromPtr(arg1
));
409 push(trustedImm32FromPtr(function
));
411 move(trustedImm32FromPtr(ctiMasmProbeTrampoline
), RegisterID::eax
);
412 call(RegisterID::eax
);
414 #endif // USE(MASM_PROBE)
418 #endif // ENABLE(ASSEMBLER)
420 #endif // MacroAssemblerX86_h