2 * Copyright (C) 2008 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_64_h
27 #define MacroAssemblerX86_64_h
29 #if ENABLE(ASSEMBLER) && CPU(X86_64)
31 #include "MacroAssemblerX86Common.h"
33 #define REPTACH_OFFSET_CALL_R11 3
37 class MacroAssemblerX86_64
: public MacroAssemblerX86Common
{
39 static const X86Registers::RegisterID scratchRegister
= X86Registers::r11
;
42 static const Scale ScalePtr
= TimesEight
;
44 using MacroAssemblerX86Common::add32
;
45 using MacroAssemblerX86Common::and32
;
46 using MacroAssemblerX86Common::or32
;
47 using MacroAssemblerX86Common::sub32
;
48 using MacroAssemblerX86Common::load32
;
49 using MacroAssemblerX86Common::store32
;
50 using MacroAssemblerX86Common::call
;
51 using MacroAssemblerX86Common::addDouble
;
52 using MacroAssemblerX86Common::loadDouble
;
53 using MacroAssemblerX86Common::convertInt32ToDouble
;
55 void add32(TrustedImm32 imm
, AbsoluteAddress address
)
57 move(TrustedImmPtr(address
.m_ptr
), scratchRegister
);
58 add32(imm
, Address(scratchRegister
));
61 void and32(TrustedImm32 imm
, AbsoluteAddress address
)
63 move(TrustedImmPtr(address
.m_ptr
), scratchRegister
);
64 and32(imm
, Address(scratchRegister
));
67 void or32(TrustedImm32 imm
, AbsoluteAddress address
)
69 move(TrustedImmPtr(address
.m_ptr
), scratchRegister
);
70 or32(imm
, Address(scratchRegister
));
73 void sub32(TrustedImm32 imm
, AbsoluteAddress address
)
75 move(TrustedImmPtr(address
.m_ptr
), scratchRegister
);
76 sub32(imm
, Address(scratchRegister
));
79 void load32(void* address
, RegisterID dest
)
81 if (dest
== X86Registers::eax
)
82 m_assembler
.movl_mEAX(address
);
84 move(X86Registers::eax
, dest
);
85 m_assembler
.movl_mEAX(address
);
86 swap(X86Registers::eax
, dest
);
90 void loadDouble(const void* address
, FPRegisterID dest
)
92 move(TrustedImmPtr(address
), scratchRegister
);
93 loadDouble(scratchRegister
, dest
);
96 void addDouble(AbsoluteAddress address
, FPRegisterID dest
)
98 move(TrustedImmPtr(address
.m_ptr
), scratchRegister
);
99 m_assembler
.addsd_mr(0, scratchRegister
, dest
);
102 void convertInt32ToDouble(TrustedImm32 imm
, FPRegisterID dest
)
104 move(imm
, scratchRegister
);
105 m_assembler
.cvtsi2sd_rr(scratchRegister
, dest
);
108 void store32(TrustedImm32 imm
, void* address
)
110 move(X86Registers::eax
, scratchRegister
);
111 move(imm
, X86Registers::eax
);
112 m_assembler
.movl_EAXm(address
);
113 move(scratchRegister
, X86Registers::eax
);
118 DataLabelPtr label
= moveWithPatch(TrustedImmPtr(0), scratchRegister
);
119 Call result
= Call(m_assembler
.call(scratchRegister
), Call::Linkable
);
120 ASSERT_UNUSED(label
, differenceBetween(label
, result
) == REPTACH_OFFSET_CALL_R11
);
124 Call
tailRecursiveCall()
126 DataLabelPtr label
= moveWithPatch(TrustedImmPtr(0), scratchRegister
);
127 Jump newJump
= Jump(m_assembler
.jmp_r(scratchRegister
));
128 ASSERT_UNUSED(label
, differenceBetween(label
, newJump
) == REPTACH_OFFSET_CALL_R11
);
129 return Call::fromTailJump(newJump
);
132 Call
makeTailRecursiveCall(Jump oldJump
)
135 DataLabelPtr label
= moveWithPatch(TrustedImmPtr(0), scratchRegister
);
136 Jump newJump
= Jump(m_assembler
.jmp_r(scratchRegister
));
137 ASSERT_UNUSED(label
, differenceBetween(label
, newJump
) == REPTACH_OFFSET_CALL_R11
);
138 return Call::fromTailJump(newJump
);
142 void addPtr(RegisterID src
, RegisterID dest
)
144 m_assembler
.addq_rr(src
, dest
);
147 void addPtr(TrustedImm32 imm
, RegisterID srcDest
)
149 m_assembler
.addq_ir(imm
.m_value
, srcDest
);
152 void addPtr(TrustedImmPtr imm
, RegisterID dest
)
154 move(imm
, scratchRegister
);
155 m_assembler
.addq_rr(scratchRegister
, dest
);
158 void addPtr(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
160 m_assembler
.leaq_mr(imm
.m_value
, src
, dest
);
163 void addPtr(TrustedImm32 imm
, Address address
)
165 m_assembler
.addq_im(imm
.m_value
, address
.offset
, address
.base
);
168 void addPtr(TrustedImm32 imm
, AbsoluteAddress address
)
170 move(TrustedImmPtr(address
.m_ptr
), scratchRegister
);
171 addPtr(imm
, Address(scratchRegister
));
174 void andPtr(RegisterID src
, RegisterID dest
)
176 m_assembler
.andq_rr(src
, dest
);
179 void andPtr(TrustedImm32 imm
, RegisterID srcDest
)
181 m_assembler
.andq_ir(imm
.m_value
, srcDest
);
184 void orPtr(RegisterID src
, RegisterID dest
)
186 m_assembler
.orq_rr(src
, dest
);
189 void orPtr(TrustedImmPtr imm
, RegisterID dest
)
191 move(imm
, scratchRegister
);
192 m_assembler
.orq_rr(scratchRegister
, dest
);
195 void orPtr(TrustedImm32 imm
, RegisterID dest
)
197 m_assembler
.orq_ir(imm
.m_value
, dest
);
200 void orPtr(RegisterID op1
, RegisterID op2
, RegisterID dest
)
204 else if (op1
== dest
)
212 void orPtr(TrustedImm32 imm
, RegisterID src
, RegisterID dest
)
218 void subPtr(RegisterID src
, RegisterID dest
)
220 m_assembler
.subq_rr(src
, dest
);
223 void subPtr(TrustedImm32 imm
, RegisterID dest
)
225 m_assembler
.subq_ir(imm
.m_value
, dest
);
228 void subPtr(TrustedImmPtr imm
, RegisterID dest
)
230 move(imm
, scratchRegister
);
231 m_assembler
.subq_rr(scratchRegister
, dest
);
234 void xorPtr(RegisterID src
, RegisterID dest
)
236 m_assembler
.xorq_rr(src
, dest
);
239 void xorPtr(TrustedImm32 imm
, RegisterID srcDest
)
241 m_assembler
.xorq_ir(imm
.m_value
, srcDest
);
245 void loadPtr(ImplicitAddress address
, RegisterID dest
)
247 m_assembler
.movq_mr(address
.offset
, address
.base
, dest
);
250 void loadPtr(BaseIndex address
, RegisterID dest
)
252 m_assembler
.movq_mr(address
.offset
, address
.base
, address
.index
, address
.scale
, dest
);
255 void loadPtr(const void* address
, RegisterID dest
)
257 if (dest
== X86Registers::eax
)
258 m_assembler
.movq_mEAX(address
);
260 move(X86Registers::eax
, dest
);
261 m_assembler
.movq_mEAX(address
);
262 swap(X86Registers::eax
, dest
);
266 DataLabel32
loadPtrWithAddressOffsetPatch(Address address
, RegisterID dest
)
268 m_assembler
.movq_mr_disp32(address
.offset
, address
.base
, dest
);
269 return DataLabel32(this);
272 DataLabelCompact
loadPtrWithCompactAddressOffsetPatch(Address address
, RegisterID dest
)
274 m_assembler
.movq_mr_disp8(address
.offset
, address
.base
, dest
);
275 return DataLabelCompact(this);
278 void storePtr(RegisterID src
, ImplicitAddress address
)
280 m_assembler
.movq_rm(src
, address
.offset
, address
.base
);
283 void storePtr(RegisterID src
, BaseIndex address
)
285 m_assembler
.movq_rm(src
, address
.offset
, address
.base
, address
.index
, address
.scale
);
288 void storePtr(RegisterID src
, void* address
)
290 if (src
== X86Registers::eax
)
291 m_assembler
.movq_EAXm(address
);
293 swap(X86Registers::eax
, src
);
294 m_assembler
.movq_EAXm(address
);
295 swap(X86Registers::eax
, src
);
299 void storePtr(TrustedImmPtr imm
, ImplicitAddress address
)
301 move(imm
, scratchRegister
);
302 storePtr(scratchRegister
, address
);
305 DataLabel32
storePtrWithAddressOffsetPatch(RegisterID src
, Address address
)
307 m_assembler
.movq_rm_disp32(src
, address
.offset
, address
.base
);
308 return DataLabel32(this);
311 void movePtrToDouble(RegisterID src
, FPRegisterID dest
)
313 m_assembler
.movq_rr(src
, dest
);
316 void moveDoubleToPtr(FPRegisterID src
, RegisterID dest
)
318 m_assembler
.movq_rr(src
, dest
);
321 void comparePtr(RelationalCondition cond
, RegisterID left
, TrustedImm32 right
, RegisterID dest
)
323 if (((cond
== Equal
) || (cond
== NotEqual
)) && !right
.m_value
)
324 m_assembler
.testq_rr(left
, left
);
326 m_assembler
.cmpq_ir(right
.m_value
, left
);
327 m_assembler
.setCC_r(x86Condition(cond
), dest
);
328 m_assembler
.movzbl_rr(dest
, dest
);
331 Jump
branchPtr(RelationalCondition cond
, RegisterID left
, RegisterID right
)
333 m_assembler
.cmpq_rr(right
, left
);
334 return Jump(m_assembler
.jCC(x86Condition(cond
)));
337 Jump
branchPtr(RelationalCondition cond
, RegisterID left
, TrustedImmPtr right
)
339 move(right
, scratchRegister
);
340 return branchPtr(cond
, left
, scratchRegister
);
343 Jump
branchPtr(RelationalCondition cond
, RegisterID left
, Address right
)
345 m_assembler
.cmpq_mr(right
.offset
, right
.base
, left
);
346 return Jump(m_assembler
.jCC(x86Condition(cond
)));
349 Jump
branchPtr(RelationalCondition cond
, AbsoluteAddress left
, RegisterID right
)
351 move(TrustedImmPtr(left
.m_ptr
), scratchRegister
);
352 return branchPtr(cond
, Address(scratchRegister
), right
);
355 Jump
branchPtr(RelationalCondition cond
, Address left
, RegisterID right
)
357 m_assembler
.cmpq_rm(right
, left
.offset
, left
.base
);
358 return Jump(m_assembler
.jCC(x86Condition(cond
)));
361 Jump
branchPtr(RelationalCondition cond
, Address left
, TrustedImmPtr right
)
363 move(right
, scratchRegister
);
364 return branchPtr(cond
, left
, scratchRegister
);
367 Jump
branchTestPtr(ResultCondition cond
, RegisterID reg
, RegisterID mask
)
369 m_assembler
.testq_rr(reg
, mask
);
370 return Jump(m_assembler
.jCC(x86Condition(cond
)));
373 Jump
branchTestPtr(ResultCondition cond
, RegisterID reg
, TrustedImm32 mask
= TrustedImm32(-1))
375 // if we are only interested in the low seven bits, this can be tested with a testb
376 if (mask
.m_value
== -1)
377 m_assembler
.testq_rr(reg
, reg
);
378 else if ((mask
.m_value
& ~0x7f) == 0)
379 m_assembler
.testb_i8r(mask
.m_value
, reg
);
381 m_assembler
.testq_i32r(mask
.m_value
, reg
);
382 return Jump(m_assembler
.jCC(x86Condition(cond
)));
385 Jump
branchTestPtr(ResultCondition cond
, AbsoluteAddress address
, TrustedImm32 mask
= TrustedImm32(-1))
387 loadPtr(address
.m_ptr
, scratchRegister
);
388 return branchTestPtr(cond
, scratchRegister
, mask
);
391 Jump
branchTestPtr(ResultCondition cond
, Address address
, TrustedImm32 mask
= TrustedImm32(-1))
393 if (mask
.m_value
== -1)
394 m_assembler
.cmpq_im(0, address
.offset
, address
.base
);
396 m_assembler
.testq_i32m(mask
.m_value
, address
.offset
, address
.base
);
397 return Jump(m_assembler
.jCC(x86Condition(cond
)));
400 Jump
branchTestPtr(ResultCondition cond
, BaseIndex address
, TrustedImm32 mask
= TrustedImm32(-1))
402 if (mask
.m_value
== -1)
403 m_assembler
.cmpq_im(0, address
.offset
, address
.base
, address
.index
, address
.scale
);
405 m_assembler
.testq_i32m(mask
.m_value
, address
.offset
, address
.base
, address
.index
, address
.scale
);
406 return Jump(m_assembler
.jCC(x86Condition(cond
)));
410 Jump
branchAddPtr(ResultCondition cond
, RegisterID src
, RegisterID dest
)
413 return Jump(m_assembler
.jCC(x86Condition(cond
)));
416 Jump
branchSubPtr(ResultCondition cond
, TrustedImm32 imm
, RegisterID dest
)
419 return Jump(m_assembler
.jCC(x86Condition(cond
)));
422 DataLabelPtr
moveWithPatch(TrustedImmPtr initialValue
, RegisterID dest
)
424 m_assembler
.movq_i64r(initialValue
.asIntptr(), dest
);
425 return DataLabelPtr(this);
428 Jump
branchPtrWithPatch(RelationalCondition cond
, RegisterID left
, DataLabelPtr
& dataLabel
, TrustedImmPtr initialRightValue
= TrustedImmPtr(0))
430 dataLabel
= moveWithPatch(initialRightValue
, scratchRegister
);
431 return branchPtr(cond
, left
, scratchRegister
);
434 Jump
branchPtrWithPatch(RelationalCondition cond
, Address left
, DataLabelPtr
& dataLabel
, TrustedImmPtr initialRightValue
= TrustedImmPtr(0))
436 dataLabel
= moveWithPatch(initialRightValue
, scratchRegister
);
437 return branchPtr(cond
, left
, scratchRegister
);
440 DataLabelPtr
storePtrWithPatch(TrustedImmPtr initialValue
, ImplicitAddress address
)
442 DataLabelPtr label
= moveWithPatch(initialValue
, scratchRegister
);
443 storePtr(scratchRegister
, address
);
447 using MacroAssemblerX86Common::branchTest8
;
448 Jump
branchTest8(ResultCondition cond
, ExtendedAddress address
, TrustedImm32 mask
= TrustedImm32(-1))
450 TrustedImmPtr
addr(reinterpret_cast<void*>(address
.offset
));
451 MacroAssemblerX86Common::move(addr
, scratchRegister
);
452 return MacroAssemblerX86Common::branchTest8(cond
, BaseIndex(scratchRegister
, address
.base
, TimesOne
), mask
);
455 bool supportsFloatingPoint() const { return true; }
456 // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
457 bool supportsFloatingPointTruncate() const { return true; }
458 bool supportsFloatingPointSqrt() const { return true; }
461 friend class LinkBuffer
;
462 friend class RepatchBuffer
;
464 static void linkCall(void* code
, Call call
, FunctionPtr function
)
466 if (!call
.isFlagSet(Call::Near
))
467 X86Assembler::linkPointer(code
, call
.m_jmp
.labelAtOffset(-REPTACH_OFFSET_CALL_R11
), function
.value());
469 X86Assembler::linkCall(code
, call
.m_jmp
, function
.value());
472 static void repatchCall(CodeLocationCall call
, CodeLocationLabel destination
)
474 X86Assembler::repatchPointer(call
.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11
).dataLocation(), destination
.executableAddress());
477 static void repatchCall(CodeLocationCall call
, FunctionPtr destination
)
479 X86Assembler::repatchPointer(call
.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11
).dataLocation(), destination
.executableAddress());
486 #endif // ENABLE(ASSEMBLER)
488 #endif // MacroAssemblerX86_64_h