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::loadDouble
;
52 using MacroAssemblerX86Common::convertInt32ToDouble
;
54 void add32(Imm32 imm
, AbsoluteAddress address
)
56 move(ImmPtr(address
.m_ptr
), scratchRegister
);
57 add32(imm
, Address(scratchRegister
));
60 void and32(Imm32 imm
, AbsoluteAddress address
)
62 move(ImmPtr(address
.m_ptr
), scratchRegister
);
63 and32(imm
, Address(scratchRegister
));
66 void or32(Imm32 imm
, AbsoluteAddress address
)
68 move(ImmPtr(address
.m_ptr
), scratchRegister
);
69 or32(imm
, Address(scratchRegister
));
72 void sub32(Imm32 imm
, AbsoluteAddress address
)
74 move(ImmPtr(address
.m_ptr
), scratchRegister
);
75 sub32(imm
, Address(scratchRegister
));
78 void load32(void* address
, RegisterID dest
)
80 if (dest
== X86Registers::eax
)
81 m_assembler
.movl_mEAX(address
);
83 move(X86Registers::eax
, dest
);
84 m_assembler
.movl_mEAX(address
);
85 swap(X86Registers::eax
, dest
);
89 void loadDouble(const void* address
, FPRegisterID dest
)
91 move(ImmPtr(address
), scratchRegister
);
92 loadDouble(scratchRegister
, dest
);
95 void convertInt32ToDouble(AbsoluteAddress src
, FPRegisterID dest
)
97 move(Imm32(*static_cast<int32_t*>(src
.m_ptr
)), scratchRegister
);
98 m_assembler
.cvtsi2sd_rr(scratchRegister
, dest
);
101 void store32(Imm32 imm
, void* address
)
103 move(X86Registers::eax
, scratchRegister
);
104 move(imm
, X86Registers::eax
);
105 m_assembler
.movl_EAXm(address
);
106 move(scratchRegister
, X86Registers::eax
);
111 DataLabelPtr label
= moveWithPatch(ImmPtr(0), scratchRegister
);
112 Call result
= Call(m_assembler
.call(scratchRegister
), Call::Linkable
);
113 ASSERT(differenceBetween(label
, result
) == REPTACH_OFFSET_CALL_R11
);
117 Call
tailRecursiveCall()
119 DataLabelPtr label
= moveWithPatch(ImmPtr(0), scratchRegister
);
120 Jump newJump
= Jump(m_assembler
.jmp_r(scratchRegister
));
121 ASSERT(differenceBetween(label
, newJump
) == REPTACH_OFFSET_CALL_R11
);
122 return Call::fromTailJump(newJump
);
125 Call
makeTailRecursiveCall(Jump oldJump
)
128 DataLabelPtr label
= moveWithPatch(ImmPtr(0), scratchRegister
);
129 Jump newJump
= Jump(m_assembler
.jmp_r(scratchRegister
));
130 ASSERT(differenceBetween(label
, newJump
) == REPTACH_OFFSET_CALL_R11
);
131 return Call::fromTailJump(newJump
);
135 void addPtr(RegisterID src
, RegisterID dest
)
137 m_assembler
.addq_rr(src
, dest
);
140 void addPtr(Imm32 imm
, RegisterID srcDest
)
142 m_assembler
.addq_ir(imm
.m_value
, srcDest
);
145 void addPtr(ImmPtr imm
, RegisterID dest
)
147 move(imm
, scratchRegister
);
148 m_assembler
.addq_rr(scratchRegister
, dest
);
151 void addPtr(Imm32 imm
, RegisterID src
, RegisterID dest
)
153 m_assembler
.leaq_mr(imm
.m_value
, src
, dest
);
156 void addPtr(Imm32 imm
, Address address
)
158 m_assembler
.addq_im(imm
.m_value
, address
.offset
, address
.base
);
161 void addPtr(Imm32 imm
, AbsoluteAddress address
)
163 move(ImmPtr(address
.m_ptr
), scratchRegister
);
164 addPtr(imm
, Address(scratchRegister
));
167 void andPtr(RegisterID src
, RegisterID dest
)
169 m_assembler
.andq_rr(src
, dest
);
172 void andPtr(Imm32 imm
, RegisterID srcDest
)
174 m_assembler
.andq_ir(imm
.m_value
, srcDest
);
177 void orPtr(RegisterID src
, RegisterID dest
)
179 m_assembler
.orq_rr(src
, dest
);
182 void orPtr(ImmPtr imm
, RegisterID dest
)
184 move(imm
, scratchRegister
);
185 m_assembler
.orq_rr(scratchRegister
, dest
);
188 void orPtr(Imm32 imm
, RegisterID dest
)
190 m_assembler
.orq_ir(imm
.m_value
, dest
);
193 void subPtr(RegisterID src
, RegisterID dest
)
195 m_assembler
.subq_rr(src
, dest
);
198 void subPtr(Imm32 imm
, RegisterID dest
)
200 m_assembler
.subq_ir(imm
.m_value
, dest
);
203 void subPtr(ImmPtr imm
, RegisterID dest
)
205 move(imm
, scratchRegister
);
206 m_assembler
.subq_rr(scratchRegister
, dest
);
209 void xorPtr(RegisterID src
, RegisterID dest
)
211 m_assembler
.xorq_rr(src
, dest
);
214 void xorPtr(Imm32 imm
, RegisterID srcDest
)
216 m_assembler
.xorq_ir(imm
.m_value
, srcDest
);
220 void loadPtr(ImplicitAddress address
, RegisterID dest
)
222 m_assembler
.movq_mr(address
.offset
, address
.base
, dest
);
225 void loadPtr(BaseIndex address
, RegisterID dest
)
227 m_assembler
.movq_mr(address
.offset
, address
.base
, address
.index
, address
.scale
, dest
);
230 void loadPtr(void* address
, RegisterID dest
)
232 if (dest
== X86Registers::eax
)
233 m_assembler
.movq_mEAX(address
);
235 move(X86Registers::eax
, dest
);
236 m_assembler
.movq_mEAX(address
);
237 swap(X86Registers::eax
, dest
);
241 DataLabel32
loadPtrWithAddressOffsetPatch(Address address
, RegisterID dest
)
243 m_assembler
.movq_mr_disp32(address
.offset
, address
.base
, dest
);
244 return DataLabel32(this);
247 void storePtr(RegisterID src
, ImplicitAddress address
)
249 m_assembler
.movq_rm(src
, address
.offset
, address
.base
);
252 void storePtr(RegisterID src
, BaseIndex address
)
254 m_assembler
.movq_rm(src
, address
.offset
, address
.base
, address
.index
, address
.scale
);
257 void storePtr(RegisterID src
, void* address
)
259 if (src
== X86Registers::eax
)
260 m_assembler
.movq_EAXm(address
);
262 swap(X86Registers::eax
, src
);
263 m_assembler
.movq_EAXm(address
);
264 swap(X86Registers::eax
, src
);
268 void storePtr(ImmPtr imm
, ImplicitAddress address
)
270 move(imm
, scratchRegister
);
271 storePtr(scratchRegister
, address
);
274 DataLabel32
storePtrWithAddressOffsetPatch(RegisterID src
, Address address
)
276 m_assembler
.movq_rm_disp32(src
, address
.offset
, address
.base
);
277 return DataLabel32(this);
280 void movePtrToDouble(RegisterID src
, FPRegisterID dest
)
282 m_assembler
.movq_rr(src
, dest
);
285 void moveDoubleToPtr(FPRegisterID src
, RegisterID dest
)
287 m_assembler
.movq_rr(src
, dest
);
290 void setPtr(Condition cond
, RegisterID left
, Imm32 right
, RegisterID dest
)
292 if (((cond
== Equal
) || (cond
== NotEqual
)) && !right
.m_value
)
293 m_assembler
.testq_rr(left
, left
);
295 m_assembler
.cmpq_ir(right
.m_value
, left
);
296 m_assembler
.setCC_r(x86Condition(cond
), dest
);
297 m_assembler
.movzbl_rr(dest
, dest
);
300 Jump
branchPtr(Condition cond
, RegisterID left
, RegisterID right
)
302 m_assembler
.cmpq_rr(right
, left
);
303 return Jump(m_assembler
.jCC(x86Condition(cond
)));
306 Jump
branchPtr(Condition cond
, RegisterID left
, ImmPtr right
)
308 move(right
, scratchRegister
);
309 return branchPtr(cond
, left
, scratchRegister
);
312 Jump
branchPtr(Condition cond
, RegisterID left
, Address right
)
314 m_assembler
.cmpq_mr(right
.offset
, right
.base
, left
);
315 return Jump(m_assembler
.jCC(x86Condition(cond
)));
318 Jump
branchPtr(Condition cond
, AbsoluteAddress left
, RegisterID right
)
320 move(ImmPtr(left
.m_ptr
), scratchRegister
);
321 return branchPtr(cond
, Address(scratchRegister
), right
);
324 Jump
branchPtr(Condition cond
, Address left
, RegisterID right
)
326 m_assembler
.cmpq_rm(right
, left
.offset
, left
.base
);
327 return Jump(m_assembler
.jCC(x86Condition(cond
)));
330 Jump
branchPtr(Condition cond
, Address left
, ImmPtr right
)
332 move(right
, scratchRegister
);
333 return branchPtr(cond
, left
, scratchRegister
);
336 Jump
branchTestPtr(Condition cond
, RegisterID reg
, RegisterID mask
)
338 m_assembler
.testq_rr(reg
, mask
);
339 return Jump(m_assembler
.jCC(x86Condition(cond
)));
342 Jump
branchTestPtr(Condition cond
, RegisterID reg
, Imm32 mask
= Imm32(-1))
344 // if we are only interested in the low seven bits, this can be tested with a testb
345 if (mask
.m_value
== -1)
346 m_assembler
.testq_rr(reg
, reg
);
347 else if ((mask
.m_value
& ~0x7f) == 0)
348 m_assembler
.testb_i8r(mask
.m_value
, reg
);
350 m_assembler
.testq_i32r(mask
.m_value
, reg
);
351 return Jump(m_assembler
.jCC(x86Condition(cond
)));
354 Jump
branchTestPtr(Condition cond
, Address address
, Imm32 mask
= Imm32(-1))
356 if (mask
.m_value
== -1)
357 m_assembler
.cmpq_im(0, address
.offset
, address
.base
);
359 m_assembler
.testq_i32m(mask
.m_value
, address
.offset
, address
.base
);
360 return Jump(m_assembler
.jCC(x86Condition(cond
)));
363 Jump
branchTestPtr(Condition cond
, BaseIndex address
, Imm32 mask
= Imm32(-1))
365 if (mask
.m_value
== -1)
366 m_assembler
.cmpq_im(0, address
.offset
, address
.base
, address
.index
, address
.scale
);
368 m_assembler
.testq_i32m(mask
.m_value
, address
.offset
, address
.base
, address
.index
, address
.scale
);
369 return Jump(m_assembler
.jCC(x86Condition(cond
)));
373 Jump
branchAddPtr(Condition cond
, RegisterID src
, RegisterID dest
)
375 ASSERT((cond
== Overflow
) || (cond
== Zero
) || (cond
== NonZero
));
377 return Jump(m_assembler
.jCC(x86Condition(cond
)));
380 Jump
branchSubPtr(Condition cond
, Imm32 imm
, RegisterID dest
)
382 ASSERT((cond
== Overflow
) || (cond
== Zero
) || (cond
== NonZero
));
384 return Jump(m_assembler
.jCC(x86Condition(cond
)));
387 DataLabelPtr
moveWithPatch(ImmPtr initialValue
, RegisterID dest
)
389 m_assembler
.movq_i64r(initialValue
.asIntptr(), dest
);
390 return DataLabelPtr(this);
393 Jump
branchPtrWithPatch(Condition cond
, RegisterID left
, DataLabelPtr
& dataLabel
, ImmPtr initialRightValue
= ImmPtr(0))
395 dataLabel
= moveWithPatch(initialRightValue
, scratchRegister
);
396 return branchPtr(cond
, left
, scratchRegister
);
399 Jump
branchPtrWithPatch(Condition cond
, Address left
, DataLabelPtr
& dataLabel
, ImmPtr initialRightValue
= ImmPtr(0))
401 dataLabel
= moveWithPatch(initialRightValue
, scratchRegister
);
402 return branchPtr(cond
, left
, scratchRegister
);
405 DataLabelPtr
storePtrWithPatch(ImmPtr initialValue
, ImplicitAddress address
)
407 DataLabelPtr label
= moveWithPatch(initialValue
, scratchRegister
);
408 storePtr(scratchRegister
, address
);
412 using MacroAssemblerX86Common::branchTest8
;
413 Jump
branchTest8(Condition cond
, ExtendedAddress address
, Imm32 mask
= Imm32(-1))
415 ImmPtr
addr(reinterpret_cast<void*>(address
.offset
));
416 MacroAssemblerX86Common::move(addr
, scratchRegister
);
417 return MacroAssemblerX86Common::branchTest8(cond
, BaseIndex(scratchRegister
, address
.base
, TimesOne
), mask
);
420 Label
loadPtrWithPatchToLEA(Address address
, RegisterID dest
)
423 loadPtr(address
, dest
);
427 bool supportsFloatingPoint() const { return true; }
428 // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
429 bool supportsFloatingPointTruncate() const { return true; }
430 bool supportsFloatingPointSqrt() const { return true; }
433 friend class LinkBuffer
;
434 friend class RepatchBuffer
;
436 static void linkCall(void* code
, Call call
, FunctionPtr function
)
438 if (!call
.isFlagSet(Call::Near
))
439 X86Assembler::linkPointer(code
, X86Assembler::labelFor(call
.m_jmp
, -REPTACH_OFFSET_CALL_R11
), function
.value());
441 X86Assembler::linkCall(code
, call
.m_jmp
, function
.value());
444 static void repatchCall(CodeLocationCall call
, CodeLocationLabel destination
)
446 X86Assembler::repatchPointer(call
.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11
).dataLocation(), destination
.executableAddress());
449 static void repatchCall(CodeLocationCall call
, FunctionPtr destination
)
451 X86Assembler::repatchPointer(call
.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11
).dataLocation(), destination
.executableAddress());
458 #endif // ENABLE(ASSEMBLER)
460 #endif // MacroAssemblerX86_64_h